[PHP] Note viết hàm chuyển mã (Encoding) tiếng Việt từ TCVN3 sang Unicode

Hôm nay lại bàn về vấn để chuyển mã từ font Tiêu chuẩn Việt Nam 3 (TCVN3) sáng bảng mã quốc tế Unicode.

Lý do là vì hôm trước tìm được thư viện UConvert tưởng tìm được chân kinh, nhưng không ngờ áp dụng vô thực tế cái đang làm không được

Unicode và mã hóa ký tự cũ của Việt Nam

Mặc dù đã khai báo, nhưng cứ hễ gọi cái class UConvert từ trong một hàm nào đó là nó báo lỗi không tìm thấy @@!

Lỗi class UConvert
Lỗi class UConvert

Vậy là đành phải tự viết một cái function chuyển đổi bảng mã thôi :’), cậy người không bằng cậy mình :v

Nói vậy chứ mình cũng dạo thêm một vòng Google xem có ai làm chưa, thì thấy có một người có làm, nhưng làm chưa đến nơi.

—-

Hàm chuyển mã Unicode sang VNI

Hàm chuyển mã tiếng Việt Unicode sang VNI, dùng thủ thuật tìm và thay thế từng âm tiết

Cách dùng

Mở rộngBạn cũng có thể thay thế đoạn code này

Thành thế này

Để thực hiện việc chuyển từ mã VNI sang Unicode.Ngoài ra, bạn cũng có thể dùng Unikey, chuyển nội dung mảng $VNI thành những bảng mã khác.Ví dụ: Hàm chuyển từ bảng mã Unicode sang TCVN3

—-
https://kingno1.wordpress.com/2010/10/04/ham-chuy%E1%BB%83n-ma-unicode-sang-vni/
Tại sao mình nói là chưa đến nơi.
  • Thứ nhất vì bảng mã của Unicode và TCVN3 bạn này dùng mình thấy chưa chuẩn, mình dùng lại thì convert từ Unikey sang khác với của bạn này.
  • Thứ hai là thuật toán chưa hợp lý. Bạn này chỉ dùng hàm str_replace để thay thế ký tự đơn thuần từ TCVN3 sang UNICODE, tuy nhiên khi chạy vòng lặp lại là lặp hết mảng UNICODE hoặc TCVN3, đều này dẫn đến là nếu một chuỗi có một ký tự chuyển từ TCVN3 sang UNICODE ra 1 ký tự, ký tự này lại nằm trong mảng TCVN3 nữa thì nó sẽ lại bị thay thế một lần nữa.
Ví dụ trường hợp mình bị là đối với chuỗi
ch©u ®èc
Chuỗi này chuyển sang UNICODE đúng là châu đốc
châu đốc
Tuy nhiên khi dùng cách chuyển như bạn thì từ © trong từ ch©u sẽ bị chuyển thành â, từ â lại bị chuyển thành
Kết quả mình có:
Lỗi font
Lỗi font
Để khắc phục mình đưa ra ý tưởng là thay vì lập hết mảng TCVN3 hay Unicode thì mình duyệt qua từ ký tự của chuỗi. Sau đó xác định vị trí của ký tự trong mảng TCVN3, thay thế nó bằng ký tự ở mảng Unicode ở vị trí tương ứng. Như vậy mỗi ký tự trong chuỗi chỉ được duyệt qua và thay thế 1 lần thôi. Tránh tình trạng bị thay thế 2 lần như cách của bạn ở trên.
Cuối cùng ráp lại ta có chuỗi mới.
Thực hiện.

Đầu tiên tạo một mảng chứa các ký tự Unicode


Sau đó mình dùng Unikey convert cái này sang TCVN3 để có mảng các ký tự theo TCVN3

Unikey convert sang TCVN3
Unikey convert sang TCVN3

Bây giờ đến giai đoạn tách chuỗi, ban đầu mình dùng hàm str_split, nhưng hàm này tách riêng từng byte (từng char, ngay cả dấu sắc, dấu hỏi,..)

Do mình dùng tiếng Việt là mã Multi byte, do vậy mình đã sửa chuyển sang dùng hàm mb_split

$arr1=mb_split($text,’UTF-8′);

Và để đếm ký tự multi byte thì cũng có hàm riêng cho nó

$len = mb_strlen($text, ‘UTF-8’);

Cái vòng lập duyệt qua từng char

Cuối cùng, ráp mảng kết quả lại bằng hàm implode

$text=implode(“”,$arr2);

Code full hàm chuyển đổi bảng mã tiếng Việt TCVN3 sang Unicode của mình

Kết quả

Hàm php chuyển mã tiếng Việt
Hàm php chuyển mã tiếng Việt

Hi vọng giúp được mọi người, đối với các bảng mã khác cũng tương tụ vậy nhé

-soiqualang_chentreu-

Tham khảo

https://stackoverflow.com/questions/38126940/php-str-split-and-utf8-polish-characters

https://stackoverflow.com/questions/29710635/fatal-error-call-to-undefined-function-mb-split

http://php.net/manual/en/function.mb-split.php

https://www.w3schools.com/php/func_string_implode.asp

http://php.net/manual/en/function.str-split.php

https://stackoverflow.com/questions/2959222/get-the-index-value-of-an-array-in-php