You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by za...@apache.org on 2020/07/27 08:56:56 UTC

[incubator-echarts] 01/01: feat(i18n): draft commit for discuss

This is an automated email from the ASF dual-hosted git repository.

zakwu pushed a commit to branch next-i18n
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git

commit 950275dd5f931cfaedc6b2458192ebe0e29c42b9
Author: zakwu <12...@qq.com>
AuthorDate: Mon Jul 27 16:56:20 2020 +0800

    feat(i18n): draft commit for discuss
---
 i18n/langEN.js                               | 144 +++++++++++++++++++++++++++
 {src => i18n}/langES.ts                      |   0
 {src => i18n}/langFI.ts                      |   0
 {src => i18n}/langTH.ts                      |   0
 i18n/langZH.js                               | 141 ++++++++++++++++++++++++++
 src/component/legend/LegendModel.ts          |  34 ++++---
 src/component/toolbox/ToolboxModel.ts        |   7 +-
 src/component/toolbox/feature/Brush.ts       |  41 ++++----
 src/component/toolbox/feature/DataView.ts    |  44 ++++----
 src/component/toolbox/feature/DataZoom.ts    |  28 +++---
 src/component/toolbox/feature/MagicType.ts   |  44 ++++----
 src/component/toolbox/feature/Restore.ts     |  21 ++--
 src/component/toolbox/feature/SaveAsImage.ts |  34 ++++---
 src/component/toolbox/featureManager.ts      |   3 +-
 src/echarts.ts                               |  19 +++-
 src/lang.ts                                  | 126 -----------------------
 src/langEN.ts                                | 126 -----------------------
 src/model/Global.ts                          |  27 ++++-
 src/util/types.ts                            |   1 +
 src/visual/aria.ts                           |   4 +-
 test/lang.html                               | 104 +++++++++++++++++++
 21 files changed, 574 insertions(+), 374 deletions(-)

