您现在的位置是:网站首页 > 国际化实现文章详情

国际化实现

国际化实现

ECharts 的国际化支持让图表能够适应不同语言环境的需求。通过配置语言和地区参数,开发者可以轻松实现图表文本、提示框、图例等内容的本地化展示。国际化功能覆盖了组件文本、时间格式化、数值格式化等多个方面,为全球用户提供一致的体验。

语言包配置

ECharts 内置了多种语言包,包括中文(简体/繁体)、英文、日文等。使用前需要注册对应的语言包:

// 引入ECharts和语言包
import * as echarts from 'echarts';
import 'echarts/i18n/langEN';  // 英文
import 'echarts/i18n/langJA';  // 日文

// 注册语言
echarts.registerLocale('EN', require('echarts/i18n/langEN').default);
echarts.registerLocale('JA', require('echarts/i18n/langJA').default);

初始化图表时指定语言:

const chart = echarts.init(document.getElementById('chart'), null, {
  locale: 'EN'  // 使用英文
});

组件文本国际化

所有可视化组件都支持国际化,包括标题、图例、坐标轴等:

option = {
  title: {
    text: 'Sales Report'  // 文本会根据语言包自动转换
  },
  tooltip: {
    trigger: 'axis'
  },
  legend: {
    data: ['Sales', 'Cost']  // 图例项也会被翻译
  },
  xAxis: {
    type: 'category',
    data: ['Jan', 'Feb', 'Mar']
  },
  yAxis: {
    type: 'value'
  }
};

时间格式化

时间轴的显示会根据语言环境自动调整格式:

option = {
  xAxis: {
    type: 'time',
    axisLabel: {
      formatter: '{yyyy}-{MM}-{dd}'  // 格式会自动适配地区习惯
    }
  },
  series: [{
    data: [
      ['2023-01-01', 100],
      ['2023-01-02', 200]
    ],
    type: 'line'
  }]
};

数值格式化

数值显示支持地区差异,如千分位分隔符和小数点:

option = {
  tooltip: {
    formatter: '{b}: {c}'  // 数值会根据地区自动格式化
  },
  series: [{
    data: [1200.5, 2000.8, 1500.3],
    type: 'bar'
  }]
};

自定义语言包

当内置语言包不满足需求时,可以创建自定义语言包:

const customLocale = {
  time: {
    month: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    monthAbbr: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
    dayOfWeek: ['日', '一', '二', '三', '四', '五', '六'],
    dayOfWeekAbbr: ['日', '一', '二', '三', '四', '五', '六']
  },
  legend: {
    scroll: '滚动',
    selectAll: '全选'
  }
};

echarts.registerLocale('custom', customLocale);

动态切换语言

实现运行时语言切换需要销毁并重新初始化图表:

function changeLanguage(lang) {
  const container = document.getElementById('chart');
  const oldChart = echarts.getInstanceByDom(container);
  if (oldChart) {
    oldChart.dispose();
  }
  
  const newChart = echarts.init(container, null, {
    locale: lang
  });
  newChart.setOption(option);
}

// 切换按钮事件
document.getElementById('btn-en').addEventListener('click', () => changeLanguage('EN'));
document.getElementById('btn-ja').addEventListener('click', () => changeLanguage('JA'));

多语言图表组合

同一个页面可以展示不同语言的多个图表:

// 英文图表
const chartEN = echarts.init(document.getElementById('chart-en'), null, {
  locale: 'EN'
});
chartEN.setOption(option);

// 日文图表
const chartJA = echarts.init(document.getElementById('chart-ja'), null, {
  locale: 'JA'
});
chartJA.setOption(option);

服务端渲染的国际化

对于SSR场景,需要在服务端设置语言环境:

// Node.js 服务端代码
const echarts = require('echarts');
require('echarts/i18n/langEN');

const option = {
  title: {
    text: 'Server-side Chart'
  }
};

const chartHTML = echarts.renderToString(option, {
  locale: 'EN',
  width: 600,
  height: 400
});

第三方组件集成

当ECharts与其他UI库配合使用时,确保语言环境一致:

// 使用Vue-ECharts示例
<template>
  <v-chart :option="option" :init-options="{ locale: currentLang }" />
</template>

<script>
import { use } from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import 'echarts/i18n/langEN';

export default {
  data() {
    return {
      currentLang: 'EN',
      option: {
        title: { text: 'Vue Chart' }
      }
    }
  }
}
</script>

无障碍访问

国际化还应考虑无障碍需求,为屏幕阅读器提供支持:

option = {
  aria: {
    enabled: true,
    label: {
      description: 'This is a bar chart showing monthly sales data'
    }
  }
};

本地化扩展

除了文本翻译,还可以扩展本地化功能:

// 扩展货币符号显示
echarts.registerLocale('EN-US', {
  ...require('echarts/i18n/langEN').default,
  currency: {
    symbol: '$',
    symbolPosition: 'before',
    decimal: '.',
    thousand: ','
  }
});

