Skip to content

Commit

Permalink
feat: locale 支持 (#2605)
Browse files Browse the repository at this point in the history
* feat(locale): 添加国际化 & 单测

* refactor: 暂时不暴露 GLOBAL 变量,修改 cr 建议

* fix(locale): 找不到翻译时,返回 key 值 & 修复单测
  • Loading branch information
visiky authored Jun 5, 2021
1 parent 4a9d83f commit 7d5eebe
Show file tree
Hide file tree
Showing 19 changed files with 283 additions and 13 deletions.
13 changes: 13 additions & 0 deletions __tests__/unit/core/global-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { GLOBAL, setGlobal } from '../../../src/core/global';

describe('global variables', () => {
it('global locale', () => {
// 单测环境,默认 中文
expect(GLOBAL.locale).toBe('zh-CN');
});

it('setGlobal', () => {
setGlobal({ locale: 'en-US' });
expect(GLOBAL.locale).toBe('en-US');
});
});
42 changes: 42 additions & 0 deletions __tests__/unit/core/locale-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 得引一下 src,否则无法注册国际化
import '../../../src';
import { GLOBAL, setGlobal } from '../../../src/core/global';
import { getLocale, registerLocale } from '../../../src/core/locale';
import { EN_US_LOCALE } from '../../../src/locales/en_US';
import { ZH_CN_LOCALE } from '../../../src/locales/zh_CN';

describe('locale', () => {
it('getLocale', () => {
// 单测环境,默认 中文
expect(GLOBAL.locale).toBe('zh-CN');
expect(getLocale('xxx').get('general')).toEqual(ZH_CN_LOCALE.general);

expect(getLocale('en-US').get('general')).toEqual(EN_US_LOCALE.general);

setGlobal({ locale: 'en-US' });
expect(getLocale('xxx').get('general')).toEqual(EN_US_LOCALE.general);
});

it('registerLocale', () => {
registerLocale('custom', {
locale: 'custom',
general: { increase: 'INCREASE', decrease: 'DECREASE', root: 'ROOT' },
statistic: { total: '统计' },
conversionTag: { label: '转化率' },
waterfall: { total: '累计值' },
});
expect(getLocale('custom').get(['statistic', 'total'])).toBe('统计');
expect(getLocale('custom').get('statistic.total')).toBe('统计');
// 返回 key 值
expect(getLocale('custom').get('statistic-total')).toBe('statistic-total');
// 找不到语言包,则使用全局语言包
expect(getLocale('---').get('locale')).toBe('en-US');
expect(getLocale('---').get('locale')).toBe('en-US');

setGlobal({ locale: 'custom' });
expect(getLocale('---').get('locale')).toBe('custom');
expect(getLocale('---').get(['statistic', 'total'])).toBe('统计');
expect(getLocale('---').get('statistic.total')).toBe('统计');
expect(getLocale('---').get('statistic-total')).toBe('statistic-total');
});
});
9 changes: 8 additions & 1 deletion __tests__/unit/utils/template-spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { template } from '../../../src/utils/template';

describe('template', () => {
it('template', () => {
it('default', () => {
const data = { name: 'item1', value: 1, percentage: 0.23 };
expect(template('{name}: {value}', data)).toBe('item1: 1');
expect(template('{ name }: { value }', data)).toBe('item1: 1');
Expand All @@ -13,4 +13,11 @@ describe('template', () => {
// 没有 match 的 data 原路返回
expect(template('{name}: {value}({percentage1})', data)).toBe('item1: 1({percentage1})');
});

it('data: empty', () => {
// 没有 match 的 data 原路返回
expect(template('{name}: {value}({percentage1})', {})).toBe('{name}: {value}({percentage1})');
expect(template('{name}: {value}({percentage1})', null)).toBe('{name}: {value}({percentage1})');
expect(template('{name}: {value}({percentage1})', undefined)).toBe('{name}: {value}({percentage1})');
});
});
3 changes: 3 additions & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { setGlobal } = require('./src/core/global');

setGlobal({ locale: 'zh-CN' });
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@
"testEnvironment": "jest-electron/environment",
"testTimeout": 30000,
"setupFilesAfterEnv": [
"jest-extended"
"jest-extended",
"./jest.setup.js"
],
"preset": "ts-jest",
"collectCoverage": false,
Expand All @@ -138,7 +139,7 @@
"limit-size": [
{
"path": "dist/g2plot.min.js",
"limit": "910 Kb"
"limit": "920 Kb"
},
{
"path": "dist/g2plot.min.js",
Expand Down
17 changes: 17 additions & 0 deletions src/core/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { each } from '@antv/util';
/**
* @file 全局的一些变量定义:含国际化、主题...
*/
export const GLOBAL = {
/** 全局语言 */
locale: 'en-US',
};

/**
* 全局变量设置
* @param key
* @param value
*/
export function setGlobal(datum: Record<string, any>): void {
each(datum, (v, k) => (GLOBAL[k] = v));
}
31 changes: 31 additions & 0 deletions src/core/locale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { get } from '@antv/util';
import { Locale } from '../types/locale';
import { template } from '../utils';
import { GLOBAL } from './global';

const LocaleMap = {};

/**
* register a locale
* @param locale
* @param localeObj
*/
export function registerLocale(locale: string, localeObj: Locale) {
LocaleMap[locale] = localeObj;
}

/**
* get locale of specific language
* @param lang
* @returns
*/
export function getLocale(locale: string) {
return {
get: (key: string | string[], obj?: Record<string, any>) => {
return template(
get(LocaleMap[locale], key) || get(LocaleMap[GLOBAL.locale], key) || get(LocaleMap['en-US'], key) || key,
obj
);
},
};
}
1 change: 1 addition & 0 deletions src/core/plot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type PickOptions = Pick<
| 'syncViewPadding'
| 'supportCSSTransform'
| 'limitInPlot'
| 'locale'
>;

const SOURCE_ATTRIBUTE_NAME = 'data-chart-source-type';
Expand Down
13 changes: 13 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ export const version = '2.3.21';
import * as G2 from '@antv/g2';
export { G2 };

// 国际化处理
import { registerLocale } from './core/locale';
import { EN_US_LOCALE } from './locales/en_US';
import { ZH_CN_LOCALE } from './locales/zh_CN';
/** default locale register */
registerLocale('en-US', EN_US_LOCALE);
registerLocale('zh-CN', ZH_CN_LOCALE);
/** 透出 国际化 工具函数,便于使用 */
export { registerLocale };

/** 全局变量 */
export { setGlobal } from './core/global';

/** G2Plot 的 Plot 基类 */
export { Plot } from './core/plot';

Expand Down
31 changes: 31 additions & 0 deletions src/locales/en_US.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Locale } from '../types/locale';

export const EN_US_LOCALE: Locale = {
locale: 'en-US',

// General
general: {
increase: 'Increase',
decrease: 'Decrease',
root: 'Root',
},

// Plot Components
/** statistic text component */
statistic: {
total: 'Total',
},
/** conversionTag component */
conversionTag: {
label: 'Conversion rate',
},
legend: {},
tooltip: {},
slider: {},
scrollbar: {},

// Plots
waterfall: {
total: 'Total',
},
};
31 changes: 31 additions & 0 deletions src/locales/zh_CN.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Locale } from '../types/locale';

export const ZH_CN_LOCALE: Locale = {
locale: 'zh-CN',

// 通用
general: {
increase: '增加',
decrease: '减少',
root: '初始',
},

// 按照图表组件
/** 中心文本 */
statistic: {
total: '总计',
},
/** 转化率组件 */
conversionTag: {
label: '转化率',
},
legend: {},
tooltip: {},
slider: {},
scrollbar: {},

// 按照图表类型
waterfall: {
total: '总计',
},
};
10 changes: 8 additions & 2 deletions src/plots/funnel/adaptor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Params } from '../../core/adaptor';
import { interaction, animation, theme, scale, annotation, tooltip } from '../../adaptor/common';
import { getLocale } from '../../core/locale';
import { flow, deepAssign } from '../../utils';
import { conversionTagFormatter } from '../../utils/conversion';
import { FunnelOptions } from './types';
Expand All @@ -24,7 +25,9 @@ import { FUNNEL_CONVERSATION, FUNNEL_MAPPING_VALUE, FUNNEL_PERCENT } from './con
*/
function defaultOptions(params: Params<FunnelOptions>): Params<FunnelOptions> {
const { options } = params;
const { compareField, xField, yField } = options;
const { compareField, xField, yField, locale } = options;
const i18n = getLocale(locale);

const defaultOption = {
minSize: 0,
maxSize: 1,
Expand Down Expand Up @@ -68,7 +71,10 @@ function defaultOptions(params: Params<FunnelOptions>): Params<FunnelOptions> {
offsetY: 0,
style: {},
// conversionTag 的计算和显示逻辑统一保持一致
formatter: (datum) => `转化率: ${conversionTagFormatter(...(datum[FUNNEL_CONVERSATION] as [number, number]))}`,
formatter: (datum) =>
`${i18n.get(['conversionTag', 'label'])}: ${conversionTagFormatter(
...(datum[FUNNEL_CONVERSATION] as [number, number])
)}`,
},
};

Expand Down
7 changes: 5 additions & 2 deletions src/plots/pie/adaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Params } from '../../core/adaptor';
import { legend, animation, theme, state, annotation } from '../../adaptor/common';
import { getMappingFunction } from '../../adaptor/geometries/base';
import { interval } from '../../adaptor/geometries';
import { getLocale } from '../../core/locale';
import { Interaction } from '../../types/interaction';
import { flow, template, transformLabel, deepAssign, renderStatistic, processIllegalData } from '../../utils';
import { Data, Datum } from '../../types';
Expand Down Expand Up @@ -176,7 +177,9 @@ function label(params: Params<PieOptions>): Params<PieOptions> {
* 2. 默认使用 meta 的 formatter
*/
export function transformStatisticOptions(options: PieOptions): PieOptions {
const { innerRadius, statistic, angleField, colorField, meta } = options;
const { innerRadius, statistic, angleField, colorField, meta, locale } = options;

const i18n = getLocale(locale);

if (innerRadius && statistic) {
let { title: titleOpt, content: contentOpt } = deepAssign({}, DEFAULT_OPTIONS.statistic, statistic);
Expand All @@ -189,7 +192,7 @@ export function transformStatisticOptions(options: PieOptions): PieOptions {
if (datum) {
return datum[colorField];
}
return !isNil(titleOpt.content) ? titleOpt.content : '总计';
return !isNil(titleOpt.content) ? titleOpt.content : i18n.get(['statistic', 'total']);
},
},
titleOpt
Expand Down
43 changes: 39 additions & 4 deletions src/plots/waterfall/adaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,31 @@ import { Datum } from '../../types';
import { Params } from '../../core/adaptor';
import { interaction, animation, theme, state, scale, annotation } from '../../adaptor/common';
import { interval } from '../../adaptor/geometries';
import { getLocale } from '../../core/locale';
import { findGeometry, flow, transformLabel, deepAssign } from '../../utils';
import { Y_FIELD, ABSOLUTE_FIELD, DIFF_FIELD, IS_TOTAL } from './constant';
import { WaterfallOptions } from './types';
import { transformData } from './utils';
import './shape';

/**
* 处理默认配置项
* @param params
* @returns
*/
function defaultOptions(params: Params<WaterfallOptions>): Params<WaterfallOptions> {
const { locale, total } = params.options;

const localeTotalLabel = getLocale(locale).get(['waterfall', 'total']);

if (total && typeof total.label !== 'string' && localeTotalLabel) {
// @ts-ignore
params.options.total.label = localeTotalLabel;
}

return params;
}

/**
* 字段
* @param params
Expand Down Expand Up @@ -109,23 +128,26 @@ function axis(params: Params<WaterfallOptions>): Params<WaterfallOptions> {
*/
function legend(params: Params<WaterfallOptions>): Params<WaterfallOptions> {
const { chart, options } = params;
const { legend, total, risingFill, fallingFill } = options;
const { legend, total, risingFill, fallingFill, locale } = options;

const i18n = getLocale(locale);

if (legend === false) {
chart.legend(false);
} else {
const items = [
{
name: '增加',
name: i18n.get(['general', 'increase']),
value: 'increase',
marker: { symbol: 'square', style: { r: 5, fill: risingFill } },
},
{
name: '减少',
name: i18n.get(['general', 'decrease']),
value: 'decrease',
marker: { symbol: 'square', style: { r: 5, fill: fallingFill } },
},
];

if (total) {
items.push({
name: total.label || '',
Expand Down Expand Up @@ -209,5 +231,18 @@ export function tooltip(params: Params<WaterfallOptions>): Params<WaterfallOptio
* @param params
*/
export function adaptor(params: Params<WaterfallOptions>) {
return flow(geometry, meta, axis, legend, tooltip, label, state, theme, interaction, animation, annotation())(params);
return flow(
defaultOptions,
theme,
geometry,
meta,
axis,
legend,
tooltip,
label,
state,
interaction,
animation,
annotation()
)(params);
}
1 change: 0 additions & 1 deletion src/plots/waterfall/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export const DEFAULT_OPTIONS = {
},
/** default: show total */
total: {
label: '总计',
style: {
fill: 'rgba(0, 0, 0, 0.25)',
},
Expand Down
Loading

0 comments on commit 7d5eebe

Please sign in to comment.