资讯动态

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

发布时间:2026/9/5 18:27:12 来源:尧图企业网站定制
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 users browser setting */ locale: string;locale 取值Unicode BCP 47 语言标签locale的取值是一个 [Unicode BCP 47 locale identifier]Unicode 组织 TR35 第 47 节定义的本地化标识符。一个完整的 BCP 47 标签由以下部分组成各部分之间用连字符-分隔语言代码必填如en、zh、de可选书写系统代码script code如Hant繁体中文可选地区/国家代码region code如CN、TW、DE可选一个或多个变体代码variant code可选一个或多个扩展序列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 Mapstring, 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 formatterlocale最主要的作用点是坐标轴的刻度标签。在 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或极大 1e15时改用科学计数法 const maxTick Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value); if (maxTick 1e-4 || maxTick 1e15) { 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 生效的完整链路locale 读取直接从this.chart.options.locale取图表级选项未设置时为undefinedIntl.NumberFormat会自动回退到运行时默认区域与文档“By default, the chart is using the default locale of the platform which is running on”一致小数位数推导根据相邻刻度差delta的十进制对数反推出合理的小数位数上限 20 位对齐toFixed的精度上限并防止 NaN 导致NumberFormat抛错科学计数法当刻度最大值小于1e-4或大于1e15时notation设为scientific交由Intl.NumberFormat的 notation 能力输出与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还被用于以下位置线性系坐标轴的getLabelForValuescale.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.NumberFormatticks.callback若自定义刻度回调则会绕过默认 formatter也就不再自动读取 locale——本地化逻辑只存在于默认的数字格式化路径中时间坐标轴time 轴的刻度标签由 date adapter 负责格式化仓库中 scale.time.js 未直接引用chart.options.localelocale 对其默认标签行为无直接作用如需本地化时间标签应在 adapter 层面处理。注意事项默认值依赖运行时不设置locale时格式化结果取决于用户浏览器或 Node.js 环境的默认区域。跨用户一致性要求高的场景务必显式设置标签必须符合 BCP 47语言代码、书写系统、地区、变体、扩展序列之间用连字符连接不合法的标签会由Intl.NumberFormat按标准实现处理可能回退到默认区域依赖Intl全局对象该能力完全建立在 ECMAScriptIntl.NumberFormat之上运行环境必须提供标准Intl支持性能无忧格式化器实例按locale options缓存见 helpers.intl.ts频繁渲染不会重复构造NumberFormat。小结locale是 Chart.js 中一个“小而关键”的图表级选项一个 BCP 47 字符串贯通了刻度标签、getLabelForValue、饼图/环形图与极坐标图的数值标签。其底层是带缓存的Intl.NumberFormathelpers.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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价