diff --git a/i18n/langEN.js b/i18n/langEN.js
new file mode 100644
index 0000000..ebba3a1
--- /dev/null
+++ b/i18n/langEN.js
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Language: English.
+ */
+
+(function(root, factory) {
+    if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define(['exports', 'echarts'], factory);
+    } else if (
+        typeof exports === 'object' &&
+        typeof exports.nodeName !== 'string'
+    ) {
+        // CommonJS
+        factory(exports, require('echarts'));
+    } else {
+        // Browser globals
+        factory({}, root.echarts);
+    }
+})(this, function(exports, echarts) {
+    let lang = {
+        legend: {
+            selector: {
+                all: 'All',
+                inverse: 'Inv'
+            }
+        },
+        toolbox: {
+            brush: {
+                title: {
+                    rect: 'Box Select',
+                    polygon: 'Lasso Select',
+                    lineX: 'Horizontally Select',
+                    lineY: 'Vertically Select',
+                    keep: 'Keep Selections',
+                    clear: 'Clear Selections'
+                }
+            },
+            dataView: {
+                title: 'Data View',
+                lang: ['Data View', 'Close', 'Refresh']
+            },
+            dataZoom: {
+                title: {
+                    zoom: 'Zoom',
+                    back: 'Zoom Reset'
+                }
+            },
+            magicType: {
+                title: {
+                    line: 'Switch to Line Chart',
+                    bar: 'Switch to Bar Chart',
+                    stack: 'Stack',
+                    tiled: 'Tile'
+                }
+            },
+            restore: {
+                title: 'Restore'
+            },
+            saveAsImage: {
+                title: 'Save as Image',
+                lang: ['Right Click to Save Image']
+            }
+        },
+        series: {
+            typeNames: {
+                pie: 'Pie chart',
+                bar: 'Bar chart',
+                line: 'Line chart',
+                scatter: 'Scatter plot',
+                effectScatter: 'Ripple scatter plot',
+                radar: 'Radar chart',
+                tree: 'Tree',
+                treemap: 'Treemap',
+                boxplot: 'Boxplot',
+                candlestick: 'Candlestick',
+                k: 'K line chart',
+                heatmap: 'Heat map',
+                map: 'Map',
+                parallel: 'Parallel coordinate map',
+                lines: 'Line graph',
+                graph: 'Relationship graph',
+                sankey: 'Sankey diagram',
+                funnel: 'Funnel chart',
+                gauge: 'Guage',
+                pictorialBar: 'Pictorial bar',
+                themeRiver: 'Theme River Map',
+                sunburst: 'Sunburst'
+            }
+        },
+        aria: {
+            general: {
+                withTitle: 'This is a chart about "{title}"',
+                withoutTitle: 'This is a chart'
+            },
+            series: {
+                single: {
+                    prefix: '',
+                    withName: ' with type {seriesType} named {seriesName}.',
+                    withoutName: ' with type {seriesType}.'
+                },
+                multiple: {
+                    prefix: '. It consists of {seriesCount} series count.',
+                    withName: ' The {seriesId} series is a {seriesType} representing {seriesName}.',
+                    withoutName: ' The {seriesId} series is a {seriesType}.',
+                    separator: {
+                        middle: '',
+                        end: ''
+                    }
+                }
+            },
+            data: {
+                allData: 'The data is as follows: ',
+                partialData: 'The first {displayCnt} items are: ',
+                withName: 'the data for {name} is {value}',
+                withoutName: '{value}',
+                separator: {
+                    middle: ',',
+                    end: '.'
+                }
+            }
+        }
+    };
+
+    echarts.registerLocale('EN', lang);
+});
diff --git a/src/langES.ts b/i18n/langES.ts
similarity index 100%
rename from src/langES.ts
rename to i18n/langES.ts
diff --git a/src/langFI.ts b/i18n/langFI.ts
similarity index 100%
rename from src/langFI.ts
rename to i18n/langFI.ts
diff --git a/src/langTH.ts b/i18n/langTH.ts
similarity index 100%
rename from src/langTH.ts
rename to i18n/langTH.ts
diff --git a/i18n/langZH.js b/i18n/langZH.js
new file mode 100644
index 0000000..5b2a4d9
--- /dev/null
+++ b/i18n/langZH.js
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+(function(root, factory) {
+    if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define(['exports', 'echarts'], factory);
+    } else if (
+        typeof exports === 'object' &&
+        typeof exports.nodeName !== 'string'
+    ) {
+        // CommonJS
+        factory(exports, require('echarts'));
+    } else {
+        // Browser globals
+        factory({}, root.echarts);
+    }
+})(this, function(exports, echarts) {
+    let lang = {
+
+        legend: {
+            selector: {
+                all: '全选',
+                inverse: '反选'
+            }
+        },
+        toolbox: {
+            brush: {
+                title: {
+                    rect: '矩形选择',
+                    polygon: '圈选',
+                    lineX: '横向选择',
+                    lineY: '纵向选择',
+                    keep: '保持选择',
+                    clear: '清除选择'
+                }
+            },
+            dataView: {
+                title: '数据视图',
+                lang: ['数据视图', '关闭', '刷新']
+            },
+            dataZoom: {
+                title: {
+                    zoom: '区域缩放',
+                    back: '区域缩放还原'
+                }
+            },
+            magicType: {
+                title: {
+                    line: '切换为折线图',
+                    bar: '切换为柱状图',
+                    stack: '切换为堆叠',
+                    tiled: '切换为平铺'
+                }
+            },
+            restore: {
+                title: '还原'
+            },
+            saveAsImage: {
+                title: '保存为图片',
+                lang: ['右键另存为图片']
+            }
+        },
+        series: {
+            typeNames: {
+                pie: '饼图',
+                bar: '柱状图',
+                line: '折线图',
+                scatter: '散点图',
+                effectScatter: '涟漪散点图',
+                radar: '雷达图',
+                tree: '树图',
+                treemap: '矩形树图',
+                boxplot: '箱型图',
+                candlestick: 'K线图',
+                k: 'K线图',
+                heatmap: '热力图',
+                map: '地图',
+                parallel: '平行坐标图',
+                lines: '线图',
+                graph: '关系图',
+                sankey: '桑基图',
+                funnel: '漏斗图',
+                gauge: '仪表盘图',
+                pictorialBar: '象形柱图',
+                themeRiver: '主题河流图',
+                sunburst: '旭日图'
+            }
+        },
+        aria: {
+            general: {
+                withTitle: '这是一个关于“{title}”的图表。',
+                withoutTitle: '这是一个图表,'
+            },
+            series: {
+                single: {
+                    prefix: '',
+                    withName: '图表类型是{seriesType},表示{seriesName}。',
+                    withoutName: '图表类型是{seriesType}。'
+                },
+                multiple: {
+                    prefix: '它由{seriesCount}个图表系列组成。',
+                    withName: '第{seriesId}个系列是一个表示{seriesName}的{seriesType},',
+                    withoutName: '第{seriesId}个系列是一个{seriesType},',
+                    separator: {
+                        middle: ';',
+                        end: '。'
+                    }
+                }
+            },
+            data: {
+                allData: '其数据是——',
+                partialData: '其中,前{displayCnt}项是——',
+                withName: '{name}的数据是{value}',
+                withoutName: '{value}',
+                separator: {
+                    middle: ',',
+                    end: ''
+                }
+            }
+        }
+    };
+
+    echarts.registerLocale('ZH', lang);
+});
diff --git a/src/component/legend/LegendModel.ts b/src/component/legend/LegendModel.ts
index 290b7b3..aba8915 100644
--- a/src/component/legend/LegendModel.ts
+++ b/src/component/legend/LegendModel.ts
@@ -20,7 +20,6 @@
 import * as zrUtil from 'zrender/src/core/util';
 import Model from '../../model/Model';
 import {isNameSpecified} from '../../util/model';
