Chart.js locale 选项深度解析:基于 BCP 47 的语言敏感数字格式化
2026/9/15 2:19:57 网站建设 项目流程

Chart.js locale 选项深度解析:基于 BCP 47 的语言敏感数字格式化

【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js

在 Chart.js 中,坐标轴刻度、数据标签、提示框等位置显示的数字默认只是简单的字符串拼接,而多语言应用往往需要按目标语言的习惯来格式化数字(例如德语的1.234,56、法语的千分位写法等)。本文围绕 locale 配置文档 展开,讲清楚locale选项的作用范围、取值格式、默认行为,并结合仓库源码剖析 Chart.js 是如何把 BCP 47 语言标签贯通到刻度格式化器和各类图表控制器的,以及它与ticks.format的合并关系。读完后你将能够正确配置 locale、理解其底层Intl.NumberFormat缓存机制,并知道哪些位置会受该选项影响。

locale 解决什么问题

Chart.js 的官方文档指出:对于刻度上的数字必须按照“语言敏感的数值格式化(language sensitive number formatting)”规则显示的应用,可以通过设置locale选项启用这种格式化能力。

默认情况下,图表使用的是当前运行平台(浏览器/Node.js 运行时)的默认区域设置。也就是说,如果不显式指定locale,不同用户的浏览器可能会渲染出不同样式的数字标签。对于需要保证“无论用户环境如何,图表数字格式统一”的场景(如面向特定市场的报表系统),就应该显式设置该选项。

配置项说明

locale属于图表级配置,命名空间为options

名称类型默认值说明
localestringundefined一个符合 BCP 47 的语言标签字符串,底层基于Intl.NumberFormat完成格式化

从 TypeScript 类型定义看,该选项的语义与文档一致,且明确给出了默认行为——未设置时使用用户的浏览器区域设置(见 ChartOptions 类型定义):

/** * Locale used for number formatting (using `Intl.NumberFormat`). * @default user's browser setting */ locale: string;

locale 取值:Unicode BCP 47 语言标签

locale的取值是一个 [Unicode BCP 47 locale identifier](Unicode 组织 TR35 第 47 节定义的本地化标识符)。一个完整的 BCP 47 标签由以下部分组成,各部分之间用连字符-分隔:

  1. 语言代码(必填),如enzhde
  2. (可选)书写系统代码(script code),如Hant(繁体中文);
  3. (可选)地区/国家代码(region code),如CNTWDE
  4. (可选)一个或多个变体代码(variant code);
  5. (可选)一个或多个扩展序列(extension sequences)。

常见取值示例:en-US(美式英语)、de-DE(德语-德国)、fr-FR(法语-法国)、zh-CN(简体中文)。由于底层直接交给Intl.NumberFormat解析,因此标签的合法性由 JavaScript 引擎的标准实现负责校验。

基本用法

在图表配置中把locale放在options下即可:

