Commit d33b51432d8c13900f1062d84860fb0082780804
1 parent
86b4da54
support i18n
support i18n
Showing
10 changed files
with
151 additions
and
15 deletions
Show diff stats
package.json
src/components/select/select.vue
| ... | ... | @@ -35,6 +35,7 @@ |
| 35 | 35 | import Dropdown from './dropdown.vue'; |
| 36 | 36 | import clickoutside from '../../directives/clickoutside'; |
| 37 | 37 | import { oneOf, MutationObserver } from '../../utils/assist'; |
| 38 | + import { t } from '../../locale'; | |
| 38 | 39 | |
| 39 | 40 | const prefixCls = 'ivu-select'; |
| 40 | 41 | |
| ... | ... | @@ -60,7 +61,9 @@ |
| 60 | 61 | }, |
| 61 | 62 | placeholder: { |
| 62 | 63 | type: String, |
| 63 | - default: '请选择' | |
| 64 | + default () { | |
| 65 | + return t('i.select.placeholder'); | |
| 66 | + } | |
| 64 | 67 | }, |
| 65 | 68 | filterable: { |
| 66 | 69 | type: Boolean, |
| ... | ... | @@ -80,7 +83,9 @@ |
| 80 | 83 | }, |
| 81 | 84 | notFoundText: { |
| 82 | 85 | type: String, |
| 83 | - default: '无匹配数据' | |
| 86 | + default () { | |
| 87 | + return t('i.select.noMatch'); | |
| 88 | + } | |
| 84 | 89 | } |
| 85 | 90 | }, |
| 86 | 91 | data () { | ... | ... |
src/index.js
| ... | ... | @@ -40,6 +40,7 @@ import Tooltip from './components/tooltip'; |
| 40 | 40 | import Transfer from './components/transfer'; |
| 41 | 41 | import { Row, Col } from './components/layout'; |
| 42 | 42 | import { Select, Option, OptionGroup } from './components/select'; |
| 43 | +import locale from './locale'; | |
| 43 | 44 | |
| 44 | 45 | const iview = { |
| 45 | 46 | Affix, |
| ... | ... | @@ -100,7 +101,10 @@ const iview = { |
| 100 | 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 | 108 | Object.keys(iview).forEach((key) => { |
| 105 | 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 | 51 | \ No newline at end of file | ... | ... |
test/main.js
| ... | ... | @@ -5,9 +5,10 @@ import Vue from 'vue'; |
| 5 | 5 | import VueRouter from 'vue-router'; |
| 6 | 6 | import App from './app.vue'; |
| 7 | 7 | import iView from '../src/index'; |
| 8 | +import locale from '../src/locale/lang/en-US'; | |
| 8 | 9 | |
| 9 | 10 | Vue.use(VueRouter); |
| 10 | -Vue.use(iView); | |
| 11 | +Vue.use(iView, { locale }); | |
| 11 | 12 | |
| 12 | 13 | // 开启debug模式 |
| 13 | 14 | Vue.config.debug = true; | ... | ... |
test/routers/select.vue
| ... | ... | @@ -2,12 +2,12 @@ |
| 2 | 2 | <Row> |
| 3 | 3 | <i-col span="12" style="padding-right:10px"> |
| 4 | 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 | 6 | </i-select> |
| 7 | 7 | </i-col> |
| 8 | 8 | <i-col span="12"> |
| 9 | 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 | 11 | </i-select> |
| 12 | 12 | </i-col> |
| 13 | 13 | </Row> |
| ... | ... | @@ -19,27 +19,31 @@ |
| 19 | 19 | cityList: [ |
| 20 | 20 | { |
| 21 | 21 | value: 'beijing', |
| 22 | - label: '北京市', | |
| 23 | - des: '帝都' | |
| 22 | + label: '北京市' | |
| 24 | 23 | }, |
| 25 | 24 | { |
| 26 | 25 | value: 'shanghai', |
| 27 | - label: '上海市', | |
| 28 | - des: '魔都' | |
| 26 | + label: '上海市' | |
| 29 | 27 | }, |
| 30 | 28 | { |
| 31 | 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 | 41 | value: 'chongqing', |
| 37 | - label: '重庆市', | |
| 38 | - des: '山城' | |
| 42 | + label: '重庆市' | |
| 39 | 43 | } |
| 40 | 44 | ], |
| 41 | 45 | model11: '', |
| 42 | - model12: ['beijing', 'shanghai'] | |
| 46 | + model12: [] | |
| 43 | 47 | } |
| 44 | 48 | } |
| 45 | 49 | } | ... | ... |