Skip to content

Commit 193bf34

Browse files
authored
Merge pull request #3736 from czllll/fix/a11y-zh-hans-and-language-switcher
Add zh-hans translation for accessibility guide, filter language switcher to translated articles
2 parents 7e12707 + dd2bfbe commit 193bf34

3 files changed

Lines changed: 313 additions & 0 deletions

File tree

Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
---
2+
lang: zh-hans
3+
title: 项目无障碍最佳实践
4+
description: 让你的开源项目对所有人(尤其是残障人士)可用的实用、可落地的步骤。
5+
class: accessibility-best-practices
6+
order: -1
7+
image: /assets/images/cards/accessibility-best-practices.png
8+
---
9+
10+
无障碍(accessibility,常简写为 _a11y_)意味着不论用户是否残障、使用何种辅助技术、身处何种环境或使用何种设备,都能使用你的项目。它包括但不限于:对屏幕阅读器的支持、纯键盘导航、字幕/文字记录、足够的色彩对比度,以及清晰的内容结构。
11+
12+
## 与残障人士携手合作
13+
14+
**"没有我们的参与,就不要替我们做决定"** —— 对无障碍建设而言,最重要的一件事就是把它所服务的人群放在中心位置。有残障经历的用户、贡献者和测试者,能以指南和自动化工具无法企及的方式理解真正的障碍所在。尽早并持续地寻求他们的真实体验。
15+
16+
### 落到实处
17+
18+
脱离受影响的人群做出的决定,往往会偏离目标。与残障人士一起构建,而不是替他们构建,才能打造出对所有人都更好的软件。
19+
20+
以下是几种纳入真实体验的方式:
21+
22+
* 邀请残障贡献者参与设计讨论,而不仅仅是缺陷分类(bug triage)。
23+
* 在条件允许的情况下,邀请残障人士参与可用性测试和反馈。
24+
* 当有人描述他们如何使用你的项目时,认真倾听,即使这挑战了你原有的假设。
25+
* 把无障碍报告当作专业意见来对待,而不是抱怨——它们所代表的用户可能比你想象的更多。
26+
27+
### 无障碍让所有人受益
28+
29+
* **它影响着大量人群。** 根据[世界卫生组织](https://www.who.int/news-room/fact-sheets/detail/disability-and-health)的估计,全球约有 13 亿人(六分之一)存在显著的残障情况。
30+
* **它是质量的一部分。** 具备无障碍能力的产品,往往对所有人都更易用。
31+
* **它降低支持负担。** 更清晰的界面和文档意味着更少困惑的用户。
32+
* **它扩大你的贡献者群体。** 辅助技术用户能够更充分地参与进来。
33+
* **它推动创新。** 为多样化需求而设计,往往会带来让所有人都受益的功能(比如字幕、语音控制和深色模式,最初都是无障碍方案)。
34+
* **它常常是硬性要求。** 许多组织(以及一些政府)在采购和合规方面都要求具备无障碍能力。
35+
* **我们的未来充满不确定性。** 没有人能确定自己明天还拥有今天所拥有的能力。
36+
37+
## 从无障碍声明开始
38+
39+
在动手写代码之前,先花点时间记录下你的项目对无障碍的承诺。一份无障碍声明向用户和贡献者传达了一个信号:无障碍是优先事项,而不是事后补丁。具体做法可参考 [W3C 的《撰写无障碍声明》指南](https://www.w3.org/WAI/planning/statements/)
40+
41+
添加一份清晰的声明,设定预期,并让用户能方便地报告问题。你可以直接在 README 中添加一个无障碍章节,也可以创建独立的 **ACCESSIBILITY.md** 文件,并在 README 中链接到它以提高可见性。可参考这个 [ACCESSIBILITY.md 示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/ACCESSIBILITY.md)
42+
43+
### 目标
44+
45+
* 陈述可衡量的目标和准则(在可行的情况下,参考 [WCAG AA](https://www.w3.org/TR/WCAG22/#wcag-2-layers-of-guidance))。
46+
* 明确首要优先事项,以及你打算如何实现它们(键盘与屏幕阅读器支持、字幕与文字记录等)。
47+
* 说明已知的局限性,以及可用的替代方案(如果存在)。
48+
49+
### 贡献者要求
50+
51+
设立清晰的准则,让贡献者知道项目对他们的期望:
52+
53+
* **测试:** 所有 UI 改动都必须使用无障碍测试工具进行测试(例如 [Axe DevTools](https://www.deque.com/axe/devtools/extension/#:~:text=Try%20Axe%20DevTools%20Extension%20in%20your%20browser%20of%20choice))。
54+
* **文档:** 针对 SVG、图片、交互元素等组件,遵循项目的无障碍指南。
55+
* **CI/CD:** 如果 PR 引入了无障碍检查工作流检测到的违规项,应当让检查失败。
56+
57+
### 支持的环境
58+
59+
* 列出你所支持的平台(Web、移动端 Web、iOS、Android、终端/CLI、桌面应用)。
60+
* 列出任何部分支持的说明。
61+
62+
### 报告无障碍问题
63+
64+
* 引导报告者使用无障碍问题模板来创建 issue。
65+
* **小贴士:** 诚实地设定预期(比如"我们正在处理这个问题——进展跟踪见 ISSUE-123");确认收到报告,并在可能的情况下提供后续进展或临时解决方案。
66+
67+
#### 为什么要把无障碍问题从常规问题流程中独立出来?
68+
69+
用户早已习惯了一份专门的无障碍声明和报告路径——这在私营部门和各类政府网站中都是行之有效的惯例,很多用户在遇到障碍时会首先寻找它。让无障碍问题独立于常规缺陷流程,原因在于:
70+
71+
* **影响具有时效性。** 无障碍缺陷可能导致用户完全无法使用你的项目,而不只是带来不便。独立的报告路径有助于这类问题被更快地分类处理。
72+
* **上下文不同。** 无障碍问题报告需要具体信息(所用辅助技术、操作系统、浏览器、严重程度),而通用的缺陷模板不会主动提示这些内容。
73+
* **它传达出承诺。** 一份可见的、独立的声明向用户和贡献者表明,无障碍是一等公民关切,而不是被塞进"其他缺陷"里草草处理。
74+
* **报告者本身可能正在使用辅助技术来提交报告。** 一个清晰、可预期的流程(固定的文件、固定的标签、固定的模板)能减少受影响最严重的那部分人所面临的阻力。
75+
76+
## 让文档默认无障碍
77+
78+
文档往往是用户接触到的第一个"界面"。确保每个人都能读懂它。
79+
80+
### 结构与语义
81+
82+
* 使用**合乎逻辑的标题层级**,不要跳级(`#``##``###``####``#####``######`)。
83+
* 使用**独特且具描述性的链接文字**(用"阅读贡献指南"而不是"点击这里")。
84+
* 使用平实的语言,避免行话,首次出现的缩写要展开说明。
85+
* [使用**真正的列表**](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#lists),而不是手动打出的编号。
86+
***帮助和导航保持在各页面一致的位置**,方便用户可预期地找到它们。
87+
* 避免仅通过位置或样式来传达含义(例如"看右边的红色文字")。
88+
89+
### 图片、图表与视频
90+
91+
* 为图片提供有意义的**替代文本**(常简称为"alt text",参考 [W3C 的 alt 决策树](https://www.w3.org/WAI/tutorials/images/decision-tree/))。
92+
* 尽量使用真实文本,而不是文字图片。
93+
* 对于复杂图片(如架构图),在附近提供额外的**文字说明**(要点列表或简短解释)。
94+
* 如果你发布演示、教程、演讲或发布视频:
95+
* 提供**字幕**(尽量选择人工校对过的版本)。
96+
* 提供**文字记录**
97+
* 避免自动播放音视频。
98+
* 用语言描述重要的屏幕操作。
99+
100+
### 表格
101+
102+
* 表格只用于呈现表格数据,不要用于页面布局。
103+
* 提供**表头单元格**,将列标题和行标题与数据单元格关联起来。
104+
* 提供**说明或摘要**,描述表格的用途。
105+
106+
### 代码块
107+
108+
* 保持每行长度合理(自动换行有助于可读性)。
109+
* 不要仅依赖颜色高亮来传达含义。
110+
* 用文字说明代码做了什么、成功的标志是什么。
111+
112+
## 设计无障碍的界面
113+
114+
如果你的项目有 Web 界面,以下这些高影响力的默认设计能帮助到所有用户。
115+
116+
### 键盘支持
117+
118+
* 所有可交互元素都应能**仅通过键盘**访问和操作。
119+
* 确保有**可见的焦点指示**(除非提供替代方案,否则不要移除焦点轮廓)。
120+
* 保持与视觉布局一致的、合乎逻辑的 **Tab 键顺序**
121+
* 除非你有意管理焦点(例如模态对话框)并提供退出方式,否则不要在组件内困住焦点。
122+
123+
### 语义优先
124+
125+
* 尽可能使用**原生 HTML** 元素(`<h1>``<button>``<a>``<input>``<label>`)。
126+
* 只有在原生 HTML 不够用时才使用 **ARIA**。没有 ARIA 也好过糟糕的 ARIA。如果确实需要使用,请遵循 [ARIA(无障碍富互联网应用)文档](https://www.w3.org/TR/wai-aria/),并确保所有可交互的 ARIA 控件都支持键盘操作。
127+
* 声明文档的**语言**(例如 HTML 中的 `lang="en"`),并标注其中语言不同的部分。
128+
129+
### 名称、标签、说明
130+
131+
* 每个表单控件都需要关联一个**标签**
132+
* 提供**清晰的错误信息**,指出哪个字段出错,并通过程序化方式(如 `aria-describedby`)将错误信息与字段关联。
133+
* 对于必填字段,用文字说明要求(而不只是一个星号)。
134+
135+
### 颜色与对比度
136+
137+
* 不要仅用颜色来传达含义(例如"错误是红色的")。
138+
* 确保文字、图标和 UI 控件有足够的对比度(参考 [WebAIM 的对比度检测工具](https://webaim.org/resources/contrastchecker/))。
139+
140+
### 动效与动画
141+
142+
* 避免闪烁内容和快速动画。
143+
* 避免视差效果和自动轮播,或者让它们可以被关闭和控制。
144+
* 如果操作系统表明用户要求减少或关闭动效,就避免不必要的动画。
145+
146+
### 动态内容
147+
148+
当内容在不刷新页面的情况下发生更新时,要确保辅助技术用户能够获知:
149+
150+
* 谨慎地使用合适的 **ARIA live region** 来发出通知。
151+
* 在打开/关闭对话框、菜单和抽屉时妥善管理焦点。
152+
153+
### 依赖与模式
154+
155+
* 使用有完善无障碍支持文档的组件库。
156+
* 追踪上游的无障碍缺陷,并在你的 issue 中关联它们。
157+
* 对自定义 UI 控件保持谨慎。原生控件(如 `<button>``<select>``<input type="checkbox">``<details>`)自带浏览器和辅助技术已经理解的键盘支持、焦点管理、屏幕阅读器语义和表单集成能力。在自定义组件中重新实现这些行为既耗时又容易出错,并且会随着平台和辅助技术的演进带来长期维护成本。只有在原生元素确实无法满足需求时,才考虑使用自定义控件。
158+
159+
### 移动端注意事项
160+
161+
* 让触控目标至少达到 **24×24 CSS 像素**
162+
* 为多指或路径手势(如捏合、滑动)提供单点替代方案。
163+
* 为拖放操作提供替代方案(按钮、菜单)。
164+
* 除非内容本身确实需要特定方向,否则不要将内容限制在单一显示方向上。
165+
* 为由设备运动触发的功能(如摇一摇撤销)提供替代方案。
166+
167+
## 让工具无障碍
168+
169+
只要设计得当,命令行工具和仪表盘也可以做到高度无障碍。
170+
171+
### CLI 工具
172+
173+
命令行应用只要具备可预期性和可脚本化,就能做到高度无障碍。
174+
175+
* 支持 `--help`,并提供清晰的用法示例。
176+
* 为难以解析表格的用户提供**机器可读的输出**选项(如 `--json`)。
177+
* 不要仅依赖 ANSI 颜色来传达成功/失败,要同时提供文字标签和退出码。
178+
* 编写错误信息时,应当:
179+
* 说明发生了什么,
180+
* 展示如何修复,以及
181+
* 在需要时链接到文档。
182+
* 使用标准的退出码,并确保失败时返回非零值。
183+
184+
### 终端、日志与仪表盘
185+
186+
* 优先使用平实语言,而非行话。
187+
* 避免使用未加说明的缩写。
188+
* 对严重程度级别(`ERROR``WARN``INFO`)使用一致的格式,并在有用时包含时间戳。
189+
* 确保"状态"不是仅通过颜色来传达的。
190+
191+
## 把无障碍融入贡献流程
192+
193+
当无障碍成为常规流程的一部分时,它会更容易维持下去。
194+
195+
### 添加 issue 标签和模板
196+
197+
* 创建一个无障碍标签(例如 _"accessibility"__"a11y"_)。
198+
* 创建一个无障碍 issue 模板,包含:
199+
* _accessibility_ 标签
200+
* 预期行为与实际行为
201+
* 复现步骤(可选附带屏幕录制)
202+
* 所用工具(操作系统、浏览器、辅助技术及其版本)
203+
* 用于优先级排序的严重程度分类:
204+
* **严重(Critical):** 阻止用户完成核心任务(例如"无法结算")。
205+
* **高(High):** 存在明显困难,但有变通方案。
206+
* **中(Medium):** 造成困扰或体验不一致。
207+
* **低(Low):** 对可用性影响很小的小问题。
208+
* 如有需要,附上联系方式或升级处理的说明。
209+
210+
可参考这个[无障碍 issue 模板示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/.github/ISSUE_TEMPLATE/accessibility.yml)
211+
212+
### 在 Pull Request(PR)中添加无障碍检查清单
213+
214+
对于涉及 UI 改动的项目,可以包含如下问题:
215+
216+
* 键盘导航能否端到端正常工作
217+
* 焦点状态是否可见且符合逻辑
218+
* 表单是否有标签,错误是否会被朗读出来
219+
* 颜色是否不是传达含义的唯一方式
220+
* 是否遵循了"减少动效"的系统设置(如果新增了动画)
221+
* 是否至少检查过一次屏幕阅读器下的行为
222+
223+
可参考这个 [PR 模板示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/.github/PULL_REQUEST_TEMPLATE.md)
224+
225+
### 明确"完成"的定义
226+
227+
为功能和缺陷修复添加无障碍验收标准,让它不再是可选项或临时补救。
228+
229+
### 善用 GitHub Copilot
230+
231+
* 创建专门的 Copilot 智能体,将无障碍相关任务自动化融入开发流程,从使用 [axe-core](https://github.com/dequelabs/axe-core) 审计页面,到跨版本追踪无障碍改进情况。参考[《GitHub Copilot 自定义智能体无障碍入门指南》](https://accessibility.github.com/documentation/guide/getting-started-with-agents/)
232+
* 根据你的编码风格、无障碍实践和项目背景,定制 Copilot 的建议,确保它们符合你的无障碍要求。参考[《使用自定义指令优化 GitHub Copilot 的无障碍表现》指南](https://accessibility.github.com/documentation/guide/copilot-instructions/)
233+
234+
### 得体而有效地处理无障碍问题报告
235+
236+
无障碍问题往往难以描述、难以复现,并且对报告者能否使用你的项目具有时效性。处理这类报告时:
237+
238+
* 感谢报告者,并不带质疑地提出澄清性问题。
239+
* 优先处理阻断性问题(无法完成核心流程),而不是外观类问题。
240+
* 在可能的情况下提供变通方案。
241+
* 闭环处理:如果报告者愿意,与他们确认修复是否有效。
242+
243+
## 持续测试无障碍性
244+
245+
自动化工具擅长捕捉回归问题,但只有人工测试才能建立起真正的信心。
246+
247+
### 自动化检查(擅长捕捉回归)
248+
249+
* 在 UI 代码中进行无障碍相关的 lint 检查。
250+
* 在 CI 中自动扫描常见的 WCAG 违规项(例如使用 [GitHub Accessibility Scanner](https://github.com/github/accessibility-scanner))。
251+
* 编写单元/集成测试,对关键组件断言其 [role/name](https://www.w3.org/TR/accname-1.2/)
252+
253+
### 人工测试(建立真正信心所必需)
254+
255+
* **纯键盘**测试:不用鼠标,能否顺利完成主要流程?
256+
* **屏幕阅读器**抽查:
257+
* macOS:[VoiceOver](https://support.apple.com/guide/voiceover/welcome/mac)
258+
* Windows:[NVDA](https://www.nvaccess.org/about-nvda/)(在开源社区中常用)、[JAWS](https://vispero.com/jaws-screen-reader-software/)(企业场景常用)
259+
* **缩放与重排**:在 200% 缩放和窄屏宽度下测试。
260+
* 在适用的情况下测试**高对比度/强制颜色**模式。
261+
262+
**小贴士:** 在发布检查清单中加入一个轻量的"无障碍[冒烟测试](https://en.wikipedia.org/wiki/Smoke_testing_(software))"环节。
263+
264+
## 本周就能开始的一些小改进
265+
266+
### 你不需要一次做完所有事,可以先从几个能快速见效的改进入手。
267+
268+
挑几项来做:
269+
270+
* 添加 `ACCESSIBILITY.md` 文件,并创建一个无障碍标签(如 _"accessibility"__"a11y"_
271+
* 确保每个可交互元素都能通过键盘访问
272+
* 修复缺失的表单标签
273+
* 声明文档的**语言**(例如 HTML 中的 `lang="en"`),并标注其中语言不同的部分
274+
* 为 README 和文档添加替代文本和标题结构
275+
* 在 PR 检查清单中加入键盘/焦点相关条目
276+
* 为你最受欢迎的视频添加字幕/文字记录
277+
* 为某个 CLI 命令添加 `--json` 输出
278+
279+
### 有助于将无障碍承诺正式落地的建议文件
280+
281+
可以考虑在你的仓库中添加以下文件:
282+
283+
* `ACCESSIBILITY.md`:你的无障碍声明、问题报告方式,以及任何项目特定的指导(组件规则、模式、已知问题)——[ACCESSIBILITY.md 示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/ACCESSIBILITY.md)
284+
* `.github/ISSUE_TEMPLATE/accessibility.yml`:无障碍缺陷报告模板——[无障碍 issue 模板示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/.github/ISSUE_TEMPLATE/accessibility.yml)
285+
* `.github/pull_request_template.md`:包含无障碍检查清单——[PR 模板示例](https://github.com/open-source-accessibility/accessibility-toolkit/blob/main/.github/PULL_REQUEST_TEMPLATE.md)
286+
287+
可参考这个[提供了更多示例的项目](https://github.com/mgifford/ACCESSIBILITY.md/tree/main)
288+
289+
## 结语:你的一小步,用户体验的一大步
290+
291+
这些步骤看起来可能很基础,但它们能大幅提升项目的无障碍程度。你所做的每一个修复——无论是补上一个缺失的标签、消除一个键盘焦点陷阱,还是为视频加上字幕——都会为一位此前无法使用你项目的用户打开一扇门。
292+
293+
无障碍不是一次性的修复,而是一项持续的实践,你不需要一次性做完所有事情。从键盘导航和语义结构开始,保持改动小步进行,并尽早寻求评审。
294+
295+
你今天投入的这些努力,意味着会有更多人能够从你构建的成果中学习、为之贡献,并依赖它。这份收获值得庆祝。
296+
297+
## 贡献者
298+
299+
### 非常感谢所有为本指南分享经验和建议的维护者!
300+
301+
本指南由 [@mlama007](https://github.com/mlama007) 撰写,并有以下贡献者参与:[@ericwbailey](https://github.com/ericwbailey)[@andyfeller](https://github.com/andyfeller)[@mgifford](https://github.com/mgifford)[@smockle](https://github.com/smockle)[@weboverhauls](https://github.com/weboverhauls)

_includes/head.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
{% assign locales = site.data.locales | sort %}
1313
{% for locale in locales %}
1414
{% assign lang = locale[0] %}
15+
{% if page.layout == 'article' and lang != page.lang %}
16+
{% assign translated_article = site.articles | where: 'lang', lang | where: 'class', page.class | first %}
17+
{% unless translated_article %}
18+
{% continue %}
19+
{% endunless %}
20+
{% endif %}
1521
{% assign page_lang_slash = page.lang | append: '/' | prepend: '/' %}
1622
{% assign default_url = page.url | replace: page_lang_slash, '/' %}
1723
{% if lang == "en" %}

_includes/nav.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@
3737
{% for locale in locales %}
3838
{% assign lang = locale[0] %}
3939
{% assign locale_name = locale[1][lang].locale_name %}
40+
{% if page.layout == 'article' and lang != page.lang %}
41+
{% assign translated_article = site.articles | where: 'lang', lang | where: 'class', page.class | first %}
42+
{% unless translated_article %}
43+
{% continue %}
44+
{% endunless %}
45+
{% endif %}
4046
{% if page.lang == lang %}
4147
<option value="{{ lang }}" selected="selected">{{ locale_name }}</option>
4248
{% else %}

0 commit comments

Comments
 (0)