const chart = new Chart(ctx, { type: 'line', data: { labels: ['Q1', 'Q2', 'Q3', 'Q4'], datasets: [{ data: [1000000, 3500000, 1000000, 5000000] }] }, options: { locale: 'de-DE' // 刻度与标签按德语-德国规则格式化 } });

设置之后,Y 轴刻度1000000会显示为1.000.000(德语千分位为点号);若保持英文环境默认,则显示为1,000,000。仓库测试 scale.linear.tests.js 中有一条“Should correctly use the locale setting when getting a label”用例,正是以locale: 'de-DE'创建线性坐标轴的折线图来验证getLabelForValue的本地化输出;core.controller.tests.js 中也用locale: 'en-US'验证了 options 更新时 locale 配置的一致性。

底层实现:Intl.NumberFormat 与缓存

Chart.js 的数字格式化入口在 helpers.intl.ts,核心代码非常精简:

const intlCache = new Map<string, Intl.NumberFormat>(); function getNumberFormat(locale: string, options?: Intl.NumberFormatOptions) { options = options || {}; const cacheKey = locale + JSON.stringify(options); let formatter = intlCache.get(cacheKey); if (!formatter) { formatter = new Intl.NumberFormat(locale, options); intlCache.set(cacheKey, formatter); } return formatter; } export function formatNumber(num: number, locale: string, options?: Intl.NumberFormatOptions) { return getNumberFormat(locale, options).format(num); }

从这段实现可以得到两个关键结论:

  • 缓存机制Intl.NumberFormat实例会按locale + 序列化后的 options作为 key 缓存在一个Map中。由于new Intl.NumberFormat(...)的构造有一定开销,而刻度绘制每一帧都可能触发格式化,缓存保证了同一 locale 与格式化选项组合下只构造一次;
  • locale 透传:所有调用formatNumber的地方都会把chart.options.locale作为第一个语义参数传入,也就是说该选项是一张“全局”的格式化上下文,各模块自行读取。

作用点一:刻度数字格式化器(ticks formatter)

locale最主要的作用点是坐标轴的刻度标签。在 core.ticks.js 的Chart.Ticks.formatters.numeric中:

numeric(tickValue, index, ticks) { if (tickValue === 0) { return '0'; // 0 永不显示小数位 } const locale = this.chart.options.locale; let notation; let delta = tickValue; if (ticks.length > 1) { // 刻度值极小(< 1e-4)或极大(> 1e+15)时改用科学计数法 const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value); if (maxTick < 1e-4 || maxTick > 1e+15) { notation = 'scientific'; } delta = calculateDelta(tickValue, ticks); } const logDelta = log10(Math.abs(delta)); // NaN 保护:避免把 NaN 传给 minimumFractionDigits/maximumFractionDigits const numDecimal = isNaN(logDelta) ? 1 : Math.max(Math.min(-1 * Math.floor(logDelta), 20), 0); const options = {notation, minimumFractionDigits: numDecimal, maximumFractionDigits: numDecimal}; Object.assign(options, this.options.ticks.format); return formatNumber(tickValue, locale, options); }

这里体现了 locale 生效的完整链路:

  1. locale 读取:直接从this.chart.options.locale取图表级选项,未设置时为undefinedIntl.NumberFormat会自动回退到运行时默认区域(与文档“By default, the chart is using the default locale of the platform which is running on”一致);
  2. 小数位数推导:根据相邻刻度差delta的十进制对数反推出合理的小数位数(上限 20 位,对齐toFixed的精度上限),并防止 NaN 导致NumberFormat抛错;
  3. 科学计数法:当刻度最大值小于1e-4或大于1e+15时,notation设为'scientific',交由Intl.NumberFormat的 notation 能力输出;
  4. ticks.format的合并:最后Object.assign(options, this.options.ticks.format),意味着用户可以在scales.x.ticks.format中追加或覆盖任意Intl.NumberFormatOptions字段(如style: 'currency'currency: 'EUR'),而 locale 始终来自图表级选项。测试 core.ticks.tests.js 验证了该格式化器在空/单元素刻度数组下以locale: 'en'调用的行为。

其他受 locale 影响的数值输出位置

除刻度外,从源码调用点看,chart.options.locale还被用于以下位置:

  • 线性系坐标轴的getLabelForValue:scale.linearbase.js 中formatNumber(value, this.chart.options.locale, this.options.ticks.format),因此chart.scales.y.getLabelForValue(...)这类编程式取值同样受 locale 影响;
  • 对数坐标轴刻度:scale.logarithmic.js 同样以 locale +ticks.format格式化刻度值;
  • 饼图/环形图控制器:controller.doughnut.js 的getLabelAndValue使用formatNumber(meta._parsed[index], chart.options.locale)生成tooltip等回调里的value,所以提示框中显示的数值也会本地化;
  • 极坐标面积图控制器:controller.polarArea.js 对半径值r做同样的格式化。

可以推断,只要某处输出的是“数值字符串”,Chart.js 都倾向于走formatNumber(..., chart.options.locale, ...)这一条路径,从而保证图表内所有数字的本地化风格一致。

与相关选项的协同

  • ticks.format:它并不是 locale 的替代,而是Intl.NumberFormatOptions的补充对象。locale 决定“哪种语言的规则”,ticks.format决定“格式化的细节”(货币、符号、小数位等),二者在 core.ticks.js 中合并后一起传给Intl.NumberFormat
  • ticks.callback:若自定义刻度回调,则会绕过默认 formatter,也就不再自动读取 locale——本地化逻辑只存在于默认的数字格式化路径中;
  • 时间坐标轴:time 轴的刻度标签由 date adapter 负责格式化,仓库中 scale.time.js 未直接引用chart.options.locale,locale 对其默认标签行为无直接作用(如需本地化时间标签,应在 adapter 层面处理)。

注意事项

  1. 默认值依赖运行时:不设置locale时,格式化结果取决于用户浏览器或 Node.js 环境的默认区域。跨用户一致性要求高的场景务必显式设置;
  2. 标签必须符合 BCP 47:语言代码、书写系统、地区、变体、扩展序列之间用连字符连接;不合法的标签会由Intl.NumberFormat按标准实现处理(可能回退到默认区域);
  3. 依赖Intl全局对象:该能力完全建立在 ECMAScriptIntl.NumberFormat之上,运行环境必须提供标准Intl支持;
  4. 性能无忧:格式化器实例按locale + options缓存(见 helpers.intl.ts),频繁渲染不会重复构造NumberFormat

小结

locale是 Chart.js 中一个“小而关键”的图表级选项:一个 BCP 47 字符串,贯通了刻度标签、getLabelForValue、饼图/环形图与极坐标图的数值标签。其底层是带缓存的Intl.NumberFormat(helpers.intl.ts),并可与ticks.format灵活合并。理解这条链路后,你可以放心地在多语言报表中用一行options.locale = 'de-DE'获得完全本地化的数字展示,同时借助 core.ticks.js 与 helpers.intl.ts 这两个文件继续深入其实现细节。

【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询