9.4 国际化与无障碍


9.4 国际化与无障碍

最后一道防线扩大受众的半径:多语言(让其他语种的用户跑进同一条跑道)与无障碍(让所有能力的用户都能完赛)。本节用 i18n 模块实现语言路由与文案管理,处理 RTL 与区域格式,再按 WCAG 要点过一遍无障碍自查——8.3 报告里 Accessibility 分类扣的分,答案大半在这节。

i18n:语言路由与文案管理

官方 i18n 模块的核心决策是路由策略——每种语言是否有独立 URL:

npm install @nuxtjs/i18n
// nuxt.config.ts export default defineNuxtConfig({ modules: ['@nuxtjs/i18n'], i18n: { strategy: 'prefix_except_default', // 默认语言不带前缀,其他带 defaultLocale: 'zh', locales: [ { code: 'zh', iso: 'zh-CN', name: '中文' }, { code: 'en', iso: 'en-US', name: 'English' }, { code: 'ar', iso: 'ar-EG', name: 'العربية', dir: 'rtl' }, // 阿拉伯语:从右到左 ], }, })

三种策略的取舍:

图 9-3:三种语言路由策略的 URL 形态

图 9-3:三种语言路由策略的 URL 形态

策略 URL 形态 适用
prefix_except_default /(中文)、/en、/ar 默认市场为主,SEO 友好(常用)
prefix /zh、/en、/ar 各语言平等,结构最清晰
no_prefix 同一 URL 按浏览器协商 工具类应用,SEO 弱

文案文件按语言分目录(模块约定),组件里用组合函数取:

<script setup> const { t, locale, setLocale } = useI18n() </script> <template> <nav> <h1>{{ t('products.title') }}</h1> <p>{{ t('products.count', { n: 42 }) }}</p> <!-- 语言切换:模块处理路由前缀与 cookie 记忆 --> <button v-for="l in ['zh', 'en', 'ar']" :key="l" @click="setLocale(l)"> {{ l }} </button> </nav> </template>
# i18n/locales/zh.yaml products: title: 全部商品 count: 共 {n} 件 # i18n/locales/en.yaml products: title: All Products count: '{n} items'

SEO 配套三件事:每语言的 hreflang 标签(模块自动生成)、useSeoMeta 按当前语言出标题描述(8.2 的多语言版)、sitemap 包含全部语言变体。

RTL 与区域格式

dir: 'rtl' 声明后,模块在语言切换时自动更新文档方向。样式侧用逻辑属性替代物理方向,一套 CSS 适配双向:

/* 物理属性:RTL 下全部反掉,要写两套 */ /* margin-left: 16px; */ /* 逻辑属性:方向感知,一套通吃 */ .sidebar { margin-inline-start: 16px; } .title { text-align: start; } .row { padding-inline: 24px; }

区域格式交给标准 API,别手拼字符串:

// 日期、数字、货币按 locale 格式化 const dtf = new Intl.DateTimeFormat(locale.value, { dateStyle: 'long' }) dtf.format(new Date()) // 中文:2026年9月8日 const nf = new Intl.NumberFormat(locale.value, { style: 'currency', currency: 'CNY' }) nf.format(399) // 中文:¥399.00

水合视角的注意点(4.1 的回访):服务端格式化用的 locale 来自请求(cookie 或 URL 前缀),客户端必须用同一来源,否则格式差异触发 mismatch——语言从 route 参数推导而不是浏览器嗅探,正是为了两端一致。

无障碍:WCAG 要点自查

按"能感知、可操作、可理解、健壮"四原则过清单,配合 8.3 的 Accessibility 分类逐项修:

检查项 做法 常见扣分点
图片替代文本 有信息量的 img 必写 alt;装饰图 alt 置空 空图无 alt、alt 写文件名
表单标签 label 与控件显式关联 只有 placeholder 没有 label
键盘可达 全部交互可 Tab 触达、焦点顺序合理、模态锁焦点 div 当按钮、自定义组件丢焦点
语义地标 header/nav/main/footer 用语义标签 一律 div 加 class
对比度 文本与背景至少四点五比一 浅灰字白底
动效尊重 减动效偏好下关闭非必要动画 强制入场动画
<template> <!-- 扣分写法:<div class="btn" @click="submit">提交</div> --> <!-- 合格写法:真按钮 + 可聚焦 + 状态可读 --> <button type="submit" :disabled="busy" :aria-busy="busy" > {{ busy ? '提交中…' : '提交订单' }} </button> </template>

修无障碍的最佳时机是写组件的时候——aria-* 与语义标签随组件一起落地,几乎零成本;事后回补则要在全站找交互元素,成本翻几倍。9.1 的 E2E 用角色选择器(getByRole)测试,本身就是无障碍的回归测试:角色选择器找不到的元素,屏幕阅读器多半也读不到。

读屏验证不必购买设备:系统自带的读屏(旁白、讲述人、屏幕阅读器)关掉显示器走一遍下单流程,比想象中更快暴露问题。8.3 归因图里 Accessibility 的扣分项(alt 缺失、表单无标签)用本节清单逐条核销即可。

⚠️ 常见坑:机器翻译批量生成语言文件直接上线。译文质量差损害品牌,RTL 语言的排版没人工过一遍必乱(标点、数字方向、混合文本)。每增加一门语言,留人工审校与 RTL 走查的预算。

💡 关键直觉:无障碍不是"照顾少数人"的公益项——键盘可达帮了快捷键用户,alt 文本喂了搜索引擎(8.2 的 SEO),对比度惠及强光下的每个手机用户。它是把"能用"扩展到"更多人能用"的通用质量。

本节要点回顾

  • 路由策略三选:默认语言免前缀最常用;hreflang 与多语言 sitemap 是 SEO 配套;
  • 文案按语言分文件,t 函数带插值;语言来源统一从路由推导防水合差异;
  • RTL 用逻辑属性(margin-inline-start 等)一套 CSS 双向通吃;区域格式交给 Intl 标准 API;
  • 无障碍清单六项:alt、label、键盘、地标、对比度、动效尊重——随组件落地成本最低;
  • 语义即无障碍:真按钮真标签既是读屏的依据,也是 E2E 角色选择器与 SEO 的共同基础。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U