// 在tooltip中使用
option = {
  tooltip: {
    formatter: (params) => {
      const value = params[0].value;
      return `${params[0].name}: ${value.toLocaleString('en-US')}$`;
    }
  }
};

时区处理

对于跨时区应用,需要正确处理时间显示:

option = {
  xAxis: {
    type: 'time',
    axisLabel: {
      formatter: (value) => {
        return echarts.format.formatTime('yyyy-MM-dd HH:mm', value, false, 'America/New_York');
      }
    }
  }
};

复杂文本处理

处理从右到左(RTL)语言布局:

// 阿拉伯语等RTL语言支持
echarts.registerLocale('AR', {
  ...require('echarts/i18n/langAR').default,
  direction: 'rtl'
});

const chart = echarts.init(document.getElementById('chart'), null, {
  locale: 'AR'
});

// 需要额外调整的样式
option = {
  grid: {
    right: '10%',
    left: '30%'  // RTL语言通常需要调整布局
  }
};

性能优化

多语言场景下的性能考虑:

// 按需加载语言包
async function loadChart(lang) {
  const locale = await import(`echarts/i18n/lang${lang.toUpperCase()}`);
  echarts.registerLocale(lang, locale.default);
  
  const chart = echarts.init(document.getElementById('chart'), null, { locale: lang });
  chart.setOption(option);
}

// 使用Webpack的魔法注释实现预加载
import(/* webpackPrefetch: true */ `echarts/i18n/lang${userLang.toUpperCase()}`);

错误处理

处理语言包加载失败的情况:

try {
  const locale = await import(`echarts/i18n/lang${lang}`);
  echarts.registerLocale(lang, locale.default);
} catch (e) {
  console.warn(`Language pack for ${lang} not found, falling back to EN`);
  const locale = await import('echarts/i18n/langEN');
  echarts.registerLocale('EN', locale.default);
  lang = 'EN';
}

测试验证

确保国际化功能正确实现的测试方法:

// 使用Jest测试不同语言环境
describe('ECharts Internationalization', () => {
  test('should display English labels', () => {
    const chart = initChart('EN');
    expect(chart.getOption().title.text).toBe('Sales Report');
  });

  test('should display Japanese labels', () => {
    const chart = initChart('JA');
    expect(chart.getOption().title.text).toBe('売上レポート');
  });
});

持续集成

在多语言项目中的CI/CD流程集成:

# .github/workflows/test.yml
jobs:
  test:
    strategy:
      matrix:
        lang: [EN, JA, ZH]
    steps:
      - run: npm test -- --lang=${{ matrix.lang }}

用户偏好保存

记住用户的语言选择:

// 从本地存储获取用户偏好
const userLang = localStorage.getItem('preferredLang') || navigator.language.slice(0, 2).toUpperCase();

// 初始化图表
const chart = echarts.init(document.getElementById('chart'), null, {
  locale: ['EN', 'JA'].includes(userLang) ? userLang : 'EN'
});

// 保存用户选择
function setLanguage(lang) {
  localStorage.setItem('preferredLang', lang);
  changeLanguage(lang);
}

框架集成示例

与React集成的完整示例:

import React, { useEffect, useRef } from 'react';
import * as echarts from 'echarts';
import 'echarts/i18n/langEN';
import 'echarts/i18n/langJA';

function ChartComponent({ language }) {
  const chartRef = useRef(null);
  let chartInstance = null;

  useEffect(() => {
    const initChart = () => {
      if (chartInstance) {
        chartInstance.dispose();
      }
      
      chartInstance = echarts.init(chartRef.current, null, {
        locale: language
      });
      
      chartInstance.setOption({
        title: { text: 'React Chart' },
        series: [{ type: 'bar', data: [100, 200, 150] }]
      });
    };

    initChart();
    
    return () => {
      if (chartInstance) {
        chartInstance.dispose();
      }
    };
  }, [language]);

  return <div ref={chartRef} style={{ width: '100%', height: '400px' }} />;
}

企业级应用实践

大型项目中的国际化架构设计:

// 国际化模块封装
class ChartI18n {
  constructor() {
    this.currentLang = 'EN';
    this.loadedLanguages = new Set(['EN']);
  }

  async setLanguage(lang) {
    if (!this.loadedLanguages.has(lang)) {
      try {
        const locale = await import(`echarts/i18n/lang${lang}`);
        echarts.registerLocale(lang, locale.default);
        this.loadedLanguages.add(lang);
      } catch (e) {
        console.error(`Failed to load language ${lang}`, e);
        lang = 'EN';
      }
    }
    this.currentLang = lang;
  }

  getInstance(dom, option) {
    return echarts.init(dom, null, {
      locale: this.currentLang
    });
  }
}

// 应用中使用
const chartI18n = new ChartI18n();
await chartI18n.setLanguage(userLang);
const chart = chartI18n.getInstance(document.getElementById('chart'));
chart.setOption(option);

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步