Commit d33b51432d8c13900f1062d84860fb0082780804
1 parent
86b4da54
support i18n
support i18n
Showing
10 changed files
with
151 additions
and
15 deletions
Show diff stats
package.json
@@ -40,6 +40,7 @@ | @@ -40,6 +40,7 @@ | ||
40 | "dependencies": { | 40 | "dependencies": { |
41 | "async-validator": "^1.6.7", | 41 | "async-validator": "^1.6.7", |
42 | "core-js": "^2.4.1", | 42 | "core-js": "^2.4.1", |
43 | + "deepmerge": "^1.3.1", | ||
43 | "popper.js": "^0.6.4" | 44 | "popper.js": "^0.6.4" |
44 | }, | 45 | }, |
45 | "peerDependencies": { | 46 | "peerDependencies": { |
src/components/select/select.vue
@@ -35,6 +35,7 @@ | @@ -35,6 +35,7 @@ | ||
35 | import Dropdown from './dropdown.vue'; | 35 | import Dropdown from './dropdown.vue'; |
36 | import clickoutside from '../../directives/clickoutside'; | 36 | import clickoutside from '../../directives/clickoutside'; |
37 | import { oneOf, MutationObserver } from '../../utils/assist'; | 37 | import { oneOf, MutationObserver } from '../../utils/assist'; |
38 | + import { t } from '../../locale'; | ||
38 | 39 | ||
39 | const prefixCls = 'ivu-select'; | 40 | const prefixCls = 'ivu-select'; |
40 | 41 | ||
@@ -60,7 +61,9 @@ | @@ -60,7 +61,9 @@ | ||
60 | }, | 61 | }, |
61 | placeholder: { | 62 | placeholder: { |
62 | type: String, | 63 | type: String, |
63 | - default: '请选择' | 64 | + default () { |
65 | + return t('i.select.placeholder'); | ||
66 | + } | ||
64 | }, | 67 | }, |
65 | filterable: { | 68 | filterable: { |
66 | type: Boolean, | 69 | type: Boolean, |
@@ -80,7 +83,9 @@ | @@ -80,7 +83,9 @@ | ||
80 | }, | 83 | }, |
81 | notFoundText: { | 84 | notFoundText: { |
82 | type: String, | 85 | type: String, |
83 | - default: '无匹配数据' | 86 | + default () { |
87 | + return t('i.select.noMatch'); | ||
88 | + } | ||
84 | } | 89 | } |
85 | }, | 90 | }, |
86 | data () { | 91 | data () { |
src/index.js
@@ -40,6 +40,7 @@ import Tooltip from './components/tooltip'; | @@ -40,6 +40,7 @@ import Tooltip from './components/tooltip'; | ||
40 | import Transfer from './components/transfer'; | 40 | import Transfer from './components/transfer'; |
41 | import { Row, Col } from './components/layout'; | 41 | import { Row, Col } from './components/layout'; |
42 | import { Select, Option, OptionGroup } from './components/select'; | 42 | import { Select, Option, OptionGroup } from './components/select'; |
43 | +import locale from './locale'; | ||
43 | 44 | ||
44 | const iview = { | 45 | const iview = { |
45 | Affix, | 46 | Affix, |
@@ -100,7 +101,10 @@ const iview = { | @@ -100,7 +101,10 @@ const iview = { | ||
100 | Transfer | 101 | Transfer |
101 | }; | 102 | }; |
102 | 103 | ||
103 | -const install = function (Vue) { | 104 | +const install = function (Vue, opts = {}) { |
105 | + locale.use(opts.locale); | ||
106 | + locale.i18n(opts.i18n); | ||
107 | + | ||
104 | Object.keys(iview).forEach((key) => { | 108 | Object.keys(iview).forEach((key) => { |
105 | Vue.component(key, iview[key]); | 109 | Vue.component(key, iview[key]); |
106 | }); | 110 | }); |
1 | +/** | ||
2 | + * String format template | ||
3 | + * - Inspired: | ||
4 | + * https://github.com/Matt-Esch/string-template/index.js | ||
5 | + */ | ||
6 | + | ||
7 | +const RE_NARGS = /(%|)\{([0-9a-zA-Z_]+)\}/g; | ||
8 | + | ||
9 | +export default function(Vue) { | ||
10 | + const { hasOwn } = Vue.util; | ||
11 | + | ||
12 | + /** | ||
13 | + * template | ||
14 | + * | ||
15 | + * @param {String} string | ||
16 | + * @param {Array} ...args | ||
17 | + * @return {String} | ||
18 | + */ | ||
19 | + | ||
20 | + function template(string, ...args) { | ||
21 | + if (args.length === 1 && typeof args[0] === 'object') { | ||
22 | + args = args[0]; | ||
23 | + } | ||
24 | + | ||
25 | + if (!args || !args.hasOwnProperty) { | ||
26 | + args = {}; | ||
27 | + } | ||
28 | + | ||
29 | + return string.replace(RE_NARGS, (match, prefix, i, index) => { | ||
30 | + let result; | ||
31 | + | ||
32 | + if (string[index - 1] === '{' && | ||
33 | + string[index + match.length] === '}') { | ||
34 | + return i; | ||
35 | + } else { | ||
36 | + result = hasOwn(args, i) ? args[i] : null; | ||
37 | + if (result === null || result === undefined) { | ||
38 | + return ''; | ||
39 | + } | ||
40 | + | ||
41 | + return result; | ||
42 | + } | ||
43 | + }); | ||
44 | + } | ||
45 | + | ||
46 | + return template; | ||
47 | +} |
1 | +// https://github.com/ElemeFE/element/blob/dev/src/locale/index.js | ||
2 | + | ||
3 | +import defaultLang from './lang/zh-CN'; | ||
4 | +import Vue from 'vue'; | ||
5 | +import deepmerge from 'deepmerge'; | ||
6 | +import Format from './format'; | ||
7 | + | ||
8 | +const format = Format(Vue); | ||
9 | +let lang = defaultLang; | ||
10 | +let merged = false; | ||
11 | +let i18nHandler = function() { | ||
12 | + const vuei18n = Object.getPrototypeOf(this || Vue).$t; | ||
13 | + if (typeof vuei18n === 'function') { | ||
14 | + if (!merged) { | ||
15 | + merged = true; | ||
16 | + Vue.locale( | ||
17 | + Vue.config.lang, | ||
18 | + deepmerge(lang, Vue.locale(Vue.config.lang) || {}, { clone: true }) | ||
19 | + ); | ||
20 | + } | ||
21 | + return vuei18n.apply(this, arguments); | ||
22 | + } | ||
23 | +}; | ||
24 | + | ||
25 | +export const t = function(path, options) { | ||
26 | + let value = i18nHandler.apply(this, arguments); | ||
27 | + if (value !== null && value !== undefined) return value; | ||
28 | + | ||
29 | + const array = path.split('.'); | ||
30 | + let current = lang; | ||
31 | + | ||
32 | + for (let i = 0, j = array.length; i < j; i++) { | ||
33 | + const property = array[i]; | ||
34 | + value = current[property]; | ||
35 | + if (i === j - 1) return format(value, options); | ||
36 | + if (!value) return ''; | ||
37 | + current = value; | ||
38 | + } | ||
39 | + return ''; | ||
40 | +}; | ||
41 | + | ||
42 | +export const use = function(l) { | ||
43 | + lang = l || lang; | ||
44 | +}; | ||
45 | + | ||
46 | +export const i18n = function(fn) { | ||
47 | + i18nHandler = fn || i18nHandler; | ||
48 | +}; | ||
49 | + | ||
50 | +export default { use, t, i18n }; | ||
0 | \ No newline at end of file | 51 | \ No newline at end of file |
test/main.js
@@ -5,9 +5,10 @@ import Vue from 'vue'; | @@ -5,9 +5,10 @@ import Vue from 'vue'; | ||
5 | import VueRouter from 'vue-router'; | 5 | import VueRouter from 'vue-router'; |
6 | import App from './app.vue'; | 6 | import App from './app.vue'; |
7 | import iView from '../src/index'; | 7 | import iView from '../src/index'; |
8 | +import locale from '../src/locale/lang/en-US'; | ||
8 | 9 | ||
9 | Vue.use(VueRouter); | 10 | Vue.use(VueRouter); |
10 | -Vue.use(iView); | 11 | +Vue.use(iView, { locale }); |
11 | 12 | ||
12 | // 开启debug模式 | 13 | // 开启debug模式 |
13 | Vue.config.debug = true; | 14 | Vue.config.debug = true; |
test/routers/select.vue
@@ -2,12 +2,12 @@ | @@ -2,12 +2,12 @@ | ||
2 | <Row> | 2 | <Row> |
3 | <i-col span="12" style="padding-right:10px"> | 3 | <i-col span="12" style="padding-right:10px"> |
4 | <i-select :model.sync="model11" filterable> | 4 | <i-select :model.sync="model11" filterable> |
5 | - <i-option v-for="item in cityList" :value="item.value" :label="item.label"><span>{{ item.label }}</span><span>{{ item.des }}</span></i-option> | 5 | + <i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option> |
6 | </i-select> | 6 | </i-select> |
7 | </i-col> | 7 | </i-col> |
8 | <i-col span="12"> | 8 | <i-col span="12"> |
9 | <i-select :model.sync="model12" filterable multiple> | 9 | <i-select :model.sync="model12" filterable multiple> |
10 | - <i-option v-for="item in cityList" :value="item.value" :label="item.label"><span>{{ item.label }}</span><span>{{ item.des }}</span></i-option> | 10 | + <i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option> |
11 | </i-select> | 11 | </i-select> |
12 | </i-col> | 12 | </i-col> |
13 | </Row> | 13 | </Row> |
@@ -19,27 +19,31 @@ | @@ -19,27 +19,31 @@ | ||
19 | cityList: [ | 19 | cityList: [ |
20 | { | 20 | { |
21 | value: 'beijing', | 21 | value: 'beijing', |
22 | - label: '北京市', | ||
23 | - des: '帝都' | 22 | + label: '北京市' |
24 | }, | 23 | }, |
25 | { | 24 | { |
26 | value: 'shanghai', | 25 | value: 'shanghai', |
27 | - label: '上海市', | ||
28 | - des: '魔都' | 26 | + label: '上海市' |
29 | }, | 27 | }, |
30 | { | 28 | { |
31 | value: 'shenzhen', | 29 | value: 'shenzhen', |
32 | - label: '深圳市', | ||
33 | - des: '渔村' | 30 | + label: '深圳市' |
31 | + }, | ||
32 | + { | ||
33 | + value: 'hangzhou', | ||
34 | + label: '杭州市' | ||
35 | + }, | ||
36 | + { | ||
37 | + value: 'nanjing', | ||
38 | + label: '南京市' | ||
34 | }, | 39 | }, |
35 | { | 40 | { |
36 | value: 'chongqing', | 41 | value: 'chongqing', |
37 | - label: '重庆市', | ||
38 | - des: '山城' | 42 | + label: '重庆市' |
39 | } | 43 | } |
40 | ], | 44 | ], |
41 | model11: '', | 45 | model11: '', |
42 | - model12: ['beijing', 'shanghai'] | 46 | + model12: [] |
43 | } | 47 | } |
44 | } | 48 | } |
45 | } | 49 | } |