CreepJS Intl 报告:字段来源与缺失值
沿源码追踪 CreepJS Intl 的固定输入、构造器区域设置和错误分支,区分格式差异、缺失样本与继承评估,避免把显示结果直接当作身份或修改判定。
BotBrowser Team
CreepJS Intl 报告把格式化样本、合并后的区域设置列表和继承评估放在一起。这些值来自不同路径:少一行不一定意味着 API 不可用,措辞变化本身也不是修改证据。BotBrowser 支持时区、区域设置和语言配置,但不保证特定的 CreepJS 分类,也不保证不同浏览器构建使用区域数据时产生完全相同的文本。解释字段需要追溯生成它的调用、选项与失败路径。
TL;DR
- 固定版本的 Intl 采集函数返回六个格式化样本和一个区域设置字符串,并不是把同一种区域测试重复七遍。
- 构造器区域采集不传参数,跳过异常并去重。最终字符串不再保留构造器与区域设置的对应关系。
DisplayNames需要选项。即使单独配置的名称样本正常,其无参数区域采集尝试仍可能被跳过。- 样本回调失败会变成
undefined;外层采集失败与渲染器的htmlElementVersion条件是另外两条路径。 lied读取已有的resolvedOptions疑点,不是拿六段格式化文本与参考设备逐一比较的结果。
Contents
七个值与六次格式化调用
CreepJS 的 10aa6724cd33a1015db1574211890518cd04f0cc 修订在 src/intl/index.ts 定义相关采集函数。返回对象包含 dateTimeFormat、displayNames、listFormat、numberFormat、pluralRules、relativeTimeFormat、locale 与 lied。前六个是格式化结果。第七个可见值 locale 来自独立的构造器循环。评估则是另一个属性,并非第八段格式化句子。区分这些类别,才能避免把报告标签误当成底层 API 调用。 CreepJS 时区字段对比把解析出的标识符、历史候选缩减与两条当前日期偏移路径分开;这些时区字段的产生方式不同于这里的 Intl 格式化样本。
日期样本格式化固定数值时间戳 963644400000,要求长月份名称和长时区名称。调用没有显式提供区域设置或时区。时间戳是源码选择的输入,不是访问者打开检测器的时间。MDN 说明 DateTimeFormat.format() 接受日期或时间戳,而且格式结果可以因实现而异。因此,月份或时区名称需要附带格式化上下文,才足以支持比较。
名称样本调用 new Intl.DisplayNames(undefined, { type: 'language' }).of('en-US')。其中 en-US 是要获得名称的语言标签,不是显式要求用于输出名称的区域设置。第一个参数是 undefined,因此仍按默认规则解析输出区域。报告中的英语本地化名称,不能重新标注成访问者声明的首选语言。输入语言与输出语言在这次调用里处于不同位置。
列表样本使用 style: 'long' 与 type: 'disjunction' 格式化两条字符串 ['0', '1']。数字样本使用紧凑记法和长紧凑显示格式化 21000000。这些选项刻意选择依赖语言的表达。连词、缩写或空格发生变化,可能是格式数据变化,而非底层数值输入变化。下表把生成列表标点和紧凑数字措辞的选项与输入类型分开。
| 返回字段 | 源码调用或固定输入 | 字段保留的信息 |
|---|---|---|
dateTimeFormat | 963644400000;长月份与时区名称 | 使用默认区域和时区的日期样本 |
displayNames | type: 'language';.of('en-US') | 该语言标签的本地化名称 |
listFormat | ['0', '1'];长析取表达 | 格式化的双元素列表 |
numberFormat | 21000000;紧凑记法、长显示 | 紧凑数字格式样本 |
pluralRules | 默认选项下的 .select(1) | 复数类别标签,而非格式化数字 |
relativeTimeFormat | 1, 'year';best-fit、自动数值措辞、长样式 | 相对时间短语 |
locale | 构造器成功读取的 resolvedOptions().locale | 不带构造器标签的去重字符串 |
PluralRules().select(1) 返回与输入数字相关的类别,而 RelativeTimeFormat(...).format(1, 'year') 产生依赖语言的相对措辞。两者都没有从时钟读取当前年份。显式选项 numeric: 'auto' 允许在区域数据提供相应表达时采用词汇短语,并不要求每种语言都用数字表示。Intl 格式化指南讨论应用层的区域选择与回退,那与追踪检测器字段来源是不同任务。
构造器区域设置与丢失的来源
名为 getLocale 的辅助函数按顺序尝试七个构造器:Collator、DateTimeFormat、DisplayNames、ListFormat、NumberFormat、PluralRules 和 RelativeTimeFormat。每次尝试不传参数,读取 resolvedOptions().locale,仅在这段流程完成后追加值。各次尝试分别有 try/catch。异常返回原有累积列表,不追加具名的失败标记。采集函数随后通过 Set 去重。
这不是按构造器逐项诊断的表格。例如在一个假设案例中,多个成功构造器可能解析到同一区域设置。去重结果只保留一次,与贡献该值的构造器数量无关。如果两个构造器解析不同,结果按插入顺序保留不同值,但不保留某个值对应哪个构造器。接着 '' + locale 把数组转换为字符串。这些是源码定义的转换,不是浏览器实测捕获。
DisplayNames 具体展示了构造要求与能力的差别。MDN 规定必须提供带 type 的 options 参数。因此,即使实现支持正确配置的 Intl.DisplayNames,无参数调用仍可能抛错,辅助函数会跳过该次尝试。独立的 displayNames 样本则提供 type: 'language'。样本支持正常与区域采集遗漏该构造器可以同时成立:两次调用提出的条件不同。
Collator 呈现相反方向的不对称。它参加构造器区域循环,但六个格式化样本没有任何排序比较。它出现在渲染器构造器提示中,不代表此模块已对两条字符串排序或比较。源码可以证明它请求了解析后的区域设置;排序正确性或顺序结果需要另一项操作。这个区别防止把提示内容扩展成并不存在的测试清单。
合并的区域字符串还不同于 navigator.languages 与 HTTP Accept-Language 请求头。两者都不是此采集函数区域循环的输入。它们可以参与更广泛的分析,但不能从 CreepJS 逗号分隔的区域行中还原出来。时区、区域设置与语言分析区分这些配置和观察位置,并没有把它们的不同表示统一成普遍的相等规则。
缺失样本与渲染条件
每个格式化回调都由共享的 caniuse 包装。已检查的 src/errors/index.ts 中,回调抛错返回 undefined。Intl 使用这种回调形式,没有在后续继续遍历属性链。因此,构造器不可用、选项被拒绝或格式化时异常,都可能归结为同一个缺失样本值。辅助函数没有把异常类别附在返回值上,单凭缺失结果无法区分这些原因。
外层 getIntl() 还有自己的 try/catch。若错误到达外层作用域,模块记录一次失败测试、调用错误捕获函数,并且不返回模块结果。这不同于某个样本回调失败而其余对象仍然存在。反过来,到达源码的 passed: true 日志也不代表每个样本都有值:回调异常可能早已在外层成功路径内部被转换成 undefined。
渲染又增加一层。在固定修订中,intlHTML(fp) 进入正常 Intl 路径前检查 !fp.htmlElementVersion。该条件指向 HTML 元素报告,不是 fp.intl。条件成立时,函数返回带阻止标记的 Intl 卡片。这是所检查渲染代码的属性,不是在声称真实浏览器发生了 Intl 故障。仅凭一张带 Intl 标签的阻止卡片,无法证明某个国际化构造器不可用。
条件允许正常渲染时,渲染器解构 fp.intl || {},并用 <br> 拼接区域设置与样本。某个缺失值可能在拼接字符串里留下空位置。显示顺序是区域、日期、名称、数字、相对时间、列表与复数类别,不是返回对象的属性顺序。不核对源码顺序而只数可见行,可能把某个短语归给错误的格式化器。
| 源码状态 | 该层的结果 | 不成立的直接解释 |
|---|---|---|
| 样本回调抛错 | 该样本变为 undefined | 从空值指认某种具体异常 |
| 一个无参数构造器尝试抛错 | 区域累积跳过本次尝试 | 宣称整个构造器不受支持 |
| 外层采集函数捕获错误 | 不返回模块报告 | 认为每个样本都已逐项运行且失败 |
htmlElementVersion 缺失或为假值 | 选择阻止卡片分支 | 把显示条件直接归因于 Intl 能力 |
| 正常渲染收到缺失样本 | 拼接结果可出现空位置 | 用虚构的本地化短语补上 |
这些情况对应明确的排查顺序:定位渲染分支、确认 Intl 对象是否存在,再在仅缺单值时定位样本回调。这样不会根据显示回退反推 API 故障。支持记录也应区分“字段缺失”“模块缺失”和“阻止卡片分支”:即使界面表现接近,它们代表的证据不同。这些来自源码的案例没有宣称进行过浏览器运行。
继承疑点与格式化文本
Intl 采集函数读取七个以 .resolvedOptions 结尾的 lieProps 键,初始化 lied,分别对应前述构造器。JavaScript 的 || 保留第一个真值操作数;全部不为真时,表达式落到 false。这不是格式化六条字符串再与已保存参考短语对比的循环。产生样本的代码之后也没有把月份、紧凑数字或复数类别的变化转化为本地 lied 结论。
比较可见徽标或警告与显示文本时,这个区别很重要。在假设案例中,两份报告可以有不同格式文本,同时都没有继承的真值疑点。另一种情况可以保留相同措辞,却继承了某个 resolvedOptions 方法的疑点。这些都不是这里测得的结果,而是说明格式数据与完整性评估必须保持独立,不能从一项推导另一项。
生产端覆盖需要独立于消费端名称检查。已检查的 src/lies/index.ts 显式注册 Intl.DateTimeFormat,目标包括 format、formatRange、formatToParts 和 resolvedOptions;同时显式注册 Intl.RelativeTimeFormat 的 resolvedOptions。这两处注册并不能让消费端七键列表自动证明存在七项等价的生产端检查。此结论限定于所检查的注册,并非审计项目其他位置所有可能的修改。
| 源码层 | 具体证据 | 解释边界 |
|---|---|---|
| Intl 消费端 | 七个 .resolvedOptions 疑点键以 OR 相连 | 可能影响 lied 的名称,不是测试数量 |
| DateTimeFormat 注册 | 含 resolvedOptions 的四个具名目标 | 此修订中的显式搜索请求 |
| RelativeTimeFormat 注册 | resolvedOptions 目标 | 另一处显式搜索请求 |
| 格式化回调 | 固定样本输入与选项 | 格式化值,没有本地参考字符串判定 |
| 渲染器 | 以真值选择拒绝样式 | 已记录疑点的展示,不是概率 |
渲染器也依据真值选择拒绝类名和徽标样式。当没有选择继承疑点时,单独的 LowerEntropy.TIME_ZONE 条件还可能影响样式。因此,解释彩色徽标必须知道背后的渲染条件。颜色既不是文档定义的置信百分比,也不是应该更改哪个产品设置的诊断。源码修订、疑点键和报告层比颜色本身包含更多信息。
报告比较决策矩阵
比较首先要确定变化对象。日期措辞变化、区域合并结果变化、某个回调结果缺失与继承疑点为真,是四种不同发现。一张截图可能隐藏这些差别,尤其是在构造器循环已去重之后。把差异归因于浏览器配置之前,应保留字段名称,以及定义输入和转换的精确源码修订。
| 调查的差异 | 必需上下文 | 有边界的下一步 |
|---|---|---|
| 日期短语不同 | 固定时间戳、月份与时区选项、默认区域与时区 | 先比较格式配置,再讨论位置 |
| 紧凑数字措辞不同 | 21000000、紧凑记法、长显示与区域数据 | 核对选项一致性及运行时修订 |
| 区域合并结果的不同值更少 | 构造器成功路径与去重 | 查看各构造器结果,不猜测遗漏了哪个 API |
| 仅名称输出缺失 | 配置过的 type: 'language' 调用 | 区分回调失败与独立的无参数区域尝试 |
| 样本输出相同但疑点样式不同 | 实际继承键与渲染条件 | 检查记录的疑点,而非只看文本 |
| 整张卡片带阻止标记 | htmlElementVersion 条件及 Intl 对象是否存在 | 先确认选中的显示分支 |
日期比较中,只改变浏览器时区配置,与改变数值时间戳是不同操作。源码固定后者,让前者采用默认值。记录不能把所得日期短语称为捕获的时钟值。如果后续修订提供了显式时区,即使界面仍把它简单标为日期,比较契约也已经变化。
列表和数字比较需要在正确层级保留字符串。列表里是字符串 0 和 1,数字样本里是数值 21000000。把两者都替换为通用的“数字格式”字段,会抹掉列表标点与数字记法的区别。精确字符串差异可以促使检查区域数据,但应用选择的归一化显示,并不证明检测器原始输出一致。
区域合并字符串更短,不自动等于回归。去重可以把多个成功解析折叠成一项,异常则可以从累积过程中移除构造器尝试。这些路径需要不同的后续证据。如果没有保留每个构造器的来源,最终合并结果无法重建它。猜测某个区域对应七个构造器中的哪一个,会添加报告已不再包含的信息。
绑定源码的最小记录
支持记录可以保留比较价值,而不导出整个检测结果或稳定的身份摘要。建议字段包括 sourceRevision、reportField、constructor、fixedInput、options、collectionState 和 displayBranch。若调查继承疑点,则保留具名键及提供它的层。这些是建议的诊断字段,并不是声称 CreepJS 原生返回这种结构。
日期选项应区分省略时区和显式选择时区。名称样本应保留 type: 'language',而不只是构造器名称。区域循环记录应标明跳过了哪次尝试,而不是替它存一个虚构区域值。这些区别是决策矩阵的具体输入,不需要采集无关请求头、页面文本或个人地理历史。
BotBrowser 文档把 --bot-timezone、--bot-locale 和 --bot-languages 描述为独立控制,具有自动默认值和显式覆盖。产品文档才是这些配置主张的来源;CreepJS 与 MDN 不负责说明 BotBrowser 行为。设置可以定义预期配置,但不能证明跨版本国际化数据相同、真实地理位置或外部服务接受。单凭警告颜色不构成修改某个设置的建议依据。
观测记录缺少相关字段时,剩余结论也应收窄。缺少构造器映射,就不能得出各构造器的区域结论;回调空值不能指认异常;没有键的继承疑点不能定位方法。实际补救是获取比较所需的最小缺失输入。用设备标签替换这些未知,会让报告更确定,却让解释更不准确。
常见问题:Intl 报告
日期行表示检测器何时运行吗?
源码提供固定时间戳 963644400000,采集时刻应另行记录。长月份和时区名称选项在格式上下文中处理这条历史输入;本地化短语不会把固定数字变成当前时钟的测量结果。
支持的 DisplayNames 为什么可能不在区域采集里?
区域辅助函数不提供选项,而格式化名称样本提供 type: 'language'。MDN 的构造要求解释了它们为何可以走不同分支。辅助函数捕获构造异常后,会从累积中省略本次尝试。
一条区域记录代表只有一个构造器成功吗?
不是。Set 在转换为字符串前移除重复的成功区域值,多个构造器可以贡献同一个值。合并结果既不保留成功构造器数量,也不保留各构造器与解析区域的对应表。
lied 表示可见文本未通过参考比较吗?
固定采集函数通过七个具名键读取已有方法疑点。样本回调产生值,没有在本地与预期短语比较。解释疑点需要其来源,仅比较显示文本不能找回最初的完整性发现。
Intl 卡片被阻止能证明 Intl 已禁用吗?
已检查的显示分支判断 htmlElementVersion,所以阻止标记不足以指认国际化失败。应分别查看 Intl 对象、各回调状态与所选渲染分支,再给出 API 层面的解释。
区域结果能确定访问者的实际国家吗?
解析后的区域描述国际化服务的选择,不是位置测量。它不能替代个人偏好、国籍或当前国家。检测器字符串既不包含经同意获得的位置,也不包含支持这种推断的上下文。
来源
- CreepJS:固定版本 Intl 采集与渲染
- CreepJS:固定版本错误辅助函数
- CreepJS:固定版本完整性检查注册
- ECMA-402:国际化服务
- MDN:Intl.DisplayNames 构造器
- MDN:DateTimeFormat.format
- MDN:ListFormat.format
- MDN:NumberFormat.format
- MDN:PluralRules.select
- MDN:RelativeTimeFormat.format
- BotBrowser:时区、区域设置与语言配置
实践结论
每个值保留构造器、固定输入、选项与失败路径,Intl 报告才具备可解释性。把去重后的区域合并值与六个格式化样本分开;解释空缺或样式前,追踪继承键及真实渲染条件。比较缺少上下文时,应获取缺失字段,而不是根据一个标签赋予设备身份或修改浏览器配置。
本文属于指南: 什么是浏览器指纹?原理、风险、信号与隐私边界