Chiều ẩn của Web: i18n + a11y
Mở đầu
i18n và lý do? Trong FE + software engineering, i18n = internationalization (multi-language support). Vì giữa i và n đúng 18 chữ, viết tắt cho gọn. Tương tự, a11y = accessibility (giữa a và y có 11 chữ).
Đằng sau khi browser render UI rực rỡ, có 2 "đường ngầm" song song mắt thường không thấy: Khi gõ URL truy cập web, browser biết nên hiển thị tiếng Việt hay Đức thế nào (i18n flow)? Trong khi parse HTML thành DOM tree để vẽ, làm sao build thêm 1 "tree braille" chuyên cho người khiếm thị (a11y flow)?
Chương này quay về flow render + decode 2 lĩnh vực thể hiện tính nhân văn của tech này.
1. Language negotiation trong Web (i18n)
Khi gõ URL Enter, browser gửi HTTP request kèm header:
- Vd:
Accept-Language: vi-VN,vi;q=0.9,en;q=0.8
Như vào quán ăn, browser nói nhỏ với phục vụ: "Chủ tôi ưu tiên tiếng Việt, không có thì tiếng Anh cũng OK". Đây là negotiation đầu tiên khi truy cập Web.
1.1 FE engineering + dictionary swap
Trong FE framework hiện đại, page skeleton được JS gen động local. FE app chủ động đọc preference browser (navigator.language API), rồi pull "language dictionary pack (JSON)" từ server theo nhu cầu — gặp tiếng Việt hiển thị "Xác nhận", gặp tiếng Anh "Confirm".
1.2 Vực thẳm typography: text length + RTL mirror
Ngoài dictionary swap, i18n thật sự đối mặt thử thách lớn ở Layout stage.
Cùng nghĩa, ngôn ngữ khác có độ dài chữ rất khác. Vd tiếng Đức hay nối nhiều từ thành 1 từ cực dài. Nếu CSS dùng width cố định, dễ bị tràn container khi switch sang tiếng Đức. Browser khuyến nghị dùng Flexbox để adaptive.
Thử thách đảo lộn hơn: direction. Tiếng Ả Rập, Hebrew đọc Right-to-Left (RTL). Khi switch sang ngôn ngữ này, không chỉ text direction đổi, browser engine còn phải mirror reverse toàn bộ content block theo horizontal! Browser cung cấp dir="rtl" attribute. CSS phải tránh từ direction tuyệt đối, dùng Flexbox justify-content: flex-start thay vì hardcode margin-left, để browser auto-flip layout theo region.
1.3 Tạm biệt regex: dùng Intl standard
Ngoài typography, browser underlying có sẵn "localization format engine". Cùng số 1200.5, Mỹ thấy $1,200.50, châu Âu dùng dấu phẩy thập phân € 1.200,50. Date format càng đa dạng.
Browser hiện đại expose Intl core object (Intl.DateTimeFormat, Intl.NumberFormat). Trong code chỉ cần chỉ định env code, browser tự call OS data spec, gen string đúng habit local.
👇 Click thử component, xem browser flip layout (RTL) + system-level data convert mà không đổi source data:
实战区 1:依赖 Flex 面向字典与排版进行重构
由于我们在 CSS 中使用了弹性的 Flex 布局,并且没有写死 `margin-left` 而是用了 `gap` 与 `justify-content`,当切换到阿拉伯语时,`dir="rtl"` 属性会指挥浏览器**完美镜像反转**整个布局。当切换到德语时,超长的按钮文字会自动引发弹性换行,而不会溢出。
实战区 2:使用 Intl 引擎接管数据呈现
彻底抛弃正则表达式的截取与拼接!看看原生的 Intl.NumberFormat 和 Intl.DateTimeFormat 是如何根据我们上方选择的“环境代号”将下方固定不变的底层二进制数据无缝格式化的。
1459800.5➔
1757430000000➔
2. Tree vô hình trong browser (a11y)
Quay về render engine. Browser parse HTML → DOM tree, kết hợp CSS → Render Tree để vẽ UI.
Ít người biết, browser còn parallel build 1 tree khác cho OS "xem" — AOM tree (Accessibility Object Model).
2.1 Screen reader + bản chất semantic
Cho user khiếm thị, OS built-in screen reader (vd VoiceOver macOS). Software này "không thấy" pixel màn hình, hoàn toàn dựa vào AOM tree browser expose để đọc.
Nếu dev dùng <div> + CSS vẽ ra button đẹp, trong render tree thường nó hoàn hảo. Nhưng trong AOM tree, chỉ là 1 text node vô nghĩa. User khiếm thị không nghe được "button", không select được bằng Tab.
Vì sao phải nhấn mạnh "dùng HTML tag semantic"? Vì khi dùng <button>, <nav>, <a>, browser tự bổ sung focus management + role trong AOM tree. Semantic = vẽ blueprint chất lượng cao cho visual tool.
2.2 WAI-ARIA: tay sửa AOM tree
App hiện đại có nhiều custom interactive component (popup, accordion menu animation), tag native browser không cover hết. Cần WAI-ARIA spec.
ARIA bản chất = nhóm HTML attribute đặc biệt, không đổi visual, chỉ ra lệnh sửa AOM tree node:
aria-label: bổ sung mô tả đọc cho element không có visible text (vd button "đóng" chỉ có icon)aria-hidden="true": bảo browser node này chỉ decorative, không nhét vào AOM treerole="alert": vùng này critical, content refresh → interrupt voice reader hiện tại để insert
👇 Trải nghiệm 2 "thế giới" qua AOM tree:
❌ 案例 A:纯粹的视觉欺骗
使用 <div> 结合 CSS 绘制。在渲染树上很完美,但在 AOM 树中缺失语义。
✅ 案例 B:语义化 + ARIA 护航
使用 <input>、<button> 等原生标签,补充 aria-label。在 AOM 树中拥有完整交互属性。
3. Web phục vụ mọi người
Kết hợp network + render chương trước:
| Dim | Trách nhiệm | Cầu nối khoảng cách |
|---|---|---|
| i18n | Negotiation header, Intl API format, RTL flex | Ngôn ngữ + văn hoá, app match spec + typography mỗi nước |
| a11y | Ngoài render tree, build AOM tree clear từ semantic HTML + ARIA | Sinh lý + thiết bị, giao control smooth cho screen reader + tool hỗ trợ |
Senior engineer thật sự không chỉ code UI rực rỡ, mà còn polish header + semantic tree vô hình, để Web phủ tới mỗi người ở ngôn ngữ + thiết bị khác. Đây là nhân văn nền của Web — platform lớn nhất thế giới.
2026 cho VN dev
- i18n libs: react-i18next, vue-i18n, next-intl (Next.js)
- VN-specific: số có "₫" + dấu chấm hàng nghìn (1.000.000₫), date dd/mm/yyyy
- a11y testing: axe DevTools, Lighthouse, WAVE
- Screen reader: VoiceOver (Mac), NVDA (Win free), JAWS
- Semantic HTML 2026: dùng
<dialog>,<details>native thay vì custom div - AI a11y: Google Lookout (mô tả image cho khiếm thị), Be My AI (GPT-4V)