Regex Tiếng Nhật Và Validation Input Trong React
Làm việc cho các dự án của khách hàng từ Nhật Bản, chúng ta sẽ thường xuyên phải validate dữ liệu tiếng Nhật: Hiragana, Katakana, Kanji, và đặc biệt là hai dạng Full-width (Zenkaku) và Half-width (Hankaku) của cùng một ký tự. Bài viết này tổng hợp các regular expression thông dụng nhất khi làm việc với dữ liệu tiếng Nhật, kèm theo best practice khi áp dụng chúng, và cách xử lý validation/input đúng cách ở phía Frontend — đặc biệt là với React, nơi một filter viết sai có thể phá vỡ hoàn toàn trải nghiệm gõ tiếng Nhật qua IME.
Nếu bạn chưa nắm khái niệm Full-width/Half-width, nên đọc trước bài Full-width vs Half-width Trong Tiếng Nhật — xét trên một font có chiều rộng/chiều cao cố định, ký tự half-width (hankaku) chiếm nửa bề rộng so với ký tự full-width (zenkaku), chiều cao thì không đổi.
Bảng Regex Thông Dụng Cho Text Tiếng Nhật
| Mục đích | Regex | Ví dụ khớp |
|---|---|---|
| Chữ số Full-width (Zenkaku) | /^[ー]?[0-9]+(\.[0-9]+)?$/ |
123, ー12.5 |
| Chữ số Half-width (Hankaku) | /^[-]?[0-9]+(\.[0-9]+)?$/ |
123, -12.5 |
| Chữ cái Latin Half-width (Hankaku) | /^[a-zA-Z]+$/ |
ABC, abc |
| Hiragana Full-width (Zenkaku) | /^[ぁ-ん]+$/ |
あいうえお |
| Katakana Full-width (Zenkaku) | `/^([ァ-ン] | ー)+$/` |
| Hiragana + Katakana Full-width | /^[ぁ-んァ-ン]+$/ |
あアいイ |
| Katakana Half-width (Hankaku) | /^[ァ-ン゙゚]+$/ |
アイウエオ |
| Kanji | /^[一-龥]+$/ |
日本語 |
| Hiragana Full-width + Kanji | /^[一-龥ぁ-ん]+$/ |
日本のはなし |
| Hiragana + Katakana Full-width + Kanji | /^[ぁ-んァ-ン一-龥]+$/ |
東京タワーへ行く |
| Mã bưu chính (postal code) | /^\d{3}-\d{4}$/ |
123-4567 |
| Số điện thoại cố định | /^[0-9-]{6,9}$|^[0-9-]{12}$/ |
03-1234-5678 |
(Hai regex "Hiragana Full-width + Kanji" và "Hiragana + Katakana Full-width + Kanji" ở trên đã được thêm +$ ở cuối so với bản nháp gốc — thiếu $ khiến regex chỉ kiểm tra ký tự đầu chuỗi, không đảm bảo toàn bộ chuỗi hợp lệ, xem mục Best Practice bên dưới. Mã bưu chính cũng được gộp lại thành một pattern duy nhất đúng chuẩn Nhật Bản 3 số - 4 số, thay vì hai dòng gốc dễ gây nhầm lẫn.)
Best Practice Khi Dùng Regex Tiếng Nhật
1. Luôn anchor cả hai đầu bằng ^ và $
Thiếu $ là lỗi phổ biến nhất khi copy-paste regex: /^[一-龥ぁ-ん]/ chỉ kiểm tra ký tự đầu tiên của chuỗi, nghĩa là "日本abc<script>" vẫn "khớp" vì ký tự đầu là Kanji hợp lệ. Luôn viết đầy đủ /^[...]+$/ để đảm bảo toàn bộ chuỗi chỉ chứa các ký tự cho phép.
2. Cân nhắc dùng Unicode property escape thay vì hardcode range
Các range như [ぁ-ん], [ァ-ン], [一-龥] hoạt động tốt nhưng dễ gõ sai hoặc bỏ sót ký tự biên (ví dụ 龥 không phải là ký tự Kanji cuối cùng theo chuẩn Unicode CJK Unified Ideographs hiện tại). JavaScript hiện đại hỗ trợ Unicode property escape rõ ràng và dễ đọc hơn:
// Thay vì hardcode range:
const kanjiRegexOld = /^[一-龥]+$/
// Nên dùng Unicode script property (cần flag "u"):
const hiraganaRegex = /^\p{Script=Hiragana}+$/u
const katakanaRegex = /^\p{Script=Katakana}+$/u
const kanjiRegex = /^\p{Script=Han}+$/u
Giải thích: \p{Script=Hiragana} khớp với toàn bộ khối Unicode Hiragana chính thức, không phụ thuộc vào việc bạn có gõ đúng range hex hay không. Bắt buộc phải có flag u (Unicode mode) thì cú pháp \p{...} mới hoạt động.
3. Regex không tự động normalize — đừng chỉ Reject, hãy cân nhắc Normalize trước
Một regex half-width digit (/^[-]?[0-9]+(\.[0-9]+)?$/) sẽ reject ngay khi user paste 123 (full-width, do IME auto-convert). Với UX tốt hơn, nên convert full-width → half-width trước khi chạy regex, thay vì báo lỗi ngay cho một giá trị mà user không cố ý gõ sai (xem phần "Khi Nào Nên Normalize" trong bài Full-width/Half-width).
4. Regex chỉ là điều kiện cần, không phải điều kiện đủ
Regex kiểm tra được loại ký tự, nhưng không kiểm tra được ý nghĩa nghiệp vụ — ví dụ /^\d{3}-\d{4}$/ chấp nhận 000-0000 dù đây không phải mã bưu chính thật. Với dữ liệu quan trọng (mã bưu chính, số điện thoại), nên kết hợp thêm một bước xác thực nghiệp vụ (tra cứu bảng mã bưu chính thật, hoặc gọi API xác thực) thay vì chỉ tin vào regex.
5. Không dùng regex để "chặn" input theo từng phím gõ
Đây là lỗi kỹ thuật nghiêm trọng nhất khi áp dụng các regex trên vào input tiếng Nhật — xem chi tiết ngay phần tiếp theo.
Yêu cầu đăng nhập
Vui lòng đăng nhập để truy cập nội dung này
Additional Resources
Course Guide
Comprehensive PDF guide with examples
GitHub Repository
Example code for all lessons
Discussion
Have a question about this lesson? Post it here and get answers from instructors and peers.