-import lang from '../../lang';
 import ComponentModel from '../../model/Component';
 import {
     ComponentOption,
@@ -35,18 +34,24 @@ import {
 import { Dictionary } from 'zrender/src/core/types';
 import GlobalModel from '../../model/Global';
 
-const langSelector = lang.legend.selector;
-
-const defaultSelectorOption = {
-    all: {
-        type: 'all',
-        title: zrUtil.clone(langSelector.all)
-    },
-    inverse: {
-        type: 'inverse',
-        title: zrUtil.clone(langSelector.inverse)
-    }
+type LegendDefaultSelectorOptionsProps = {
+    type: string;
+    title: string;
 };
+const getDefaultSelectorOptions = function (ecModel: GlobalModel, type: string): LegendDefaultSelectorOptionsProps {
+    if(type === 'all') {
+        return {
+            type: 'all',
+            title: ecModel.getWithLocale(['legend', 'selector', 'all'])
+        }
+    } else if(type === 'inverse') {
+        return {
+            type: 'inverse',
+            title: ecModel.getWithLocale(['legend', 'selector', 'inverse'])
+        }
+    }
+}
+
 
 type SelectorType = 'all' | 'inverse';
 export interface LegendSelectorButtonOption {
@@ -201,6 +206,7 @@ class LegendModel<Ops extends LegendOption = LegendOption> extends ComponentMode
 
     _updateSelector(option: Ops) {
         let selector = option.selector;
+        const {ecModel} = this;
         if (selector === true) {
             selector = option.selector = ['all', 'inverse'];
         }
@@ -208,7 +214,7 @@ class LegendModel<Ops extends LegendOption = LegendOption> extends ComponentMode
             zrUtil.each(selector, function (item, index) {
                 zrUtil.isString(item) && (item = {type: item});
                 (selector as LegendSelectorButtonOption[])[index] = zrUtil.merge(
-                    item, defaultSelectorOption[item.type]
+                    item, getDefaultSelectorOptions(ecModel, item.type)
                 );
             });
         }
@@ -434,4 +440,4 @@ class LegendModel<Ops extends LegendOption = LegendOption> extends ComponentMode
 
 ComponentModel.registerClass(LegendModel);
 
-export default LegendModel;
\ No newline at end of file
+export default LegendModel;
diff --git a/src/component/toolbox/ToolboxModel.ts b/src/component/toolbox/ToolboxModel.ts
index 4c25d8f..6c71ec7 100644
--- a/src/component/toolbox/ToolboxModel.ts
+++ b/src/component/toolbox/ToolboxModel.ts
@@ -31,6 +31,7 @@ import {
     CommonTooltipOption,
     Dictionary
 } from '../../util/types';
+import GlobalModel from "../../model/Global";
 
 
 export interface ToolboxTooltipFormatterParams {
@@ -86,9 +87,13 @@ class ToolboxModel extends ComponentModel<ToolboxOption> {
 
     optionUpdated() {
         super.optionUpdated.apply(this, arguments as any);
+        const {ecModel} = this;
 
         zrUtil.each(this.option.feature, function (featureOpt, featureName) {
             const Feature = featureManager.getFeature(featureName);
+            if(Feature.getDefaultOption) {
+                Feature.defaultOption = Feature.getDefaultOption(ecModel)
+            }
             Feature && zrUtil.merge(featureOpt, Feature.defaultOption);
         });
     }
@@ -147,4 +152,4 @@ class ToolboxModel extends ComponentModel<ToolboxOption> {
 
 ComponentModel.registerClass(ToolboxModel);
 
-export default ToolboxModel;
\ No newline at end of file
+export default ToolboxModel;
diff --git a/src/component/toolbox/feature/Brush.ts b/src/component/toolbox/feature/Brush.ts
index 984fa33..c9e1208 100644
--- a/src/component/toolbox/feature/Brush.ts
+++ b/src/component/toolbox/feature/Brush.ts
@@ -18,7 +18,6 @@
 */
 
 import * as zrUtil from 'zrender/src/core/util';
-import lang from '../../../lang';
 import {
     ToolboxFeatureModel,
     ToolboxFeatureOption,
@@ -30,8 +29,6 @@ import ExtensionAPI from '../../../ExtensionAPI';
 import BrushModel from '../../brush/BrushModel';
 import { BrushTypeUncertain } from '../../helper/BrushController';
 
-const brushLang = lang.toolbox.brush;
-
 const ICON_TYPES = ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear'] as const;
 
 type IconType = typeof ICON_TYPES[number];
@@ -132,24 +129,28 @@ class BrushFeature extends ToolboxFeature<ToolboxBrushFeatureOption> {
         }
     };
 
-    static defaultOption: ToolboxBrushFeatureOption = {
-        show: true,
-        type: ICON_TYPES.slice(),
-        icon: {
-            /* eslint-disable */
-            rect: 'M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13', // jshint ignore:line
-            polygon: 'M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2', // jshint ignore:line
-            lineX: 'M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4', // jshint ignore:line
-            lineY: 'M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4', // jshint ignore:line
-            keep: 'M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z', // jshint ignore:line
-            clear: 'M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2' // jshint ignore:line
-            /* eslint-enable */
-        },
-        // `rect`, `polygon`, `lineX`, `lineY`, `keep`, `clear`
-        title: zrUtil.clone(brushLang.title)
-    };
+    static getDefaultOption(ecModel: GlobalModel) {
+        const defaultOption: ToolboxBrushFeatureOption = {
+            show: true,
+            type: ICON_TYPES.slice(),
+            icon: {
+                /* eslint-disable */
+                rect: 'M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13', // jshint ignore:line
+                polygon: 'M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2', // jshint ignore:line
+                lineX: 'M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4', // jshint ignore:line
+                lineY: 'M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4', // jshint ignore:line
+                keep: 'M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z', // jshint ignore:line
+                clear: 'M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2' // jshint ignore:line
+                /* eslint-enable */
+            },
+            // `rect`, `polygon`, `lineX`, `lineY`, `keep`, `clear`
+            title: ecModel.getWithLocale(['toolbox', 'brush', 'title'])
+        }
+
+        return defaultOption;
+    }
 }
 
 registerFeature('brush', BrushFeature);
 
-export default BrushFeature;
\ No newline at end of file
+export default BrushFeature;
diff --git a/src/component/toolbox/feature/DataView.ts b/src/component/toolbox/feature/DataView.ts
index 690f7d4..ddf4231 100644
--- a/src/component/toolbox/feature/DataView.ts
+++ b/src/component/toolbox/feature/DataView.ts
@@ -19,7 +19,6 @@
 
 import * as echarts from '../../../echarts';
 import * as zrUtil from 'zrender/src/core/util';
-import lang from '../../../lang';
 import GlobalModel from '../../../model/Global';
 import SeriesModel from '../../../model/Series';
 import { ToolboxFeature, registerFeature, ToolboxFeatureOption } from '../featureManager';
@@ -28,8 +27,7 @@ import ExtensionAPI from '../../../ExtensionAPI';
 import { addEventListener } from 'zrender/src/core/event';
 import Axis from '../../../coord/Axis';
 import Cartesian2D from '../../../coord/cartesian/Cartesian2D';
-
-const dataViewLang = lang.toolbox.dataView;
+import {ToolboxSaveAsImageFeatureOption} from "./SaveAsImage";
 
 const BLOCK_SPLITER = new Array(60).join('-');
 const ITEM_SPLITER = '\t';
@@ -423,23 +421,27 @@ class DataView extends ToolboxFeature<ToolboxDataViewFeatureOption> {
         this.remove(ecModel, api);
     }
 
-    static defaultOption: ToolboxDataViewFeatureOption = {
-        show: true,
-        readOnly: false,
-        optionToContent: null,
-        contentToOption: null,
-
-        // eslint-disable-next-line
-        icon: 'M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28',
-        title: zrUtil.clone(dataViewLang.title),
-        lang: zrUtil.clone(dataViewLang.lang),
-        backgroundColor: '#fff',
-        textColor: '#000',
-        textareaColor: '#fff',
-        textareaBorderColor: '#333',
-        buttonColor: '#c23531',
-        buttonTextColor: '#fff'
-    };
+    static getDefaultOption(ecModel: GlobalModel) {
+        const defaultOption: ToolboxDataViewFeatureOption = {
+            show: true,
+            readOnly: false,
+            optionToContent: null,
+            contentToOption: null,
+
+            // eslint-disable-next-line
+            icon: 'M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28',
+            title: ecModel.getWithLocale(['toolbox', 'dataView', 'title']),
+            lang: ecModel.getWithLocale(['toolbox', 'dataView', 'lang']),
+            backgroundColor: '#fff',
+            textColor: '#000',
+            textareaColor: '#fff',
+            textareaBorderColor: '#333',
+            buttonColor: '#c23531',
+            buttonTextColor: '#fff'
+        }
+
+        return defaultOption;
+    }
 }
 
 /**
@@ -495,4 +497,4 @@ echarts.registerAction({
     }, payload.newOption));
 });
 
-export default DataView;
\ No newline at end of file
+export default DataView;
diff --git a/src/component/toolbox/feature/DataZoom.ts b/src/component/toolbox/feature/DataZoom.ts
index a69b92f..a42f282 100644
--- a/src/component/toolbox/feature/DataZoom.ts
+++ b/src/component/toolbox/feature/DataZoom.ts
@@ -24,7 +24,6 @@ import BrushController, { BrushControllerEvents, BrushDimensionMinMax } from '..
 import BrushTargetManager, { BrushTargetInfoCartesian2D } from '../../helper/BrushTargetManager';
 import * as history from '../../dataZoom/history';
 import sliderMove from '../../helper/sliderMove';
-import lang from '../../../lang';
 // Use dataZoomSelect
 import '../../dataZoomSelect';
 import {
@@ -51,7 +50,6 @@ import { registerInternalOptionCreator } from '../../../model/internalComponentC
 import ComponentModel from '../../../model/Component';
 
 
-const dataZoomLang = lang.toolbox.dataZoom;
 const each = zrUtil.each;
 
 const DATA_ZOOM_ID_BASE = makeInternalComponentId('toolbox-dataZoom_');
@@ -206,17 +204,21 @@ class DataZoomFeature extends ToolboxFeature<ToolboxDataZoomFeatureOption> {
         });
     }
 
-    static defaultOption: ToolboxDataZoomFeatureOption = {
-        show: true,
-        filterMode: 'filter',
-        // Icon group
-        icon: {
-            zoom: 'M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1',
-            back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
-        },
-        // `zoom`, `back`
-        title: zrUtil.clone(dataZoomLang.title)
-    };
+    static getDefaultOption(ecModel: GlobalModel) {
+        const defaultOption: ToolboxDataZoomFeatureOption = {
+            show: true,
+            filterMode: 'filter',
+            // Icon group
+            icon: {
+                zoom: 'M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1',
+                back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
+            },
+            // `zoom`, `back`
+            title: ecModel.getWithLocale(['toolbox', 'dataZoom', 'title']),
+        }
+
+        return defaultOption;
+    }
 }
 
 const handlers: { [key in IconType]: (this: DataZoomFeature) => void } = {
diff --git a/src/component/toolbox/feature/MagicType.ts b/src/component/toolbox/feature/MagicType.ts
index b5b3e0f..1fd0da9 100644
--- a/src/component/toolbox/feature/MagicType.ts
+++ b/src/component/toolbox/feature/MagicType.ts
@@ -19,7 +19,6 @@
 
 import * as echarts from '../../../echarts';
 import * as zrUtil from 'zrender/src/core/util';
-import lang from '../../../lang';
 import {ToolboxFeature, ToolboxFeatureOption, ToolboxFeatureModel, registerFeature} from '../featureManager';
 import { SeriesOption, ECUnitOption } from '../../../util/types';
 import GlobalModel from '../../../model/Global';
@@ -27,7 +26,6 @@ import ExtensionAPI from '../../../ExtensionAPI';
 import SeriesModel from '../../../model/Series';
 import { SINGLE_REFERRING } from '../../../util/model';
 
-const magicTypeLang = lang.toolbox.magicType;
 const INNER_STACK_KEYWORD = '__ec_magicType_stack__' as const;
 
 const ICON_TYPES = ['line', 'bar', 'stack'] as const;
@@ -74,21 +72,25 @@ class MagicType extends ToolboxFeature<ToolboxMagicTypeFeatureOption> {
         return icons;
     }
 
-    static defaultOption: ToolboxMagicTypeFeatureOption = {
-        show: true,
-        type: [],
-        // Icon group
-        icon: {
-            line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4',
-            bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7',
-            // eslint-disable-next-line
-            stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z' // jshint ignore:line
-        },
-        // `line`, `bar`, `stack`, `tiled`
-        title: zrUtil.clone(magicTypeLang.title),
-        option: {},
-        seriesIndex: {}
-    };
+    static getDefaultOption(ecModel: GlobalModel) {
+        const defaultOption: ToolboxMagicTypeFeatureOption = {
+            show: true,
+            type: [],
+            // Icon group
+            icon: {
+                line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4',
+                bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7',
+                // eslint-disable-next-line
+                stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z' // jshint ignore:line
+            },
+            // `line`, `bar`, `stack`, `tiled`
+            title: ecModel.getWithLocale(['toolbox', 'magicTypeLang', 'title']),
+            option: {},
+            seriesIndex: {}
+        }
+
+        return defaultOption;
+    }
 
     onclick(ecModel: GlobalModel, api: ExtensionAPI, type: IconType) {
         const model = this.model;
@@ -153,11 +155,13 @@ class MagicType extends ToolboxFeature<ToolboxMagicTypeFeatureOption> {
         // Change title of stack
         if (type === 'stack') {
             const seriesOptions = newOption.series as (SeriesOption & { stack: string })[];
+            const titldLang = ecModel.getWithLocale(['toolbox', 'magicTypeLang', 'title', 'tiled']);
+            const titleLang = ecModel.getWithLocale(['toolbox', 'magicTypeLang', 'title']);
             const isStack = seriesOptions && seriesOptions[0]
                 && seriesOptions[0].stack === INNER_STACK_KEYWORD;
             newTitle = isStack
-                ? zrUtil.merge({ stack: magicTypeLang.title.tiled }, magicTypeLang.title)
-                : zrUtil.clone(magicTypeLang.title);
+                ? zrUtil.merge({ stack: titldLang }, titleLang)
+                : zrUtil.clone(titleLang);
         }
 
         api.dispatchAction({
@@ -234,4 +238,4 @@ echarts.registerAction({
 
 registerFeature('magicType', MagicType);
 
-export default MagicType;
\ No newline at end of file
+export default MagicType;
diff --git a/src/component/toolbox/feature/Restore.ts b/src/component/toolbox/feature/Restore.ts
index 9e650bd..b8a2c69 100644
--- a/src/component/toolbox/feature/Restore.ts
+++ b/src/component/toolbox/feature/Restore.ts
@@ -19,13 +19,10 @@
 
 import * as echarts from '../../../echarts';
 import * as history from '../../dataZoom/history';
-import lang from '../../../lang';
 import { ToolboxFeatureOption, ToolboxFeature, registerFeature } from '../featureManager';
 import ExtensionAPI from '../../../ExtensionAPI';
 import GlobalModel from '../../../model/Global';
 
-const restoreLang = lang.toolbox.restore;
-
 export interface ToolboxRestoreFeatureOption extends ToolboxFeatureOption {
     icon?: string
     title?: string
@@ -42,12 +39,16 @@ class RestoreOption extends ToolboxFeature<ToolboxRestoreFeatureOption> {
         });
     }
 
-    static defaultOption: ToolboxRestoreFeatureOption = {
-        show: true,
-        // eslint-disable-next-line
-        icon: 'M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5',
-        title: restoreLang.title
-    };
+    static getDefaultOption(ecModel: GlobalModel) {
+        const defaultOption: ToolboxRestoreFeatureOption = {
+            show: true,
+            // eslint-disable-next-line
+            icon: 'M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5',
+            title: ecModel.getWithLocale(['toolbox', 'restore', 'title']),
+        }
+
+        return defaultOption;
+    }
 }
 
 registerFeature('restore', RestoreOption);
@@ -57,4 +58,4 @@ echarts.registerAction(
     function (payload, ecModel) {
         ecModel.resetOption('recreate');
     }
-);
\ No newline at end of file
+);
diff --git a/src/component/toolbox/feature/SaveAsImage.ts b/src/component/toolbox/feature/SaveAsImage.ts
index f90d718..f97827a 100644
--- a/src/component/toolbox/feature/SaveAsImage.ts
+++ b/src/component/toolbox/feature/SaveAsImage.ts
@@ -20,14 +20,11 @@
 /* global Uint8Array */
 
 import env from 'zrender/src/core/env';
-import lang from '../../../lang';
 import { ToolboxFeature, ToolboxFeatureOption, registerFeature } from '../featureManager';
 import { ZRColor } from '../../../util/types';
 import GlobalModel from '../../../model/Global';
 import ExtensionAPI from '../../../ExtensionAPI';
 
-const saveAsImageLang = lang.toolbox.saveAsImage;
-
 export interface ToolboxSaveAsImageFeatureOption extends ToolboxFeatureOption {
     icon?: string
     title?: string
@@ -97,20 +94,25 @@ class SaveAsImage extends ToolboxFeature<ToolboxSaveAsImageFeatureOption> {
         }
     }
 
-    static defaultOption: ToolboxSaveAsImageFeatureOption = {
-        show: true,
-        icon: 'M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0',
-        title: saveAsImageLang.title,
-        type: 'png',
-        // Default use option.backgroundColor
-        // backgroundColor: '#fff',
-        connectedBackgroundColor: '#fff',
-        name: '',
-        excludeComponents: ['toolbox'],
-        pixelRatio: 1,
-        lang: saveAsImageLang.lang.slice()
-    };
+    static getDefaultOption(ecModel: GlobalModel) {
+         const defaultOption: ToolboxSaveAsImageFeatureOption = {
+            show: true,
+            icon: 'M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0',
+            title: ecModel.getWithLocale(['toolbox', 'saveAsImage', 'title']),
+            type: 'png',
+            // Default use option.backgroundColor
+            // backgroundColor: '#fff',
+            connectedBackgroundColor: '#fff',
+            name: '',
+            excludeComponents: ['toolbox'],
+            pixelRatio: 1,
+            lang: ecModel.getWithLocale(['toolbox', 'saveAsImage', 'lang'], null, (t) => t.slice())
+        }
+
+        return defaultOption;
+    }
 }
+
 SaveAsImage.prototype.unusable = !env.canvasSupported;
 
 registerFeature('saveAsImage', SaveAsImage);
diff --git a/src/component/toolbox/featureManager.ts b/src/component/toolbox/featureManager.ts
index 52367cd..756e013 100644
--- a/src/component/toolbox/featureManager.ts
+++ b/src/component/toolbox/featureManager.ts
@@ -106,7 +106,8 @@ type ToolboxFeatureCtor = {
     /**
      * Static defaultOption property
      */
-    defaultOption: ToolboxFeatureOption
+    defaultOption?: ToolboxFeatureOption
+    getDefaultOption?: (ecModel: GlobalModel) => ToolboxFeatureOption
 };
 
 const features: Dictionary<ToolboxFeatureCtor> = {};
diff --git a/src/echarts.ts b/src/echarts.ts
index 64e4d89..73c883b 100644
--- a/src/echarts.ts
+++ b/src/echarts.ts
@@ -76,7 +76,7 @@ import {
     ActionHandler, ActionInfo, OptionPreprocessor, PostUpdater,
     LoadingEffect, LoadingEffectCreator, StageHandlerInternal,
     StageHandlerOverallReset, StageHandler,
-    ViewRootGroup, DimensionDefinitionLoose, ECEventData, ThemeOption,
+    ViewRootGroup, DimensionDefinitionLoose, ECEventData, ThemeOption, LocaleOption,
     ECOption,
     ECUnitOption,
     ZRColor,
@@ -274,6 +274,8 @@ class ECharts extends Eventful {
 
     private _theme: ThemeOption;
 
+    private _locale: LocaleOption;
+
     private _chartsViews: ChartView[] = [];
 
     private _chartsMap: {[viewId: string]: ChartView} = {};
@@ -310,6 +312,7 @@ class ECharts extends Eventful {
         dom: HTMLElement,
         // Theme name or themeOption.
         theme?: string | ThemeOption,
+        locale?: string | LocaleOption,
         opts?: {
             renderer?: RendererType,
             devicePixelRatio?: number,
@@ -349,6 +352,8 @@ class ECharts extends Eventful {
         theme && backwardCompat(theme as ECUnitOption, true);
 
         this._theme = theme;
+        this._locale = typeof locale === 'string' ? localeStorage[locale || 'ZH'] : zrUtil.clone(locale);
+        console.log(this._locale);
 
         this._coordSysMgr = new CoordinateSystemManager();
 
@@ -504,7 +509,7 @@ class ECharts extends Eventful {
             const theme = this._theme;
             const ecModel = this._model = new GlobalModel();
             ecModel.scheduler = this._scheduler;
-            ecModel.init(null, null, null, theme, optionManager);
+            ecModel.init(null, null, null, theme, this._locale, optionManager);
         }
 
         this._model.setOption(option, {replaceMerge: replaceMerge}, optionPreprocessorFuncs);
@@ -2301,6 +2306,8 @@ const visualFuncs: StageHandlerInternal[] = [];
 
 const themeStorage: {[themeName: string]: ThemeOption} = {};
 
+const localeStorage: {[localeName: string]: LocaleOption} = {};
+
 const loadingEffects: {[effectName: string]: LoadingEffectCreator} = {};
 
 const instances: {[id: string]: ECharts} = {};
@@ -2322,6 +2329,7 @@ const DOM_ATTRIBUTE_KEY = '_echarts_instance_';
 export function init(
     dom: HTMLElement,
     theme?: string | object,
+    locale?: string | object,
     opts?: {
         renderer?: RendererType,
         devicePixelRatio?: number,
@@ -2368,7 +2376,7 @@ export function init(
         }
     }
 
-    const chart = new ECharts(dom, theme, opts);
+    const chart = new ECharts(dom, theme, locale, opts);
     chart.id = 'ec_' + idBase++;
     instances[chart.id] = chart;
 
@@ -2459,6 +2467,11 @@ export function registerTheme(name: string, theme: ThemeOption): void {
     themeStorage[name] = theme;
 }
 
+export function registerLocale(name: string, locale: LocaleOption): void {
+    localeStorage[name] = locale;
+    console.log('localeStorage', localeStorage);
+}
+
 /**
  * Register option preprocessor
  */
diff --git a/src/lang.ts b/src/lang.ts
deleted file mode 100644
index b369139..0000000
--- a/src/lang.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*   http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-* KIND, either express or implied.  See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-
-/**
- * Language: (Simplified) Chinese.
- */
-
-export default {
-    legend: {
-        selector: {
-            all: '全选',
-            inverse: '反选'
-        }
-    },
-    toolbox: {
-        brush: {
-            title: {
-                rect: '矩形选择',
-                polygon: '圈选',
-                lineX: '横向选择',
-                lineY: '纵向选择',
-                keep: '保持选择',
-                clear: '清除选择'
-            }
-        },
-        dataView: {
-            title: '数据视图',
-            lang: ['数据视图', '关闭', '刷新']
-        },
-        dataZoom: {
-            title: {
-                zoom: '区域缩放',
-                back: '区域缩放还原'
-            }
-        },
-        magicType: {
-            title: {
-                line: '切换为折线图',
-                bar: '切换为柱状图',
-                stack: '切换为堆叠',
-                tiled: '切换为平铺'
-            }
-        },
-        restore: {
-            title: '还原'
-        },
-        saveAsImage: {
-            title: '保存为图片',
-            lang: ['右键另存为图片']
-        }
-    },
-    series: {
-        typeNames: {
-            pie: '饼图',
-            bar: '柱状图',
-            line: '折线图',
-            scatter: '散点图',
-            effectScatter: '涟漪散点图',
-            radar: '雷达图',
-            tree: '树图',
-            treemap: '矩形树图',
-            boxplot: '箱型图',
-            candlestick: 'K线图',
-            k: 'K线图',
-            heatmap: '热力图',
-            map: '地图',
-            parallel: '平行坐标图',
-            lines: '线图',
-            graph: '关系图',
-            sankey: '桑基图',
-            funnel: '漏斗图',
-            gauge: '仪表盘图',
-            pictorialBar: '象形柱图',
-            themeRiver: '主题河流图',
-            sunburst: '旭日图'
-        }
-    },
-    aria: {
-        general: {
-            withTitle: '这是一个关于“{title}”的图表。',
-            withoutTitle: '这是一个图表,'
-        },
-        series: {
-            single: {
-                prefix: '',
-                withName: '图表类型是{seriesType},表示{seriesName}。',
-                withoutName: '图表类型是{seriesType}。'
-            },
-            multiple: {
-                prefix: '它由{seriesCount}个图表系列组成。',
-                withName: '第{seriesId}个系列是一个表示{seriesName}的{seriesType},',
-                withoutName: '第{seriesId}个系列是一个{seriesType},',
-                separator: {
-                    middle: ';',
-                    end: '。'
-                }
-            }
-        },
-        data: {
-            allData: '其数据是——',
-            partialData: '其中,前{displayCnt}项是——',
-            withName: '{name}的数据是{value}',
-            withoutName: '{value}',
-            separator: {
-                middle: ',',
-                end: ''
-            }
-        }
-    }
-};
diff --git a/src/langEN.ts b/src/langEN.ts
deleted file mode 100644
index 0df1872..0000000
--- a/src/langEN.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*   http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-* KIND, either express or implied.  See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*/
-
-/**
- * Language: English.
- */
-
-export default {
-    legend: {
-        selector: {
-            all: 'All',
-            inverse: 'Inv'
-        }
-    },
-    toolbox: {
-        brush: {
-            title: {
-                rect: 'Box Select',
-                polygon: 'Lasso Select',
-                lineX: 'Horizontally Select',
-                lineY: 'Vertically Select',
-                keep: 'Keep Selections',
-                clear: 'Clear Selections'
-            }
-        },
-        dataView: {
-            title: 'Data View',
-            lang: ['Data View', 'Close', 'Refresh']
-        },
-        dataZoom: {
-            title: {
-                zoom: 'Zoom',
-                back: 'Zoom Reset'
-            }
-        },
-        magicType: {
-            title: {
-                line: 'Switch to Line Chart',
-                bar: 'Switch to Bar Chart',
-                stack: 'Stack',
-                tiled: 'Tile'
-            }
-        },
-        restore: {
-            title: 'Restore'
-        },
-        saveAsImage: {
-            title: 'Save as Image',
-            lang: ['Right Click to Save Image']
-        }
-    },
-    series: {
-        typeNames: {
-            pie: 'Pie chart',
-            bar: 'Bar chart',
-            line: 'Line chart',
-            scatter: 'Scatter plot',
-            effectScatter: 'Ripple scatter plot',
-            radar: 'Radar chart',
-            tree: 'Tree',
-            treemap: 'Treemap',
-            boxplot: 'Boxplot',
-            candlestick: 'Candlestick',
-            k: 'K line chart',
-            heatmap: 'Heat map',
-            map: 'Map',
-            parallel: 'Parallel coordinate map',
-            lines: 'Line graph',
-            graph: 'Relationship graph',
-            sankey: 'Sankey diagram',
-            funnel: 'Funnel chart',
-            gauge: 'Guage',
-            pictorialBar: 'Pictorial bar',
-            themeRiver: 'Theme River Map',
-            sunburst: 'Sunburst'
-        }
-    },
-    aria: {
-        general: {
-            withTitle: 'This is a chart about "{title}"',
-            withoutTitle: 'This is a chart'
-        },
-        series: {
-            single: {
-                prefix: '',
-                withName: ' with type {seriesType} named {seriesName}.',
-                withoutName: ' with type {seriesType}.'
-            },
-            multiple: {
-                prefix: '. It consists of {seriesCount} series count.',
-                withName: ' The {seriesId} series is a {seriesType} representing {seriesName}.',
-                withoutName: ' The {seriesId} series is a {seriesType}.',
-                separator: {
-                    middle: '',
-                    end: ''
-                }
-            }
-        },
-        data: {
-            allData: 'The data is as follows: ',
-            partialData: 'The first {displayCnt} items are: ',
-            withName: 'the data for {name} is {value}',
-            withoutName: '{value}',
-            separator: {
-                middle: ',',
-                end: '.'
-            }
-        }
-    }
-};
diff --git a/src/model/Global.ts b/src/model/Global.ts
index ff220f8..d9109d0 100644
--- a/src/model/Global.ts
+++ b/src/model/Global.ts
@@ -53,11 +53,12 @@ import {
     ThemeOption,
     ComponentOption,
     ComponentMainType,
-    ComponentSubType
+    ComponentSubType, LocaleOption
 } from '../util/types';
 import OptionManager from './OptionManager';
 import Scheduler from '../stream/Scheduler';
 import { concatInternalOptions } from './internalComponentCreator';
+import {Dictionary} from "zrender/src/core/types";
 
 export interface GlobalModelSetOptionOpts {
     replaceMerge: ComponentMainType | ComponentMainType[];
@@ -80,6 +81,8 @@ class GlobalModel extends Model<ECUnitOption> {
 
     private _theme: Model;
 
+    private _locale: object;
+
     private _optionManager: OptionManager;
 
     private _componentsMap: HashMap<ComponentModel[], ComponentMainType>;
@@ -119,11 +122,14 @@ class GlobalModel extends Model<ECUnitOption> {
         parentModel: Model,
         ecModel: GlobalModel,
         theme: object,
+        locale: object,
         optionManager: OptionManager
     ): void {
         theme = theme || {};
         this.option = null; // Mark as not initialized.
         this._theme = new Model(theme);
+        console.log('init', locale)
+        this._locale = locale;
         this._optionManager = optionManager;
     }
 
@@ -417,6 +423,25 @@ class GlobalModel extends Model<ECUnitOption> {
         return this._theme;
     }
 
+    getLocale(): LocaleOption {
+        return this._locale;
+    }
+
+    getWithLocale(localePosition: Array<string>, optionsPosition?: Array<string>, localeHandlerFn?: (text: string) => string): any {
+        console.log(optionsPosition, localePosition);
+        const locale = this.getLocale()
+        let localeText: string | any;
+        localePosition.map(t => {
+            localeText = localeText ? localeText[t] : locale[t];
+        })
+
+        if(localeHandlerFn) {
+            localeText =  localeHandlerFn(localeText);
+        }
+        console.log(localeText);
+        return localeText;
+    }
+
     setUpdatePayload(payload: Payload) {
         this._payload = payload;
     }
diff --git a/src/util/types.ts b/src/util/types.ts
index 0c7cf84..d276ad1 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -470,6 +470,7 @@ export type OptionDataValueDate = Date | string | number;
 // export type ModelOption = Dictionary<any> | any[] | string | number | boolean | ((...args: any) => any);
 export type ModelOption = any;
 export type ThemeOption = Dictionary<any>;
+export type LocaleOption = Dictionary<any>;
 
 export type DisplayState = 'normal' | 'emphasis' | 'blur' | 'select';
 export type DisplayStateNonNormal = Exclude<DisplayState, 'normal'>;
diff --git a/src/visual/aria.ts b/src/visual/aria.ts
index 7e9b00a..aa75400 100644
--- a/src/visual/aria.ts
+++ b/src/visual/aria.ts
@@ -145,7 +145,7 @@ export default function (dom, ecModel) {
         const userConfig = ariaModel.get(path);
         if (userConfig == null) {
             const pathArr = path.split('.');
-            let result = lang.aria;
+            let result = ecModel.getWithLocale(['aria']);
             for (let i = 0; i < pathArr.length; ++i) {
                 result = result[pathArr[i]];
             }
@@ -165,6 +165,6 @@ export default function (dom, ecModel) {
     }
 
     function getSeriesTypeName(type) {
-        return lang.series.typeNames[type] || '自定义图';
+        return ecModel.getWithLocale(['series', 'typeNames'])[type] || '自定义图';
     }
 }
diff --git a/test/lang.html b/test/lang.html
new file mode 100644
index 0000000..a498ab3
--- /dev/null
+++ b/test/lang.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
+    <script src="lib/esl.js"></script>
+    <script src="lib/config.js"></script>
+    <script src="lib/jquery.min.js"></script>
+    <script src="lib/facePrint.js"></script>
+    <script src="lib/testHelper.js"></script>
+    <!-- <script src="ut/lib/canteen.js"></script> -->
+    <link rel="stylesheet" href="lib/reset.css" />
+</head>
+<body>
+<style>
+    .main {
+        width: 100%;
+        height: 300px;
+    }
+</style>
+
+<div id="main0" class="main"></div>
+<div id="main1" class="main"></div>
+
+<script>
+    require(['echarts', 'i18n/langZH'], function (echarts) {
+        var option = {
+            xAxis: {},
+            yAxis: {},
+            series: {
+                type: 'line',
+                data: [[11, 22], [33, 44]]
+            },
+            toolbox: {
+                show: true,
+                feature: {
+                    restore: {},
+                    saveAsImage: {},
+                    dataZoom: {},
+                    dataView: {}
+                },
+                orient: 'vertical',
+                right: 5
+            },
+            animation: false
+        };
+
+        var chart = echarts.init(document.getElementById('main0'), null, 'ZH');
+        chart.setOption(option);
+    });
+</script>
+
+<script>
+    require(['echarts', 'i18n/langEN'], function (echarts) {
+        var option = {
+            xAxis: {},
+            yAxis: {},
+            series: {
+                type: 'line',
+                data: [[11, 22], [33, 44]]
+            },
+            toolbox: {
+                show: true,
+                feature: {
+                    restore: {},
+                    saveAsImage: {},
+                    dataZoom: {},
+                    dataView: {}
+                },
+                orient: 'vertical',
+                right: 5
+            },
+            animation: false
+        };
+
+        var chart = echarts.init(document.getElementById('main1'), null, 'EN');
+        chart.setOption(option);
+    });
+</script>
+
+
+</body>
+</html>
+


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org