Support for dynamically loading language packs.

Load the `lodash` function as needed.
Added i18n related configuration.
This commit is contained in:
zuiidea
2018-09-15 12:26:22 +08:00
parent 8aa55330b4
commit 7c83c80d5d
10 changed files with 135 additions and 62 deletions
+2
View File
@@ -2,3 +2,5 @@ src/**/*-test.js
src/public
src/routes/chart/ECharts/theme
src/routes/chart/highCharts/mapdata
src/locales/_build/
src/locales/**/*.js
+2 -1
View File
@@ -17,4 +17,5 @@ yarn-error.log
.umi-production
# jslingui
src/locales/_build
src/locales/_build
src/locales/**/*.js
+16 -1
View File
@@ -1,5 +1,6 @@
// https://umijs.org/config/
import { resolve } from 'path'
import { i18n } from './src/utils/config'
export default {
plugins: [
@@ -27,16 +28,21 @@ export default {
/chart\/Recharts\/Container\.js$/,
],
update: routes => {
if (!i18n) return routes
const newRoutes = []
for (const item of routes[0].routes) {
newRoutes.push(item)
if (item.path) {
newRoutes.push(
Object.assign({}, item, { path: '/:lang(en|zh)' + item.path })
Object.assign({}, item, {
path: `/:lang(${i18n.languages.join('|')})` + item.path,
})
)
}
}
routes[0].routes = newRoutes
return routes
},
},
@@ -91,5 +97,14 @@ export default {
},
'ant-design-pro',
],
[
'import',
{
libraryName: 'lodash',
libraryDirectory: '',
camel2DashComponentName: false,
},
'lodash',
],
],
}
+2 -3
View File
@@ -21,9 +21,7 @@
"eslint-plugin-flowtype": "^2.50.0",
"highcharts-exporting": "^0.1.7",
"highcharts-more": "^0.1.7",
"lodash.clonedeep": "^4.5.0",
"lodash.isempty": "^4.4.0",
"lodash.isequal": "^4.5.0",
"lodash": "^4.17.11",
"nprogress": "^0.2.0",
"path-to-regexp": "^2.4.0",
"prop-types": "^15.6.2",
@@ -39,6 +37,7 @@
"devDependencies": {
"@lingui/babel-preset-react": "^2.7.0",
"@lingui/cli": "^2.7.0",
"@lingui/loader": "^2.7.0",
"babel-plugin-dev-expression": "^0.2.1",
"babel-plugin-import": "^1.8.0",
"babel-plugin-macros": "^2.4.0",
+51 -6
View File
@@ -1,25 +1,70 @@
import React, { PureComponent } from 'react'
import React, { Component } from 'react'
import withRouter from 'umi/withRouter'
import { LocaleProvider } from 'antd'
import { I18nProvider } from '@lingui/react'
import { catalogs, langFromPath } from 'utils/i18n'
import { langFromPath, defaultLanguage } from 'utils'
import zh_CN from 'antd/lib/locale-provider/zh_CN'
import en_US from 'antd/lib/locale-provider/en_US'
import BaseLayout from './BaseLayout'
const languages = {
zh: zh_CN,
en: en_US,
}
@withRouter
class Layout extends PureComponent {
class Layout extends Component {
state = {
catalogs: {},
}
language = defaultLanguage
componentDidMount() {
const language = langFromPath(this.props.location.pathname)
this.language = language
this.loadCatalog(language)
}
shouldComponentUpdate(nextProps, nextState) {
const language = langFromPath(nextProps.location.pathname)
const preLanguage = this.language
const { catalogs } = nextState
if (preLanguage !== language && !catalogs[language]) {
this.loadCatalog(language)
this.language = language
return false
}
this.language = language
return true
}
loadCatalog = async language => {
const catalog = await import(/* webpackMode: "lazy", webpackChunkName: "i18n-[index]" */
`@lingui/loader!../locales/${language}/messages.json`)
this.setState(state => ({
catalogs: {
...state.catalogs,
[language]: catalog,
},
}))
}
render() {
const { location, children } = this.props
const lang = langFromPath(location.pathname)
const { catalogs } = this.state
let language = langFromPath(location.pathname)
// If the language pack is not loaded or is loading, use the default language
if (!catalogs[language]) language = defaultLanguage
return (
<LocaleProvider locale={languages[lang]}>
<I18nProvider language={lang} catalogs={catalogs}>
<LocaleProvider locale={languages[language]}>
<I18nProvider language={language} catalogs={catalogs}>
<BaseLayout>{children}</BaseLayout>
</I18nProvider>
</LocaleProvider>
+8
View File
@@ -6,6 +6,8 @@ module.exports = {
logoPath: '/logo.svg',
apiPrefix: '/api/v1',
openPages: ['/login'],
/* Layout configuration, specify which layout to use for route. */
layouts: [
{
name: 'primary',
@@ -13,4 +15,10 @@ module.exports = {
exlude: [/(\/(en|zh))*\/login/],
},
],
/* I18n configuration, `languages` and `defaultLanguage` are required currently. */
i18n: {
languages: ['en', 'zh'],
defaultLanguage: 'en',
},
}
-42
View File
@@ -1,42 +0,0 @@
const catalogs = {
en: { messages: require('../locales/en/messages.json') },
zh: { messages: require('../locales/zh/messages.json') },
}
const defaultLanguage = 'en'
const languages = []
for (const key in catalogs) {
languages.push(key)
}
/**
* Remove the language prefix in pathname.
* @param {string} pathname Remove the language prefix in pathname.
* @return {string} Return the pathname after removing the language prefix.
*/
const deLangPrefix = pathname => {
for (const item of languages) {
if (pathname.startsWith(`/${item}/`)) {
return pathname.replace(`/${item}/`, '/')
}
}
return pathname
}
/**
* Query language from pathname.
* @param {string} pathname Pathname to be queried.
* @return {string} Return the queryed language.
*/
const langFromPath = pathname => {
for (const item of languages) {
if (pathname.startsWith(`/${item}/`)) {
return item
}
}
return defaultLanguage
}
export { languages, catalogs, langFromPath, deLangPrefix, defaultLanguage }
+42 -1
View File
@@ -1,10 +1,13 @@
import cloneDeep from 'lodash.clonedeep'
import { cloneDeep, curry } from 'lodash'
import { i18n } from './config'
export classnames from 'classnames'
export config from './config'
export request from './request'
export { Color } from './theme'
const { languages, defaultLanguage } = i18n
/**
* Query objects that specify keys and values in an array where all values are objects.
* @param {array} array An array where all values are objects, like [{key:1},{key:2}].
@@ -56,3 +59,41 @@ export function arrayToTree(
})
return result
}
const langFromPath = curry(
/**
* Query language from pathname.
* @param {string} languages Specify which languages are currently available.
* @param {string} defaultLanguage Specify the default language.
* @param {string} pathname Pathname to be queried.
* @return {string} Return the queryed language.
*/
(languages, defaultLanguage, pathname) => {
for (const item of languages) {
if (pathname.startsWith(`/${item}/`)) {
return item
}
}
return defaultLanguage
}
)(languages)(defaultLanguage)
const deLangPrefix = curry(
/**
* Remove the language prefix in pathname.
* @param {array} languages Specify which languages are currently available.
* @param {string} pathname Remove the language prefix in pathname.
* @return {string} Return the pathname after removing the language prefix.
*/
(languages, pathname) => {
for (const item of languages) {
if (pathname.startsWith(`/${item}/`)) {
return pathname.replace(`/${item}/`, '/')
}
}
return pathname
}
)(languages)
export { langFromPath, deLangPrefix, defaultLanguage }
+1 -2
View File
@@ -1,6 +1,5 @@
import axios from 'axios'
import cloneDeep from 'lodash.clonedeep'
import isEmpty from 'lodash.isempty'
import { cloneDeep, isEmpty } from 'lodash'
import pathToRegexp from 'path-to-regexp'
import { message } from 'antd'
import qs from 'qs'
+11 -6
View File
@@ -908,7 +908,7 @@
"@lingui/babel-plugin-transform-js" "2.7.0"
"@lingui/babel-plugin-transform-react" "2.7.0"
"@lingui/cli@^2.7.0":
"@lingui/cli@2.7.0", "@lingui/cli@^2.7.0":
version "2.7.0"
resolved "https://registry.yarnpkg.com/@lingui/cli/-/cli-2.7.0.tgz#04137f770f148f17eb78bb6580e91eac7697b955"
dependencies:
@@ -957,6 +957,15 @@
make-plural "^4.1.1"
messageformat-parser "^2.0.0"
"@lingui/loader@^2.7.0":
version "2.7.0"
resolved "https://registry.yarnpkg.com/@lingui/loader/-/loader-2.7.0.tgz#a9092f16f909ee94616f58f6d5e163e6305883f5"
dependencies:
"@lingui/cli" "2.7.0"
"@lingui/conf" "2.7.0"
babel-runtime "^6.26.0"
ramda "^0.25.0"
"@lingui/react@^2.7.0":
version "2.7.0"
resolved "https://registry.yarnpkg.com/@lingui/react/-/react-2.7.0.tgz#36a2e905ab6a7f39798dedee2bd4a2b8e98335a9"
@@ -7306,10 +7315,6 @@ lodash.isarray@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
lodash.isempty@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e"
lodash.isequal@^4.0.0, lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
@@ -7398,7 +7403,7 @@ lodash.uniq@^4.5.0:
version "4.17.10"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
lodash@^4.11.1:
lodash@^4.11.1, lodash@^4.17.11:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"