Lưu LoátWiki
Tìm
Bảng mã & Unicode

NFC và NFD là gì: Unicode dựng sẵn, tổ hợp và cách chuẩn hoá chữ Việt

NFC gộp chữ và dấu thành một ký tự, NFD tách thành chữ gốc cộng dấu. Hai dạng trông như nhau nhưng làm tìm kiếm, lọc trùng sai. Thứ tự dấu, chữ đ và đoạn mã chuẩn hoá.

NFC và NFD là gì: Unicode dựng sẵn, tổ hợp và cách chuẩn hoá chữ Việt

NFC và NFD là hai dạng chuẩn hoá Unicode: NFC (dựng sẵn) gộp chữ và dấu thành một ký tự khi có thể, ví dụ "ệ" là một ký tự U+1EC7; NFD (tách rời) bẻ chữ thành chữ gốc cộng các dấu kết hợp, "ệ" thành ba ký tự e + dấu nặng + dấu mũ. Hai dạng hiện ra giống hệt nhau trên màn hình nhưng là hai chuỗi khác nhau trong máy, nên tìm kiếm, so trùng, sắp xếp, đếm độ dài có thể sai. Cách xử lý chuẩn: đưa mọi văn bản tiếng Việt về NFC trước khi lưu và so sánh.

Một chữ, nhiều cách lưu

Unicode chứa cả chữ dựng sẵn (như ệ, ở, ữ) lẫn các dấu kết hợp (dấu huyền U+0300, sắc U+0301, ngã U+0303, hỏi U+0309, nặng U+0323, mũ U+0302, trăng U+0306, móc U+031B). Vì thế cùng một chữ Việt có thể được ghi theo nhiều cách:

Cách ghi chữ "ệ"Chuỗi mãSố ký tự
Dựng sẵn (NFC)U+1EC71
Tách rời hoàn toàn (NFD)U+0065 U+0323 U+03023
Nửa dựng nửa tách (kiểu Windows-1258, một số bộ gõ "tổ hợp")U+00EA U+0323 (ê + dấu nặng)2

Ba chuỗi này Unicode coi là tương đương chuẩn tắc (canonically equivalent) — cùng một chữ. Nhưng một phép so sánh đơn giản từng ký tự sẽ coi chúng khác nhau.

Bốn dạng chuẩn hoá trong Unicode

Tài liệu UAX #15 của Unicode định nghĩa bốn dạng chuẩn hoá:

DạngLàm gìDùng cho tiếng Việt
NFCTách ra rồi gộp lại thành dạng dựng sẵn khi có thểDạng nên dùng để lưu, hiển thị, so sánh
NFDTách hết thành chữ gốc + dấu kết hợp, xếp dấu theo thứ tự chuẩnDùng tạm khi cần bỏ dấu, phân tích dấu
NFKCNhư NFC, thêm gộp các biến thể "tương thích" (chữ fi ghép thành f+i, số mũ ² thành 2)Dùng khi làm chỉ mục tìm kiếm; không dùng để lưu văn bản gốc
NFKDNhư NFD, thêm phép tương thíchÍt dùng

Với văn bản tiếng Việt thường, NFC và NFKC cho cùng kết quả ở phần chữ cái; khác biệt chỉ ở các ký hiệu đặc biệt. Quy tắc đơn giản: lưu bằng NFC.

Thứ tự dấu trong NFD: chi tiết hay bị bỏ qua

Khi tách, Unicode không xếp dấu theo thứ tự người Việt hay nghĩ ("mũ trước, thanh sau"), mà theo một con số gọi là lớp kết hợp (combining class). Dấu nằm dưới (dấu nặng, lớp 220) và dấu móc (lớp 216) đứng trước các dấu nằm trên (lớp 230).

ChữDạng NFD
ệe + dấu nặng (U+0323) + dấu mũ (U+0302)
ặa + dấu nặng (U+0323) + dấu trăng (U+0306)
ợo + dấu móc (U+031B) + dấu nặng (U+0323)
ễe + dấu mũ (U+0302) + dấu ngã (U+0303)
đđ (U+0111) — không tách

Hai hệ quả thực tế. Thứ nhất: chuỗi "nửa dựng nửa tách" như ê + dấu nặng không phải NFC cũng không phải NFD; phải chuẩn hoá mới về đúng dạng. Thứ hai: chữ đ không bị tách thành d + gạch ngang, vì Unicode coi đ là một chữ riêng. Muốn bỏ dấu tiếng Việt bằng NFD, phải thay đ → d, Đ → D bằng tay.

Dạng tách đến từ đâu

  • Tên tệp trên macOS. Hệ thống tệp của Apple từ lâu có xu hướng lưu tên tệp ở dạng tách. Tệp tên "Báo cáo tháng 11.docx" tạo trên Mac, nén lại gửi sang Windows hoặc tải lên web, có thể mang tên dạng NFD.
  • Chép chữ từ một số tệp PDF. Tuỳ cách tạo PDF, chữ chép ra có thể là chữ gốc cộng dấu kết hợp.
  • Bộ gõ đặt bảng mã "Unicode tổ hợp". Unikey và một số bộ gõ có tuỳ chọn này; chọn nhầm là mọi chữ gõ ra đều dạng tổ hợp.
  • Dữ liệu chuyển từ Windows-1258 sang Unicode mà không chuẩn hoá.
  • Nhập liệu từ nhiều nguồn — form trên web, ứng dụng điện thoại, tệp Excel của đối tác.

Triệu chứng: biết mình đang gặp NFD

