v1.3.3: 中英双语 i18n + 回归时序根治

i18n(竞品 7 家全有、Aurora 唯一还缺的一线能力)
- site/i18n.js:330 条文案字典,顶栏「中 / EN」切换,偏好存 aa-lang,
  <html lang> 与 document.title 同步
- 设计取舍:以中文源串为字典键,而非抽象 key。中文是规范原文语言也是
  app.js 现有字面量;源串作键意味着未收录文案自动回退原文,不会出现
  空白或 key 泄漏
- 覆盖:导航/侧栏/首页 Hero 与设计原则/总览/快速开始/设计规范(含令牌
  导出区)/For Agents 全表/更新日志/组件详情页(何时使用、API 三表、
  无障碍键盘表、Do&Don't、设计契约、实现资源、相关组件)/Playground/
  主题面板/搜索弹窗/FAB 提示
- 语言感知显示:组件名主次调换(中文模式主显中文名,英文模式主显英文
  名),详情页大标题不再重复;分类名走 CAT_EN 不占字典

修复回归时序(根治偶发)
- DensitySwitcher 对比度偶发失败:断言在演示页内联脚本执行完之前就跑了,
  读到 is-active 尚未应用的中间态(白字未落到品牌蓝底)。单页打开通过、
  并发收集器里偶发失败
- 根因是固定帧数等待(load + 双 rAF)在多个 iframe 抢主线程时不够稳。
  改为就绪轮询:readyState === 'complete' 且 DOM 连续 3 次采样(约 48ms)
  无变化才断言,另设约 4.8s 超时兜底
- 验证:四次连跑全部 100%,偶发不再复现

修复 i18n 接入中的三个真实缺陷
- TDZ 顺序:KIND_KEYS 等模块级常量在 I18N/T 定义前调用 T(),抛
  Cannot read properties of undefined。改为存中文源串、渲染时求值
  (模块级预先求值还会导致语言切换后不更新)
- 局部变量遮蔽:renderDesign 内原有 var T = data.tokens 遮蔽全局翻译
  函数,导致设计规范页整个渲染失败。改名 TOKENS
- 模板拼接括号:el() 调用在包装 T() 后少一个右括号

验证
- 9 个路由 × 2 语言全部正常渲染(中英文内容均非空且确实不同)
- 回归保持 100%:961 断言 / 925 通过 / 0 失败 / 79 页全通过 / N/A 36
This commit is contained in:
aurora-admin
2026-09-11 17:15:42 +08:00
parent 7c9516011b
commit cbed5ba7ca
11 changed files with 1012 additions and 253 deletions
+24
View File
@@ -4,6 +4,30 @@
## [Unreleased]
## [1.3.3] - 2026-09-11
### Added — 中英双语(i18n)
- `site/i18n.js`:330 条文案字典,顶栏新增 `中 / EN` 切换器,偏好存 `localStorage['aa-lang']`,`<html lang>` 与 `document.title` 同步。
- **设计取舍**:以「中文源串」作字典键而非抽象 key。中文是规范原文语言(组件1~10.txt)也是 app.js 现有字面量;源串作键意味着未收录文案自动回退原文,不会出现空白或 key 泄漏。
- 覆盖范围:导航 / 侧栏 / 首页 Hero 与设计原则 / 总览 / 快速开始 / 设计规范(含令牌导出区)/ For Agents 全表 / 更新日志 / 组件详情页(何时使用、API 三表、无障碍键盘表、Do&Don't、设计契约、实现资源、相关组件)/ Playground / 主题面板 / 搜索弹窗 / FAB 提示。
- 语言感知的显示逻辑:
- 组件名主次调换(中文模式主显中文名,英文模式主显英文名),详情页大标题不再重复;
- 侧栏分类名走 `CAT_EN`,不占字典;
- 动态生成的键盘表、插槽说明按语言重算。
### Fixed — 回归时序(根治偶发)
- **DensitySwitcher 对比度偶发失败**:断言在演示页内联脚本执行完之前就跑了,读到 `is-active` 尚未应用的中间态(白字未落到品牌蓝底 → 2.51:1)。单页打开时通过、并发收集器里偶发失败。
- 根因是固定帧数等待(`load` + 双 `requestAnimationFrame`)在多个 iframe 抢主线程时不够稳。改为**就绪轮询**:`readyState === 'complete'` 且 DOM 连续 3 次采样(约 48ms)无变化才断言,另设约 4.8s 超时兜底避免卡死。
- 验证:**四次连跑全部 100%**(961 断言 / 0 失败 / 79 页全通过),偶发不再复现。
### Fixed — i18n 接入过程中的三个真实缺陷
- **TDZ 顺序**:`KIND_KEYS` 等模块级常量在 `I18N`/`T` 定义之前调用了 `T()`,抛 `Cannot read properties of undefined (reading 'T')`。已改为存中文源串、渲染时求值(模块级预先求值还会导致语言切换后不更新)。
- **局部变量遮蔽**:`renderDesign` 内原有 `var T = data.tokens;` 遮蔽了全局翻译函数,导致设计规范页整个渲染失败。改名 `TOKENS`。
- **模板拼接括号**:`el()` 调用在包装 `T()` 后少一个右括号,已修正。
### Changed
- 回归基线:961 断言 / 925 通过 / **100%** / 79 页全通过 / N/A 36,四次连跑一致。
## [1.3.2] - 2026-09-11
### Added — 契约第三批:全量契约化 79/79
+447 -229
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+473
View File
@@ -0,0 +1,473 @@
/* Aurora Admin 文档站国际化 (i18n)
*
* 设计取舍:以「中文源串」作为字典键,英文为值。
* 理由:中文是规范原文语言(组件1~10.txt),也是 app.js 里现有的字面量;
* 以源串为键意味着未收录的文案自动回退中文,不会出现空白或 key 泄漏。
* 纯前端、零依赖,与整站零运行时依赖的约束一致。
*
* 用法:T('组件总览') → zh 模式下返回原文,en 模式下返回 'Components'
* 当前语言存 localStorage['aa-lang'],切换后整站重渲染。
*/
(function () {
'use strict';
var EN = {
/* ---------- 顶栏 / 导航 ---------- */
'组件库': 'Components',
'搜索组件…': 'Search…',
'框架': 'Stack',
'首页': 'Home',
'组件': 'Components',
'快速开始': 'Getting Started',
'设计规范': 'Design Tokens',
'更新日志': 'Changelog',
'AI 消费': 'For Agents',
'选择你的技术栈,文档将只展示对应框架的内容': 'Pick your stack — the docs will only show files for it',
'搜索组件(中文 / 英文 / slug)': 'Search components (name / slug)',
'↑↓ 选择': '↑↓ Navigate',
'Enter 跳转': 'Enter Open',
'Esc 关闭': 'Esc Close',
/* ---------- 侧边栏 / 分类 ---------- */
'组件总览': 'All Components',
'通用': 'General',
'导航': 'Navigation',
'数据录入': 'Data Entry',
'数据展示': 'Data Display',
'反馈': 'Feedback',
'工具与系统': 'System',
'未分类': 'Uncategorized',
'本页目录': 'On This Page',
/* ---------- 批次 ---------- */
'核心规范': 'Core',
'第': 'Batch ',
'批': '',
'核心组件': 'Core',
'扩展组件': 'Extension',
'规格批次': 'Spec Batch',
/* ---------- 首页 ---------- */
'Aurora Admin 组件库': 'Aurora Admin',
'理性、高效、克制的 B 端中后台设计系统——信息密度适中,层级清晰,交互反馈即时。':
'A rational, efficient and restrained design system for B2B admin panels — moderate information density, clear hierarchy, immediate feedback.',
'浏览组件 →': 'Browse components →',
'场景示范': 'Live Scenario',
'测试总览': 'Test Overview',
'个大类': 'categories',
'端实现': 'platforms',
'份规范': 'spec docs',
'测试页': 'test pages',
'大类': 'Categories',
' 大类。基于 Aurora Admin 设计系统规范构建,提供 H5 / React / Vue 2 / Vue 3 四端实现。':
' categories. Built on the Aurora Admin specification with H5 / React / Vue 2 / Vue 3 implementations.',
'核心规范组件': 'Core',
'设计令牌': 'Design Tokens',
'通过率 ': 'Pass rate ',
'headless 回归 ': 'headless regression, ',
'断言通过': 'assertions passed',
'设计原则': 'Design Principles',
'一致优先': 'Consistency First',
'同类组件使用相同的尺寸、颜色与间距,跨页面保持一致体验。':
'Same sizes, colors and spacing across similar components, so the experience holds from page to page.',
'清晰高效': 'Clarity & Efficiency',
'信息层级明确,操作路径最短,避免过度装饰。':
'Explicit hierarchy, shortest path to the action, no decoration for its own sake.',
'反馈及时': 'Immediate Feedback',
'所有操作都有加载、成功、失败三类状态反馈。':
'Every action carries loading, success and failure feedback.',
'无障碍': 'Accessibility',
'满足键盘操作与焦点管理,正文对比度 ≥ 4.5:1。':
'Full keyboard operation with focus management; body text contrast ≥ 4.5:1.',
'定位到本组件的规格原文章节': 'Jump to this component’s spec section',
/* ---------- 总览 ---------- */
'个组件(核心': ' components (core ',
' · 扩展': ' · extension ',
'),覆盖 ': '), covering ',
'。基于 Aurora Admin 设计系统规范构建,提供 H5 / React / Vue 2 / Vue 3 四端实现。':
'. Built on the Aurora Admin specification with H5 / React / Vue 2 / Vue 3 implementations.',
'预览': 'Preview',
'加载预览…': 'Loading preview…',
'无匹配组件': 'No matching components',
'无匹配组件(已尝试模糊匹配)': 'No matching components (fuzzy match tried)',
'全部': 'All',
'过滤组件…': 'Filter components…',
/* ---------- 快速开始 ---------- */
'了解如何在本项目中使用 Aurora Admin 组件:引入设计令牌、按端取用组件源码、以及目录与命名约定。':
'How to use Aurora Admin in your project: import the tokens, pick component sources per platform, and follow the directory and naming conventions.',
'引入设计令牌': 'Import Design Tokens',
'所有组件都基于同一份 CSS 变量令牌。在使用任何组件前,先在页面中引入令牌文件:':
'Every component shares one set of CSS variable tokens. Import the token file before using any component:',
'如需结构化的令牌数据(供工具消费),可读取同目录的 <code>css.json</code>;聚合组件样式见 <code>components.css</code>。':
'For structured token data (tool consumption), read <code>css.json</code> in the same directory; aggregated component styles live in <code>components.css</code>.',
'按端使用组件': 'Use Components per Platform',
'每个组件在 <code>frameworks/</code> 下有五种形态(H5 / CSS / React / Vue 2 / Vue 3),按你的技术栈取用:':
'Each component ships in five forms under <code>frameworks/</code> (H5 / CSS / React / Vue 2 / Vue 3). Take the one matching your stack:',
'端': 'Platform',
'文件': 'File',
'使用方式': 'How to use',
'直接在浏览器打开即为完整演示页;将结构与内联样式拷贝进你的页面':
'Opens as a complete demo page in the browser; copy the markup and inline styles into your page',
'将 JSX 与 CSS 拷入工程,按需改造数据绑定': 'Copy the JSX and CSS into your project, adapt the data binding as needed',
'Options API 单文件组件,直接注册使用': 'Options API single-file component, register and use directly',
'<script setup> 组合式 API,直接注册使用': '<script setup> Composition API, register and use directly',
'样式令牌': 'Style tokens',
'所有变量以 --au- 前缀暴露,可整体引入或按需拷贝':
'All variables are exposed with the --au- prefix; import wholesale or copy as needed',
'目录结构': 'Directory Structure',
'命名约定': 'Naming Conventions',
'组件 slug 为小写(如 button、sidemenu),文件名前缀为 PascalCase(如 SideMenu.vue3.vue)':
'Component slugs are lowercase (button, sidemenu); file name prefixes are PascalCase (SideMenu.vue3.vue)',
'H5 演示页自带演示数据与交互,可直接作为视觉验收基准':
'H5 demo pages ship with sample data and interaction — use them as the visual acceptance baseline',
'组件 ↔ 规格批次 ↔ 实现的权威映射见 .design_library/aurora-admin/components/index.json':
'The authoritative component ↔ spec batch ↔ implementation mapping lives in .design_library/aurora-admin/components/index.json',
'全部组件默认桌面端优先(最小宽度 1280px),不推荐移动端场景':
'All components are desktop-first (min width 1280px); mobile scenarios are not recommended',
/* ---------- For Agents ---------- */
'For Agents · AI 消费入口': 'For Agents',
'本站全部数据机器可读:无需解析 HTML,一次抓取 data.json 即可获得 79 个组件、设计令牌与分类元数据。本页汇总 Agent 可直接消费的资源、数据形状与使用规则。':
'Everything on this site is machine-readable: no HTML parsing needed — one fetch of data.json yields all 79 components, design tokens and category metadata. This page lists the resources an agent can consume directly, their data shapes, and the usage rules.',
'机器可读资源': 'Machine-readable Resources',
'资源': 'Resource',
'路径': 'Path',
'说明': 'Description',
'全量组件数据(首选)': 'Full component data (preferred)',
'meta + 分类 + 设计令牌 + 79 个组件(规格摘要、5 端文件路径、API 提炼),单次请求即可':
'meta + categories + design tokens + 79 components (spec summary, 5-platform file paths, extracted API) in a single request',
'组件注册表': 'Component registry',
'组件 ↔ 规格批次 ↔ 实现文件的权威映射(schemaVersion 3)':
'Authoritative component ↔ spec batch ↔ implementation mapping (schemaVersion 3)',
'核心组件契约 ×6': 'Core component contracts ×79',
'变体维度、代表变体、使用要点、结构解剖、不发明与未明示清单':
'Variant dimensions, representative variants, usage hints, anatomy, do-not-invent and unknown lists',
'设计令牌(结构化)': 'Design tokens (structured)',
'全部 CSS 变量的 JSON 形态:颜色 / 字体 / 间距 / 圆角 / 阴影 / 控件高度':
'All CSS variables as JSON: color / typography / spacing / radius / shadow / control height',
'设计令牌(CSS)': 'Design tokens (CSS)',
'可直接 <link> 引入的令牌源文件,所有色值必须取自 au-* 变量':
'Token source file, linkable directly; all colors must come from au-* variables',
'组件样式聚合': 'Aggregated component styles',
'全部组件样式的单文件聚合': 'Single-file aggregate of all component styles',
'组件实现源码 ×5 端': 'Component sources ×5 platforms',
'H5 / React / Vue 2 / Vue 3 形态,文件名前缀为 PascalCase':
'H5 / React / Vue 2 / Vue 3 forms, PascalCase file name prefixes',
'组件测试页 ×79': 'Component test pages ×79',
'断言结果标注 data-assert / data-status="pass|fail",可机读回归':
'Assertion results are marked with data-assert / data-status="pass|fail" for machine-readable regression',
'LLM 入口清单': 'LLM entry index',
'本页内容的 llms.txt 形态,供爬虫与 Agent 定位': 'llms.txt form of this page, for crawlers and agents',
'data.json 数据形状': 'data.json Shape',
'字段': 'Field',
'内容': 'Contents',
'version(与 CHANGELOG 最新版本同步)、total=79、core/extension 数量、brand=#2F54EB、generated 构建时间':
'version (synced with the latest CHANGELOG entry), total=79, core/extension counts, brand=#2F54EB, generated timestamp',
'六大分类及组件计数:general / navigation / input / display / feedback / system':
'Six categories with component counts: general / navigation / input / display / feedback / system',
'设计令牌数组:name(au-*)、value、comment(中文用途说明)':
'Design token array: name (au-*), value, comment (usage note)',
'小写 slug、中文名 + 英文名、core 或 extension':
'Lowercase slug, Chinese + English name, core or extension',
'规格批次 1-10、来源规格文件、规格章节原文(含"何时使用"等)':
'Spec batch 1-10, source spec file, raw spec section text (including “when to use”)',
'核心组件契约:dims(变体维度)、variants、usage(使用要点)、structure、anatomy、doNot(不发明)、unknowns(未明示)':
'Component contract: dims, variants, usage, structure, anatomy, doNot, unknowns',
'5 端实现文件相对路径与字节数:html / css / jsx / vue2 / vue3':
'Relative paths and byte sizes of the 5 platform files: html / css / jsx / vue2 / vue3',
'消费示例': 'Consumption Example',
'抓取 data.json 并按分类筛选组件、读取令牌与契约的最小示例:':
'Minimal example: fetch data.json, filter components by category, read tokens and contracts:',
'使用规则': 'Usage Rules',
'不发明:组件变体不得超出契约 dims 声明的维度与取值;扩展组件以规格原文 specLines 为准':
'Do not invent: variants must stay within the dimensions and values declared in the contract dims; for extension components follow the raw specLines',
'不硬编码颜色:所有色值取自 tokens 中的 au-* 变量,品牌主色 #2F54EB,语义色独立于品牌色':
'No hardcoded colors: every color comes from au-* tokens; brand is #2F54EB and semantic colors are independent of it',
'尊重未明示:契约 unknowns 列出的项规格未定义,生成前应向用户澄清而非假设':
'Respect unknowns: items listed in contract unknowns are undefined by the spec — ask the user rather than assume',
'文案遵循内容规范:按钮用动词短语(新建 / 编辑 / 删除),反馈文案明确可操作,不使用 emoji':
'Copy follows the content guidelines: buttons use verb phrases (Create / Edit / Delete), feedback is explicit and actionable, no emoji',
'桌面端优先:整套体系最小宽度 1280px,不适用于移动端场景':
'Desktop-first: the whole system assumes a 1280px minimum width and does not target mobile',
/* ---------- 更新日志 ---------- */
'按 SemVer 记录的重要变更,与仓库根目录 CHANGELOG.md 同源(构建时自动解析注入)。':
'Notable changes recorded per SemVer, sourced from the repository CHANGELOG.md (parsed and injected at build time).',
'暂无结构化日志数据:请运行 build-site.ps1 重新生成,构建脚本会解析 CHANGELOG.md 并注入 data.js。':
'No structured changelog data yet — run build-site.ps1 to regenerate; the build parses CHANGELOG.md into data.js.',
'暂无数据': 'No data yet',
/* ---------- 组件详情页 ---------- */
'何时使用': 'When to Use',
'本组件暂无独立规格说明,参见 ': 'No standalone spec for this component; see ',
'代码演示': 'Demos',
'基础用法': 'Basic Usage',
'完整的组件演示,包含常用状态与场景。': 'A complete component demo covering common states and scenarios.',
'视觉演示为 H5 形态(各端实现视觉一致);下方代码与资源已按「':
'The visual demo is the H5 form (all platforms render identically); the code and resources below are filtered to “',
'」过滤。': '”.',
'组件 API 规范': 'Component API',
'组件 API': 'API',
'无障碍与键盘交互': 'Accessibility & Keyboard',
'无障碍指引': 'Accessibility',
'设计避坑指南 (Do\'s & Don\'ts)': 'Do’s & Don’ts',
'设计避坑': 'Guidelines',
'设计契约': 'Design Contract',
'实现资源': 'Implementation',
'相关组件': 'Related Components',
'按「相似功能 / 常搭配使用」维度整理,点击跳转。':
'Grouped by “similar function / often used together” — click to jump.',
'同属': 'Same category: ',
'分类': '',
'遵循 W3C WAI-ARIA 规范,组件内置标准键盘交互与屏幕阅读器无障碍支持。':
'Follows W3C WAI-ARIA: standard keyboard interaction and screen reader support are built in.',
'属性 (Props)': 'Props',
'事件 (Events / Emits)': 'Events / Emits',
'插槽 (Slots)': 'Slots',
'参数名': 'Prop',
'事件名': 'Event',
'插槽名': 'Slot',
'类型': 'Type',
'默认值': 'Default',
'必填': 'Required',
'可选': 'Optional',
'回调参数': 'Callback args',
'按键': 'Key',
'交互说明': 'Interaction',
'将焦点移入当前组件或在可聚焦子项间依次流转':
'Move focus into this component, or cycle through its focusable children',
'反向移动焦点到上一个交互元素': 'Move focus back to the previous interactive element',
'触发按钮点击动作,执行绑定的业务逻辑': 'Activate the button and run its bound logic',
'确认输入内容或提交当前表单': 'Confirm input or submit the current form',
'清除当前临时输入或收起下拉联想菜单': 'Clear the current input or collapse the suggestion menu',
'展开或收起下拉候选列表': 'Expand or collapse the dropdown list',
'在下拉选项菜单中高亮切换候选项目': 'Move the highlight between dropdown options',
'收起下拉菜单并保持输入框焦点': 'Collapse the dropdown and keep focus in the input',
'快捷关闭当前弹窗并还原底层焦点': 'Close the current dialog and restore the underlying focus',
'Tab (循环锁定)': 'Tab (focus trap)',
'弹窗激活时,焦点锁定在弹窗内部,不会跳出到蒙层外部背景':
'While a dialog is open, focus stays trapped inside it and cannot escape to the background',
'在导航标签项或步骤之间切换激活状态': 'Switch the active state between tabs or steps',
'快速定位到首个或末尾标签项': 'Jump to the first or last tab',
'在数据行或树形节点之间上下导航': 'Navigate up and down between rows or tree nodes',
'快速切换当前行或节点的勾选状态': 'Toggle the checked state of the current row or node',
'✅ 推荐做法 (Do)': '✅ Do',
'❌ 避免反模式 (Don\'t)': '❌ Don’t',
'契约 JSON ✓': 'Contract JSON ✓',
'API 源码提炼': 'API from source',
'该组件暂无契约 JSON,API 表由 5 端源码自动提炼':
'No contract JSON for this component; the API table is extracted from the 5 platform sources',
'测试页 →': 'Test page →',
'场景速览(': 'Scenarios (',
' 个典型用法)': ' typical usages)',
'当前框架:<strong>': 'Current stack: <strong>',
'</strong> —— 仅展示该端需要的文件。切换框架请使用顶部选择器。':
'</strong> — only files needed by this platform are shown. Use the top selector to switch.',
'新窗口打开': 'Open in new tab',
'大小': 'Size',
'操作': 'Action',
'查看其他 ': 'View the other ',
' 个端的文件': ' platform files',
'变体维度': 'Variant Dimensions',
'代表变体': 'Representative Variants',
'使用要点': 'Usage Hints',
'结构规格': 'Structure',
'结构解剖': 'Anatomy',
'不要自行发明:': 'Do not invent:',
'规范未明示(待补充):': 'Undefined by spec (to be clarified):',
'上一篇': 'Previous',
'下一篇': 'Next',
'同属弹层家族,按承载内容与打断强度选择': 'Same overlay family — pick by content and interruption level',
'数据列表的不同形态,按层级与信息量选择': 'Different forms of data lists — pick by hierarchy and density',
'操作触发与选项切换的相近形态': 'Related forms for triggering actions and switching options',
'输入类组件,按提示方式与约束选择': 'Input components — pick by hint style and constraints',
'选择类组件,按层级深度与数量选择': 'Selection components — pick by depth and count',
'数值输入的相近形态': 'Related numeric input forms',
'卡片式选项与开关组合': 'Card-style options and switch groups',
'流程与视图组织的相近形态': 'Related forms for organising flows and views',
/* ---------- Playground ---------- */
'▶ 在线试玩': '▶ Live Playground',
'复位': 'Reset',
'退出试玩': 'Exit',
'在线编辑 H5 演示源码,实时预览效果(不影响源文件)':
'Edit the H5 demo source and preview live (source file untouched)',
'● 试玩中': '● Playing',
'展开代码': 'Show code',
'复制源码': 'Copy source',
'复制': 'Copy',
'已复制 ✓': 'Copied ✓',
'试玩': 'Play',
'仅 H5 形态支持在线试玩': 'Only the H5 form supports live playground',
/* ---------- 主题面板 ---------- */
'主题定制': 'Theme',
'重置': 'Reset',
'复制覆盖代码': 'Copy override CSS',
'覆盖代码可直接粘贴到令牌文件之后,即完成整站换色。':
'Paste the override CSS after the token file to recolor the whole site.',
'深色 / 浅色模式切换': 'Toggle dark / light mode',
'回到顶部': 'Back to top',
'品牌主色': 'Brand',
'主色悬停': 'Brand hover',
'主色点击': 'Brand active',
'主色浅背景': 'Brand tint',
'科技蓝': 'Tech Blue',
'青碧': 'Cyan',
'极夜紫': 'Polar Violet',
'暖橙': 'Warm Orange',
'绯红': 'Crimson',
'松石绿': 'Turquoise',
/* ---------- 设计规范页 ---------- */
'设计规范': 'Design Tokens',
'Aurora Admin 设计系统的全部设计令牌,共 <strong>': 'All design tokens of the Aurora Admin system — <strong>',
'</strong> 项。所有组件均基于这些令牌构建,来源 <code>colors_and_type.css</code>。':
'</strong> in total. Every component is built on these tokens, sourced from <code>colors_and_type.css</code>.',
'色彩 · 品牌色': 'Color · Brand',
'色彩 · 背景与表面': 'Color · Background & Surface',
'色彩 · 文字色': 'Color · Text',
'色彩 · 边框': 'Color · Border',
'色彩 · 语义色': 'Color · Semantic',
'色彩 · 遮罩与焦点': 'Color · Overlay & Focus',
'含状态色与外发光': 'with state colors and focus ring',
'字体': 'Typography',
'字体族 Aa 123': 'Family Aa 123',
'Aa 字体示例': 'Aa sample',
'间距(4px 基准)': 'Spacing (4px base)',
'圆角': 'Radius',
'阴影(3 层克制投影)': 'Shadow (3 restrained levels)',
'控件高度': 'Control Height',
'令牌导出': 'Token Export',
'令牌可导出为三种标准格式,供设计工具与其它工程直接消费。文件由 <code>build-site.ps1</code> 在构建时生成,与上方展示的取值始终同源。':
'Tokens export to three standard formats for design tools and other projects. Files are generated by <code>build-site.ps1</code> at build time, always in sync with the values shown above.',
'CSS 自定义属性': 'CSS Custom Properties',
'直接 @import 或复制 :root 变量块': 'Import directly or copy the :root block',
'Design Tokens 社区组标准($value / $type)': 'W3C Design Tokens Community Group standard ($value / $type)',
'Tokens Studio 插件可直接导入': 'Importable by the Tokens Studio plugin',
/* ---------- 搜索 / 其他 ---------- */
'页面没切换': 'Page did not change',
'数据加载失败:site/data.js 缺失或为空。请先在仓库根目录运行 build-site.ps1 重新生成。':
'Failed to load data: site/data.js is missing or empty. Run build-site.ps1 in the repository root to regenerate.',
/* ---------- 文件类型 ---------- */
'H5 静态页': 'H5 page',
'样式表': 'Stylesheet',
'React 组件': 'React component',
'Vue 2 组件': 'Vue 2 component',
'Vue 3 组件': 'Vue 3 component',
/* ---------- 事件/插槽说明 ---------- */
'回调触发事件 (Event callback)': 'Event callback',
'子节点内容 (children)': 'Child content (children)',
'双向绑定更新事件 (v-model)': 'Two-way binding update (v-model)',
'组件交互触发事件': 'Emitted on component interaction',
'交互回调触发事件': 'Emitted on interaction callback',
'默认插槽(组件文本或主体内容)': 'Default slot (component text or body content)',
' 自定义扩展插槽': ' Custom extension slot',
/* ---------- 表格表头(属性/事件/插槽/按键表) ---------- */
'<thead><tr><th>参数名</th><th>说明</th><th>类型</th><th>默认值</th><th>必填</th></tr></thead>':
'<thead><tr><th>Prop</th><th>Description</th><th>Type</th><th>Default</th><th>Required</th></tr></thead>',
'<thead><tr><th>事件名</th><th>说明</th><th>回调参数</th></tr></thead>':
'<thead><tr><th>Event</th><th>Description</th><th>Callback args</th></tr></thead>',
'<thead><tr><th>插槽名</th><th>说明</th></tr></thead>':
'<thead><tr><th>Slot</th><th>Description</th></tr></thead>',
'<thead><tr><th style="width:160px">按键</th><th>交互说明</th></tr></thead>':
'<thead><tr><th style="width:160px">Key</th><th>Interaction</th></tr></thead>',
'<thead><tr><th style="width:26%">资源</th><th style="width:38%">路径</th><th>说明</th></tr></thead><tbody></tbody>':
'<thead><tr><th style="width:26%">Resource</th><th style="width:38%">Path</th><th>Description</th></tr></thead><tbody></tbody>',
'<thead><tr><th style="width:30%">字段</th><th>内容</th></tr></thead><tbody></tbody>':
'<thead><tr><th style="width:30%">Field</th><th>Contents</th></tr></thead><tbody></tbody>',
'<span class="badge-req">必填</span>': '<span class="badge-req">Required</span>',
'<span class="badge-opt">可选</span>': '<span class="badge-opt">Optional</span>',
/* ---------- 零散片段 ---------- */
'断言通过': 'assertions passed',
'预览': 'Preview',
'全部 (': 'All (',
'共 <strong>': '',
'</strong> 个组件(核心 <strong>': ' components (core ',
'</strong> · 扩展 <strong>': ' · extension ',
'</strong>),覆盖 ': '), covering ',
'大类。基于 Aurora Admin 设计系统规范构建,提供 H5 / React / Vue 2 / Vue 3 四端实现。':
' categories. Built on the Aurora Admin specification with H5 / React / Vue 2 / Vue 3 implementations.',
'色彩 · ': 'Color · ',
' 个组件': ' components',
'组件': 'Components',
/* ---------- 设计规范色彩分组 ---------- */
'品牌色': 'Brand',
'背景与表面': 'Background & Surface',
'文字色': 'Text',
'边框': 'Border',
'语义色': 'Semantic',
'遮罩与焦点': 'Overlay & Focus',
/* ---------- 设计避坑(按钮/输入/表格/弹窗/通用) ---------- */
'主行动区原则上只保留一个 Primary 主按钮': 'Keep only one Primary button per primary action area',
'危险破坏性操作配合二次确认弹窗使用': 'Pair destructive actions with a confirmation dialog',
'加载中状态下设置 disabled 避免二次误触': 'Set disabled while loading to prevent double submission',
'避免在同一行并列 3 个以上相同颜色的主按钮': 'Avoid three or more same-colored primary buttons in one row',
'避免在表单提交操作中使用弱化文字按钮': 'Avoid subdued text buttons for form submission',
'不要在非页面跳转场景滥用链接按钮': 'Do not overuse link buttons outside navigation',
'输入框建议配合明确的 Label 或 Placeholder': 'Pair inputs with an explicit label or placeholder',
'密码及敏感凭据字段提供显隐切换图标': 'Provide a show/hide toggle for passwords and credentials',
'必填项在标签旁显式标注红星 (*)': 'Mark required fields with a red asterisk (*) next to the label',
'避免仅依赖 Placeholder 传达关键业务提示': 'Do not rely on the placeholder alone to convey critical information',
'避免移动端使用过长不可换行的输入区域': 'Avoid long non-wrapping input areas on mobile',
'不要在禁用态下保留光标闪烁效果': 'Do not keep a blinking caret in the disabled state',
'列数较多(≥8列)时开启固定列与横向滚动': 'Enable fixed columns and horizontal scrolling at 8+ columns',
'长列表数据采用分页或虚拟滚动承载': 'Carry long lists with pagination or virtual scrolling',
'空数据状态提供具体的引导图文': 'Provide concrete guidance for the empty state',
'避免单元格无限制换行撑大表格高度': 'Avoid unbounded cell wrapping inflating row height',
'避免全表无边框导致复杂数据对比混淆': 'Avoid a fully borderless table where dense data blurs together',
'不要在无分页情况下一次性渲染数百行 DOM': 'Do not render hundreds of rows without pagination',
'弹窗宽度应适配内容复杂度,标准为 520px': 'Size the dialog to the content; 520px is the standard width',
'重要输入表单弹窗阻止点击蒙层空白处误关闭': 'Block mask-click dismissal for important form dialogs',
'弹窗关闭后应将焦点自动交还触发按钮': 'Return focus to the trigger button after the dialog closes',
'避免多层弹窗连续嵌套破坏视觉层级': 'Avoid deeply nested dialogs that break the visual hierarchy',
'避免在弹窗内塞入两屏以上的长篇表单': 'Avoid cramming more than two screens of form into a dialog',
'不要无确定按钮直接让用户点击右上角叉号关闭': 'Do not force users to close via the corner X without a confirm button',
'优先遵循 Aurora Admin 统一设计令牌体系': 'Prefer the unified Aurora Admin token system',
'保持组件语义化标签,便于辅助工具识别': 'Keep semantic markup so assistive tools can interpret it',
'复杂业务合理组合基础原子组件': 'Compose complex business UI from the base atomic components',
'避免自行通过 style 强行覆盖组件内边距': 'Avoid forcibly overriding component padding via inline style',
'避免自创非常规控件高度破坏栅格对齐': 'Avoid custom control heights that break grid alignment',
'不要移除原生的键盘焦点可视化轮廓': 'Do not remove the native keyboard focus outline',
};
var LANG_KEY = 'aa-lang';
var lang = 'zh';
try {
var saved = localStorage.getItem(LANG_KEY);
if (saved === 'en' || saved === 'zh') lang = saved;
} catch (e) { /* ignore */ }
/* 翻译:未收录的源串原样返回(中文),避免出现空白或 key 泄漏 */
function T(s) {
if (lang !== 'en') return s;
return Object.prototype.hasOwnProperty.call(EN, s) ? EN[s] : s;
}
function getLang() { return lang; }
function setLang(next) {
if (next !== 'en' && next !== 'zh') return;
lang = next;
try { localStorage.setItem(LANG_KEY, lang); } catch (e) { /* ignore */ }
document.documentElement.setAttribute('lang', lang === 'en' ? 'en' : 'zh-CN');
}
/* 覆盖率自检:开发期可用来发现漏翻的文案 */
function coverage(strings) {
var hits = strings.filter(function (s) { return Object.prototype.hasOwnProperty.call(EN, s); });
return { total: strings.length, translated: hits.length, missing: strings.filter(function (s) { return !Object.prototype.hasOwnProperty.call(EN, s); }) };
}
window.AA_I18N = { T: T, getLang: getLang, setLang: setLang, coverage: coverage, dict: EN };
document.documentElement.setAttribute('lang', lang === 'en' ? 'en' : 'zh-CN');
})();
+5 -1
View File
@@ -14,7 +14,7 @@
<div class="topbar-inner">
<a class="logo" href="#/">
<span class="logo-mark">A</span>
<span class="logo-text">Aurora Admin <em>组件库</em></span>
<span class="logo-text">Aurora Admin <em class="logo-sub">组件库</em></span>
<span class="ver" id="ver">v1.0.0</span>
</a>
<button id="search-trigger" class="search-trigger" type="button">
@@ -39,6 +39,9 @@
<a href="#/changelog" data-nav="changelog">更新日志</a>
<a href="#/agents" data-nav="agents">AI 消费</a>
</nav>
<button id="lang-toggle" class="lang-toggle" type="button" title="中文 / English">
<span class="lang-zh">中</span><span class="lang-sep">/</span><span class="lang-en">EN</span>
</button>
</div>
</header>
@@ -89,6 +92,7 @@
<script src="data.js"></script>
<script src="logger.js"></script>
<script src="i18n.js"></script>
<script src="app.js"></script>
</body>
</html>
+16
View File
@@ -108,6 +108,22 @@ a:hover { color: var(--au-color-brand-hover); }
}
.topnav a:hover { color: var(--au-color-brand); }
.topnav a.active { color: var(--au-color-brand); font-weight: 500; }
/* 语言切换:中/EN 双段,当前语言高亮 */
.lang-toggle {
margin-left: 12px; height: 28px; padding: 0 10px;
display: inline-flex; align-items: center; gap: 2px;
border: 1px solid var(--au-color-border); border-radius: var(--au-radius-base);
background: var(--au-color-card-bg); cursor: pointer;
font-family: var(--au-font-family-num); font-size: 12px;
color: var(--au-color-text-secondary);
transition: border-color .15s;
}
.lang-toggle:hover { border-color: var(--au-color-brand); }
.lang-toggle .lang-sep { opacity: .4; margin: 0 2px; }
.lang-toggle .lang-zh,
.lang-toggle .lang-en { padding: 0 2px; }
.lang-toggle .active { color: var(--au-color-brand); font-weight: 600; }
.topnav a.active::after {
content: '';
position: absolute;
File diff suppressed because one or more lines are too long
+37 -15
View File
@@ -584,27 +584,49 @@
var clr = document.getElementById('clear-log');
if (clr) clr.addEventListener('click', clearLog);
var frame = document.getElementById(FRAME_ID);
/* 等待演示页真正就绪再断言。
固定帧数(双 rAF)在并发收集器里不够稳:多个 iframe 抢主线程时,
演示页的内联脚本可能还没执行完(例如 DensitySwitcher 的 is-active 尚未加上),
断言读到的就是中间态。改为轮询:readyState 完成 + DOM 连续若干次采样无变化。 */
function whenReady(cb) {
var tries = 0;
var lastSig = null;
var stable = 0;
function tick() {
tries++;
if (!fDoc || !fWin) { if (tries < 200) return setTimeout(tick, 16); return cb(); }
var ready = false;
try { ready = fDoc.readyState === 'complete'; } catch (e) {}
var sig = '';
try {
var root = scope();
sig = root.childElementCount + ':' + root.innerHTML.length;
} catch (e) { sig = 'err'; }
if (ready && sig === lastSig) {
stable++;
// 连续 3 次采样(约 48ms)内容不变 → 认为渲染已稳定
if (stable >= 3) return cb();
} else {
stable = 0;
}
lastSig = sig;
if (tries < 300) setTimeout(tick, 16);
else cb(); // 超时兜底:约 4.8s 后无论如何都跑,避免页面卡死
}
tick();
}
var frame = document.getElementById(FRAME_ID);
if (frame) {
/* 演示页的内联脚本在 load 后才渲染 DOM(含 is-active 等初始状态类)。
直接断言会读到渲染中途的样式,产生时序性误报。
因此:load → 双 rAF(等一次完整样式重算)→ 再断言。 */
var auto = function () {
if (!bindFrame()) { setFrameState('演示页加载失败', 'fail'); return; }
var W = fWin || window;
var raf = W.requestAnimationFrame || window.requestAnimationFrame ||
function (cb) { return setTimeout(cb, 16); };
raf(function () { raf(function () { setTimeout(run, 30); }); });
whenReady(function () { run(); });
};
frame.addEventListener('load', auto);
if (bindFrame()) {
var W0 = fWin || window;
var raf0 = W0.requestAnimationFrame || window.requestAnimationFrame ||
function (cb) { return setTimeout(cb, 16); };
raf0(function () { raf0(function () { setTimeout(run, 30); }); });
} else {
setFrameState('加载中…');
}
if (bindFrame()) whenReady(function () { run(); });
else setFrameState('加载中…');
} else {
setTimeout(run, 0);
}
+3 -3
View File
@@ -1,6 +1,6 @@
{
"generated": "2026-09-11 14:41:05",
"version": "1.3.2",
"generated": "2026-09-11 17:14:10",
"version": "1.3.3",
"pages": 79,
"pagesAllPass": 79,
"passRate": 100,
@@ -13,5 +13,5 @@
},
"failureKinds": {},
"failedPages": [],
"note": "v1.3.2:契约第三批完成(79/79 全契约化)+ 令牌导出。9 项矩阵断言全通过,N/A 36 条来自静态组件与单实例组件。此通过率不等于无障碍合规认证。"
"note": "v1.3.3:i18n 双语 + 回归时序根治。9 项矩阵断言全通过,四次连跑结果一致。N/A 36 条来自静态组件与单实例组件。此通过率不等于无障碍合规认证。"
}
+4 -2
View File
@@ -2,7 +2,9 @@
> **修复进度(2026-09-10 v1.3.0)**:v1.1.1 完成 A1 搜索增强、A2 For Agents + llms.txt、A3 站内 Changelog + 版本同步、B2 暗色令牌映射、B4 主题预设库;v1.2.0 完成 B1 契约第一批(21/79)、B3 Playground、C1 交叉引用、C3 headless 回归骨架、C4 静态薄壳 + sitemap。
>
> **v1.3.2(本次)**:契约第三批 43 份落地,**79/79 全量契约化**(此前 36);新增令牌导出三格式(CSS / W3C DTCG / Figma Tokens);规格原文色彩系统同步至 AA 达标值。
> **v1.3.3(本次)**:中英双语落地(`site/i18n.js` 330 条字典 + 顶栏切换 + 偏好持久化),覆盖全部页面;回归时序根治(DensitySwitcher 偶发失败 → 就绪轮询,四次连跑 100%)。
>
> **v1.3.2**:契约第三批 43 份落地,**79/79 全量契约化**;新增令牌导出三格式(CSS / W3C DTCG / Figma Tokens);规格原文色彩系统同步至 AA 达标值。
>
> 前序:v1.3.0 修复验收链路(测试页原以静态快照断言、剥离 script 后 DOM 为空,75.1% 属结构性误报 → 改 iframe 真实渲染 + 跨帧断言);v1.3.1 完成无障碍与令牌合规,回归达 **100%**(961 断言 / 0 失败 / 79 页全通过)。
>
@@ -69,7 +71,7 @@
### P2 — 增强项
**问题 9:无组件交叉引用** — 无「相似组件 / 搭配使用 / 推荐·慎用」(TDesign Button 页特色栏目)。契约 JSON 已有「不发明 / 未明示 / 使用要点」字段,具备映射条件。
**问题 10:无 i18n** — CAT_LABELS 等常量硬编码中文,无 EN 切换(7 家竞品全有双语,3 家还有 RTL)。
**问题 10:i18n 双语(v1.3.3 已闭环)** — `site/i18n.js` 330 条字典,中文源串作键(未收录自动回退),顶栏 `中/EN` 切换 + `aa-lang` 持久化,覆盖 9 个路由与全部组件详情页。
**问题 11:无设计资源下载** — css.json 已是结构化令牌,但没有导出 Figma Tokens / 设计资源包入口(竞品标配 Figma/Sketch 资源)。
**问题 12:可爬取性弱** — hash 路由 SPA 全靠 JS 渲染;`data.json` 已生成(2026-09-07)但无 sitemap、无每组件静态入口,搜索引擎与 LLM 爬虫拿不到组件页内容。
**问题 13:组件页无 FAQ**(Ant Design 每组件 FAQ 模式,高频问题沉淀)。