From d33b51432d8c13900f1062d84860fb0082780804 Mon Sep 17 00:00:00 2001
From: 梁灏 <admin@aresn.com>
Date: Wed, 11 Jan 2017 18:04:29 +0800
Subject: [PATCH] support i18n

---
 package.json                     |  1 +
 src/components/select/select.vue |  9 +++++++--
 src/index.js                     |  6 +++++-
 src/locale/format.js             | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 src/locale/index.js              | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/locale/lang/en-US.js         |  8 ++++++++
 src/locale/lang/zh-CN.js         |  8 ++++++++
 src/locale/lang/zh-TW.js         |  8 ++++++++
 test/main.js                     |  3 ++-
 test/routers/select.vue          | 26 +++++++++++++++-----------
 10 files changed, 151 insertions(+), 15 deletions(-)
 create mode 100644 src/locale/format.js
 create mode 100644 src/locale/index.js
 create mode 100644 src/locale/lang/en-US.js
 create mode 100644 src/locale/lang/zh-CN.js
 create mode 100644 src/locale/lang/zh-TW.js

diff --git a/package.json b/package.json
index fe3ffc5..d909780 100644
--- a/package.json
+++ b/package.json
@@ -40,6 +40,7 @@
   "dependencies": {
     "async-validator": "^1.6.7",
     "core-js": "^2.4.1",
+    "deepmerge": "^1.3.1",
     "popper.js": "^0.6.4"
   },
   "peerDependencies": {
diff --git a/src/components/select/select.vue b/src/components/select/select.vue
index 7741b78..5d607bd 100644
--- a/src/components/select/select.vue
+++ b/src/components/select/select.vue
@@ -35,6 +35,7 @@
     import Dropdown from './dropdown.vue';
     import clickoutside from '../../directives/clickoutside';
     import { oneOf, MutationObserver } from '../../utils/assist';
+    import { t } from '../../locale';
 
     const prefixCls = 'ivu-select';
 
@@ -60,7 +61,9 @@
             },
             placeholder: {
                 type: String,
-                default: '请选择'
+                default () {
+                    return t('i.select.placeholder');
+                }
             },
             filterable: {
                 type: Boolean,
@@ -80,7 +83,9 @@
             },
             notFoundText: {
                 type: String,
-                default: '无匹配数据'
+                default () {
+                    return t('i.select.noMatch');
+                }
             }
         },
         data () {
diff --git a/src/index.js b/src/index.js
index e7a71fa..6756a5b 100644
--- a/src/index.js
+++ b/src/index.js
@@ -40,6 +40,7 @@ import Tooltip from './components/tooltip';
 import Transfer from './components/transfer';
 import { Row, Col } from './components/layout';
 import { Select, Option, OptionGroup } from './components/select';
+import locale from './locale';
 
 const iview = {
     Affix,
@@ -100,7 +101,10 @@ const iview = {
     Transfer
 };
 
-const install = function (Vue) {
+const install = function (Vue, opts = {}) {
+    locale.use(opts.locale);
+    locale.i18n(opts.i18n);
+
     Object.keys(iview).forEach((key) => {
         Vue.component(key, iview[key]);
     });
diff --git a/src/locale/format.js b/src/locale/format.js
new file mode 100644
index 0000000..93e3c34
--- /dev/null
+++ b/src/locale/format.js
@@ -0,0 +1,47 @@
+/**
+ *  String format template
+ *  - Inspired:
+ *    https://github.com/Matt-Esch/string-template/index.js
+ */
+
+const RE_NARGS = /(%|)\{([0-9a-zA-Z_]+)\}/g;
+
+export default function(Vue) {
+    const { hasOwn } = Vue.util;
+
+    /**
+     * template
+     *
+     * @param {String} string
+     * @param {Array} ...args
+     * @return {String}
+     */
+
+    function template(string, ...args) {
+        if (args.length === 1 && typeof args[0] === 'object') {
+            args = args[0];
+        }
+
+        if (!args || !args.hasOwnProperty) {
+            args = {};
+        }
+
+        return string.replace(RE_NARGS, (match, prefix, i, index) => {
+            let result;
+
+            if (string[index - 1] === '{' &&
+                string[index + match.length] === '}') {
+                return i;
+            } else {
+                result = hasOwn(args, i) ? args[i] : null;
+                if (result === null || result === undefined) {
+                    return '';
+                }
+
+                return result;
+            }
+        });
+    }
+
+    return template;
+}
diff --git a/src/locale/index.js b/src/locale/index.js
new file mode 100644
index 0000000..faf0cf7
--- /dev/null
+++ b/src/locale/index.js
@@ -0,0 +1,50 @@
+// https://github.com/ElemeFE/element/blob/dev/src/locale/index.js
+
+import defaultLang from './lang/zh-CN';
+import Vue from 'vue';
+import deepmerge from 'deepmerge';
+import Format from './format';
+
+const format = Format(Vue);
+let lang = defaultLang;
+let merged = false;
+let i18nHandler = function() {
+    const vuei18n = Object.getPrototypeOf(this || Vue).$t;
+    if (typeof vuei18n === 'function') {
+        if (!merged) {
+            merged = true;
+            Vue.locale(
+                Vue.config.lang,
+                deepmerge(lang, Vue.locale(Vue.config.lang) || {}, { clone: true })
+            );
+        }
+        return vuei18n.apply(this, arguments);
+    }
+};
+
+export const t = function(path, options) {
+    let value = i18nHandler.apply(this, arguments);
+    if (value !== null && value !== undefined) return value;
+
+    const array = path.split('.');
+    let current = lang;
+
+    for (let i = 0, j = array.length; i < j; i++) {
+        const property = array[i];
+        value = current[property];
+        if (i === j - 1) return format(value, options);
+        if (!value) return '';
+        current = value;
+    }
+    return '';
+};
+
+export const use = function(l) {
+    lang = l || lang;
+};
+
+export const i18n = function(fn) {
+    i18nHandler = fn || i18nHandler;
+};
+
+export default { use, t, i18n };
\ No newline at end of file
diff --git a/src/locale/lang/en-US.js b/src/locale/lang/en-US.js
new file mode 100644
index 0000000..08f2215
--- /dev/null
+++ b/src/locale/lang/en-US.js
@@ -0,0 +1,8 @@
+export default {
+    i: {
+        select: {
+            placeholder: 'Select',
+            noMatch: 'No matching data'
+        }
+    }
+};
\ No newline at end of file
diff --git a/src/locale/lang/zh-CN.js b/src/locale/lang/zh-CN.js
new file mode 100644
index 0000000..25bfa00
--- /dev/null
+++ b/src/locale/lang/zh-CN.js
@@ -0,0 +1,8 @@
+export default {
+    i: {
+        select: {
+            placeholder: '请选择',
+            noMatch: '无匹配数据'
+        }
+    }
+};
\ No newline at end of file
diff --git a/src/locale/lang/zh-TW.js b/src/locale/lang/zh-TW.js
new file mode 100644
index 0000000..afa0053
--- /dev/null
+++ b/src/locale/lang/zh-TW.js
@@ -0,0 +1,8 @@
+export default {
+    i: {
+        select: {
+            placeholder: '請選擇',
+            noMatch: '無匹配數據'
+        }
+    }
+};
\ No newline at end of file
diff --git a/test/main.js b/test/main.js
index 1531880..b33cf28 100644
--- a/test/main.js
+++ b/test/main.js
@@ -5,9 +5,10 @@ import Vue from 'vue';
 import VueRouter from 'vue-router';
 import App from './app.vue';
 import iView from '../src/index';
+import locale from '../src/locale/lang/en-US';
 
 Vue.use(VueRouter);
-Vue.use(iView);
+Vue.use(iView, { locale });
 
 // 开启debug模式
 Vue.config.debug = true;
diff --git a/test/routers/select.vue b/test/routers/select.vue
index 749005a..90b325d 100644
--- a/test/routers/select.vue
+++ b/test/routers/select.vue
@@ -2,12 +2,12 @@
     <Row>
         <i-col span="12" style="padding-right:10px">
             <i-select :model.sync="model11" filterable>
-                <i-option v-for="item in cityList" :value="item.value" :label="item.label"><span>{{ item.label }}</span><span>{{ item.des }}</span></i-option>
+                <i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option>
             </i-select>
         </i-col>
         <i-col span="12">
             <i-select :model.sync="model12" filterable multiple>
-                <i-option v-for="item in cityList" :value="item.value" :label="item.label"><span>{{ item.label }}</span><span>{{ item.des }}</span></i-option>
+                <i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option>
             </i-select>
         </i-col>
     </Row>
@@ -19,27 +19,31 @@
                 cityList: [
                     {
                         value: 'beijing',
-                        label: '北京市',
-                        des: '帝都'
+                        label: '北京市'
                     },
                     {
                         value: 'shanghai',
-                        label: '上海市',
-                        des: '魔都'
+                        label: '上海市'
                     },
                     {
                         value: 'shenzhen',
-                        label: '深圳市',
-                        des: '渔村'
+                        label: '深圳市'
+                    },
+                    {
+                        value: 'hangzhou',
+                        label: '杭州市'
+                    },
+                    {
+                        value: 'nanjing',
+                        label: '南京市'
                     },
                     {
                         value: 'chongqing',
-                        label: '重庆市',
-                        des: '山城'
+                        label: '重庆市'
                     }
                 ],
                 model11: '',
-                model12: ['beijing', 'shanghai']
+                model12: []
             }
         }
     }
--
libgit2 0.21.4