Triệu chứngVí dụ
Tìm kiếm không ra dù chữ nhìn y hệtTìm "Nguyễn" trong danh sách có "Nguyễn" mà không thấy
Đếm độ dài saiHàm LEN trong Excel trả về 6 cho chữ "Việt" thay vì 4
Lọc trùng không gộp đượcHai dòng "Hà Nội" giống nhau vẫn được coi là hai giá trị
Dấu hiện lệch, chồng không khítDấu nặng lệch sang bên, dấu mũ và dấu sắc dính nhau với một số phông
Xoá một lần chỉ mất dấuỞ một số trình soạn thảo, nhấn Backspace sau "ệ" còn lại "ẹ"
Tên tệp "trùng" mà không đè nhauMột thư mục có hai tệp tên giống hệt nhau

Vì sao dạng tổ hợp hay bị dấu lệch? Khi chữ dựng sẵn, nhà thiết kế phông đã vẽ sẵn hình chữ "ệ" với dấu đặt khít. Khi chữ tổ hợp, phần mềm phải tự đặt dấu nặng và dấu mũ lên chữ "e" dựa trên thông tin định vị dấu trong phông. Phông mới, làm kỹ thì kết quả gần như không khác; phông cũ hoặc phông thiếu thông tin định vị thì dấu chồng lên nhau, lệch sang bên hoặc đè vào chữ.

Chuẩn hoá về NFC: đoạn mã mang về

Người làm web, làm dữ liệu nên chuẩn hoá ngay khi nhận dữ liệu vào, trước khi lưu.

Ngôn ngữCâu lệnh
Pythonunicodedata.normalize('NFC', chuoi)
JavaScriptchuoi.normalize('NFC')
PHP (cần tiện ích intl)Normalizer::normalize($chuoi, Normalizer::FORM_C)
JavaNormalizer.normalize(chuoi, Normalizer.Form.NFC)
C# (.NET)chuoi.Normalize(NormalizationForm.FormC)

Bỏ dấu tiếng Việt để làm đường dẫn hay tìm kiếm không dấu (Python): chuẩn hoá NFD, bỏ mọi ký tự có lớp kết hợp khác 0, rồi thay đ/Đ. Nếu quên bước thay đ, "Đà Nẵng" sẽ thành "Đa Nang" chứ không phải "Da Nang".

Người dùng văn phòng không lập trình: chuyển mã bằng bộ công cụ của bộ gõ (chọn nguồn "Unicode tổ hợp", đích "Unicode dựng sẵn"), và kiểm tra trong bộ gõ của mình rằng bảng mã đang là "Unicode" hoặc "Unicode dựng sẵn".

Bài tập: tự phát hiện chữ tổ hợp

  1. Mở Excel, gõ "Việt" vào ô A1, ô B1 nhập công thức =LEN(A1). Kết quả 4 là dựng sẵn.
  2. Tìm một tệp có tên tiếng Việt tạo trên máy Mac (hoặc chép một dòng từ PDF), dán vào ô A2, công thức =LEN(A2). Nếu số lớn hơn số chữ đếm bằng mắt, đó là dạng tổ hợp.
  3. Ô C1 nhập =A1=A2. Hai chữ trông giống nhau mà kết quả FALSE là đã gặp chuyện NFC – NFD.

Góc nhìn hôm nay

Đa số người dùng không bao giờ phải nghĩ đến NFC hay NFD, vì bộ gõ phổ biến mặc định dựng sẵn. Nhưng khi dữ liệu đến từ nhiều nguồn — Mac và Windows, điện thoại và web, PDF và Excel — dạng tổ hợp lặng lẽ chen vào và gây ra những lỗi "không thể giải thích": tìm không ra, lọc không gộp, sắp xếp sai. Nguyên tắc đơn giản là chuẩn hoá về NFC ngay ở cửa vào. Tài liệu UAX #15 "Unicode Normalization Forms" trên unicode.org là nguồn gốc chính xác nhất cho ai cần đi sâu.

Câu hỏi thường gặp

NFC và NFD là gì?

Đó là hai dạng chuẩn hoá Unicode. NFC gộp chữ và dấu thành ký tự dựng sẵn khi có thể, NFD tách chữ thành chữ gốc cộng các dấu kết hợp. Hai dạng hiển thị giống nhau nhưng là chuỗi khác nhau trong máy.

Văn bản tiếng Việt nên dùng NFC hay NFD?

Nên dùng NFC (Unicode dựng sẵn) để lưu, hiển thị và so sánh. Đây cũng là mặc định của các bộ gõ phổ biến. NFD chỉ nên dùng tạm khi cần xử lý dấu, ví dụ để bỏ dấu.

Vì sao tên tệp tiếng Việt từ Mac sang Windows bị lỗi?

Hệ thống tệp của Apple có xu hướng lưu tên tệp ở dạng tách (NFD). Sang Windows hoặc lên web, tên tệp có thể hiển thị dấu lệch, tìm kiếm không ra hoặc tạo hai tệp tên giống nhau.

Bỏ dấu tiếng Việt bằng NFD có cần lưu ý gì?

Chữ đ và Đ không bị tách khi chuẩn hoá NFD vì Unicode coi đó là chữ riêng. Sau khi bỏ dấu kết hợp, cần thay đ thành d và Đ thành D bằng tay.

Làm sao biết chữ đang ở dạng tổ hợp?

Dùng hàm đếm độ dài như LEN trong Excel: chữ "Việt" dựng sẵn cho 4, dạng tổ hợp cho nhiều hơn. Ở một số trình soạn thảo, xoá bằng Backspace mà chỉ mất dấu cũng là dấu hiệu của dạng tổ hợp.

Mở app Lưu Loát

Gõ tiếng Việt nhanh, chuẩn, lưu loát từng dấu

Mở app Lưu Loát

Bài viết liên quan

Mở app Lưu Loát

Gõ tiếng Việt nhanh, chuẩn, lưu loát từng dấu

Mở app Lưu Loát Xem app khác