Skip to content

Commit

Permalink
feat: ConfigProvider support locale (ant-design#17816)
Browse files Browse the repository at this point in the history
* ConfigProvider support locale

* update docs

* update category

* clean up

* moving locale

* update check script

* update related code

* add test case

* demo link

* update doc

* hide one rule of md with eslint

* update error link
  • Loading branch information
zombieJ authored Jul 24, 2019
1 parent 161def0 commit 81d8eb8
Show file tree
Hide file tree
Showing 123 changed files with 2,548 additions and 2,101 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2012,7 +2012,7 @@ timeline: true

```javascript
import { LocaleProvider } from 'antd';
import zhCN from 'antd/lib/locale-provider/zh_CN';
import zhCN from 'antd/lib/locale/zh_CN';

ReactDOM.render(
<LocaleProvider locale={zhCN}>
Expand Down
7 changes: 6 additions & 1 deletion components/_util/warning.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import warning from 'warning';

const warned: Record<string, boolean> = {};
let warned: Record<string, boolean> = {};

export function resetWarned() {
warned = {};
}

export default (valid: boolean, component: string, message: string): void => {
if (!valid && !warned[message]) {
warning(false, `[antd: ${component}] ${message}`);
Expand Down
187 changes: 187 additions & 0 deletions components/config-provider/demo/locale.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
---
order: 1
title:
zh-CN: 国际化
en-US: Locale
---

## zh-CN

此处列出 Ant Design 中需要国际化支持的组件,你可以在演示里切换语言。

## en-US

Components which need localization support are listed here, you can toggle the language in the demo.

```jsx
import {
ConfigProvider,
Pagination,
DatePicker,
TimePicker,
Calendar,
Popconfirm,
Table,
Modal,
Button,
Select,
Transfer,
Radio,
} from 'antd';
import zhCN from 'antd/lib/locale/zh_CN';
import moment from 'moment';
import 'moment/locale/zh-cn';

moment.locale('en');

const { Option } = Select;
const { RangePicker } = DatePicker;

const columns = [
{
title: 'Name',
dataIndex: 'name',
filters: [
{
text: 'filter1',
value: 'filter1',
},
],
},
{
title: 'Age',
dataIndex: 'age',
},
];

class Page extends React.Component {
state = {
visible: false,
};

showModal = () => {
this.setState({ visible: true });
};

hideModal = () => {
this.setState({ visible: false });
};

render() {
const info = () => {
Modal.info({
title: 'some info',
content: 'some info',
});
};
const confirm = () => {
Modal.confirm({
title: 'some info',
content: 'some info',
});
};
return (
<div className="locale-components">
<div className="example">
<Pagination defaultCurrent={1} total={50} showSizeChanger />
</div>
<div className="example">
<Select showSearch style={{ width: 200 }}>
<Option value="jack">jack</Option>
<Option value="lucy">lucy</Option>
</Select>
<DatePicker />
<TimePicker />
<RangePicker style={{ width: 200 }} />
</div>
<div className="example">
<Button type="primary" onClick={this.showModal}>
Show Modal
</Button>
<Button onClick={info}>Show info</Button>
<Button onClick={confirm}>Show confirm</Button>
<Popconfirm title="Question?">
<a href="#">Click to confirm</a>
</Popconfirm>
</div>
<div className="example">
<Transfer dataSource={[]} showSearch targetKeys={[]} render={item => item.title} />
</div>
<div style={{ width: 319, border: '1px solid #d9d9d9', borderRadius: 4 }}>
<Calendar fullscreen={false} value={moment()} />
</div>
<div className="example">
<Table dataSource={[]} columns={columns} />
</div>
<Modal title="Locale Modal" visible={this.state.visible} onCancel={this.hideModal}>
<p>Locale Modal</p>
</Modal>
</div>
);
}
}

class App extends React.Component {
constructor() {
super();
this.state = {
locale: null,
};
}

changeLocale = e => {
const localeValue = e.target.value;
this.setState({ locale: localeValue });
if (!localeValue) {
moment.locale('en');
} else {
moment.locale('zh-cn');
}
};

render() {
const { locale } = this.state;
return (
<div>
<div className="change-locale">
<span style={{ marginRight: 16 }}>Change locale of components: </span>
<Radio.Group defaultValue={undefined} onChange={this.changeLocale}>
<Radio.Button key="en" value={undefined}>
English
</Radio.Button>
<Radio.Button key="cn" value={zhCN}>
中文
</Radio.Button>
</Radio.Group>
</div>
<ConfigProvider locale={locale}>
<Page
key={locale ? locale.locale : 'en' /* Have to refresh for production environment */}
/>
</ConfigProvider>
</div>
);
}
}

ReactDOM.render(<App />, mountNode);
```

```css
.locale-components {
border-top: 1px solid #d9d9d9;
padding-top: 16px;
}

.example {
margin: 16px 0;
}

.example > * {
margin-right: 8px;
}

.change-locale {
margin-bottom: 16px;
}
```
1 change: 1 addition & 0 deletions components/config-provider/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ Some component use dynamic style to support wave effect. You can config `csp` pr
| csp | Set [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) config | { nonce: string } | - | 3.13.1 |
| renderEmpty | set empty content of components. Ref [Empty](/components/empty/) | Function(componentName: string): ReactNode | - | 3.12.2 |
| getPopupContainer | to set the container of the popup element. The default is to create a `div` element in `body`. | Function(triggerNode) | `() => document.body` | 3.11.0 |
| locale | language package setting, you can find the packages in [antd/es/locale](http://unpkg.com/antd/es/locale/) | object | 3.21.0 |
| prefixCls | set prefix class | string | ant | 3.12.0 |
21 changes: 19 additions & 2 deletions components/config-provider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import createReactContext from '@ant-design/create-react-context';

import defaultRenderEmpty, { RenderEmptyHandler } from './renderEmpty';
import LocaleProvider, { Locale, ANT_MARK } from '../locale-provider';

export { RenderEmptyHandler };

Expand All @@ -16,6 +17,7 @@ export interface ConfigConsumerProps {
renderEmpty: RenderEmptyHandler;
csp?: CSPConfig;
autoInsertSpaceInButton?: boolean;
locale?: Locale;
}

export const configConsumerProps = [
Expand All @@ -25,6 +27,7 @@ export const configConsumerProps = [
'renderEmpty',
'csp',
'autoInsertSpaceInButton',
'locale',
];

export interface ConfigProviderProps {
Expand All @@ -34,6 +37,7 @@ export interface ConfigProviderProps {
renderEmpty?: RenderEmptyHandler;
csp?: CSPConfig;
autoInsertSpaceInButton?: boolean;
locale?: Locale;
}

const ConfigContext = createReactContext<ConfigConsumerProps>({
Expand All @@ -59,7 +63,14 @@ class ConfigProvider extends React.Component<ConfigProviderProps> {
};

renderProvider = (context: ConfigConsumerProps) => {
const { children, getPopupContainer, renderEmpty, csp, autoInsertSpaceInButton } = this.props;
const {
children,
getPopupContainer,
renderEmpty,
csp,
autoInsertSpaceInButton,
locale,
} = this.props;

const config: ConfigConsumerProps = {
...context,
Expand All @@ -75,7 +86,13 @@ class ConfigProvider extends React.Component<ConfigProviderProps> {
config.renderEmpty = renderEmpty;
}

return <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>;
return (
<ConfigContext.Provider value={config}>
<LocaleProvider locale={locale} _ANT_MARK__={ANT_MARK}>
{children}
</LocaleProvider>
</ConfigContext.Provider>
);
};

render() {
Expand Down
1 change: 1 addition & 0 deletions components/config-provider/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ return (
| csp | 设置 [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) 配置 | { nonce: string } | - | 3.13.1 |
| renderEmpty | 自定义组件空状态。参考 [空状态](/components/empty/) | Function(componentName: string): ReactNode | - | 3.12.2 |
| getPopupContainer | 弹出框(Select, Tooltip, Menu 等等)渲染父节点,默认渲染到 body 上。 | Function(triggerNode) | () => document.body | 3.11.0 |
| locale | 语言包配置,语言包可到 [antd/es/locale](http://unpkg.com/antd/es/locale/) 目录下寻找 | object | - | 3.21.0 |
| prefixCls | 设置统一样式前缀 | string | ant | 3.12.0 |
2 changes: 1 addition & 1 deletion components/date-picker/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ There are four kinds of picker:

### Localization

The default locale is en-US, if you need to use other languages, recommend to use internationalized components provided by us at the entrance. Look at: [LocaleProvider](http://ant.design/components/locale-provider/).
The default locale is en-US, if you need to use other languages, recommend to use internationalized components provided by us at the entrance. Look at: [ConfigProvider](http://ant.design/components/config-provider/).

If there are special needs (only modifying single component language), Please use the property: local. Example: [default](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json).

Expand Down
2 changes: 1 addition & 1 deletion components/date-picker/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ subtitle: 日期选择框

### 国际化配置

默认配置为 en-US,如果你需要设置其他语言,推荐在入口处使用我们提供的国际化组件,详见:[LocaleProvider 国际化](http://ant.design/components/locale-provider-cn/)
默认配置为 en-US,如果你需要设置其他语言,推荐在入口处使用我们提供的国际化组件,详见:[ConfigProvider 国际化](http://ant.design/components/config-provider-cn/)

如有特殊需求(仅修改单一组件的语言),请使用 locale 参数,参考:[默认配置](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json)

Expand Down
17 changes: 17 additions & 0 deletions components/locale-provider/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import { mount } from 'enzyme';
import moment from 'moment';
import MockDate from 'mockdate';
import { resetWarned } from '../../_util/warning';
import {
LocaleProvider,
Pagination,
Expand Down Expand Up @@ -231,4 +232,20 @@ describe('Locale Provider', () => {
wrapper.setState({ locale: null });
expect(wrapper.render()).toMatchSnapshot();
});

it('warning if use LocaleProvider', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
resetWarned();

mount(
<LocaleProvider locale={{}}>
<div />
</LocaleProvider>,
);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: LocaleProvider] `LocaleProvider` is deprecated. Please use `locale` with `ConfigProvider` instead: http://u.ant.design/locale',
);

errorSpy.mockRestore();
});
});
43 changes: 2 additions & 41 deletions components/locale-provider/ar_EG.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,3 @@
import Pagination from 'rc-pagination/lib/locale/ar_EG';
import DatePicker from '../date-picker/locale/ar_EG';
import TimePicker from '../time-picker/locale/ar_EG';
import Calendar from '../calendar/locale/ar_EG';
import locale from '../locale/ar_EG';

export default {
locale: 'ar',
Pagination,
DatePicker,
TimePicker,
Calendar,
Table: {
filterTitle: 'الفلاتر',
filterConfirm: 'تأكيد',
filterReset: 'إعادة ضبط',
selectAll: 'اختيار الكل',
selectInvert: 'إلغاء الاختيار',
},
Modal: {
okText: 'تأكيد',
cancelText: 'إلغاء',
justOkText: 'تأكيد',
},
Popconfirm: {
okText: 'تأكيد',
cancelText: 'إلغاء',
},
Transfer: {
searchPlaceholder: 'ابحث هنا',
itemUnit: 'عنصر',
itemsUnit: 'عناصر',
},
Upload: {
uploading: 'جاري الرفع...',
removeFile: 'احذف الملف',
uploadError: 'مشكلة فى الرفع',
previewFile: 'استعرض الملف',
},
Empty: {
description: 'لا توجد بيانات',
},
};
export default locale;
Loading

0 comments on commit 81d8eb8

Please sign in to comment.