Lập trình · 19/10/2026

Intl.Collator: sắp xếp tên và mã tài liệu theo ngôn ngữ trong JavaScript

Danh sách tài liệu hiển thị “Tệp 1, Tệp 10, Tệp 2” dù người dùng muốn đọc theo thứ tự số. Một comparator theo mã ký tự có thể đúng về mặt kỹ thuật nhưng chưa phù hợp cách người dùng tìm tài liệu. Intl.Collator cung cấp phép so sánh chuỗi theo ngôn ngữ và các tùy chọn sắp xếp rõ ràng.

Intl.Collator: sắp xếp tên và mã tài liệu theo ngôn ngữ trong JavaScript

Danh sách tài liệu hiển thị “Tệp 1, Tệp 10, Tệp 2” dù người dùng muốn đọc theo thứ tự số. Một comparator theo mã ký tự có thể đúng về mặt kỹ thuật nhưng chưa phù hợp cách người dùng tìm tài liệu. Intl.Collator cung cấp phép so sánh chuỗi theo ngôn ngữ và các tùy chọn sắp xếp rõ ràng.

Bài viết dùng danh sách nhỏ trong bộ nhớ. Khi dữ liệu đã được phân trang ở server, thứ tự toàn bộ danh sách phải được giải quyết tại nguồn; sắp lại một trang ở trình duyệt không tạo ra thứ tự đúng cho tất cả các trang.

1. So sánh phần số trong tên tài liệu

const files = ['Tệp 10', 'Tệp 2', 'Tệp 1'];
const collator = new Intl.Collator('vi', {
  usage: 'sort',
  numeric: true
});
const sorted = [...files].sort(collator.compare);

console.log(sorted.join(' | ')); // Tệp 1 | Tệp 2 | Tệp 10
console.log(files.join(' | '));  // Tệp 10 | Tệp 2 | Tệp 1

Tùy chọn numeric giúp so sánh các đoạn chữ số theo giá trị số. Ví dụ tạo một collator để tái sử dụng, rồi sắp xếp bản sao mảng để giữ thứ tự nguồn. Đây không phải parser cho mọi định dạng số: đừng dùng nó thay quy tắc số thập phân, phiên bản phần mềm hoặc ngày tháng của sản phẩm.

2. Chỉ xét dấu của kết quả compare

const compare = new Intl.Collator('en', {
  numeric: true
}).compare;

console.log(compare('File 2', 'File 10') < 0); // true
console.log(compare('File 10', 'File 2') > 0); // true
console.log(compare('File 2', 'File 2') === 0); // true

Hợp đồng của compare phân biệt số âm, số dương và 0. Đừng viết kiểm thử buộc kết quả phải là -1 hoặc 1: độ lớn cụ thể không phải điều cần dựa vào. Comparator cũng không nên sửa object hoặc gọi API trong lúc sắp xếp.

3. sensitivity là chính sách so sánh

const relaxed = new Intl.Collator('en', {
  sensitivity: 'base'
});
const detailed = new Intl.Collator('en', {
  sensitivity: 'variant'
});

console.log(relaxed.compare('resume', 'résumé') === 0); // true
console.log(detailed.compare('resume', 'résumé') !== 0); // true
console.log(relaxed.compare('A', 'a') === 0);           // true

Ví dụ chọn locale en để minh họa khác biệt độ nhạy. Không suy rộng kết quả bỏ dấu sang mọi ngôn ngữ: một chữ có dấu có thể là chữ cái cơ sở riêng trong locale khác. Với tiếng Việt, hãy dùng bộ tên thật gồm a, ă, â, d, đ cùng các thanh để duyệt quy tắc mong muốn trên runtime đích.

Hai chuỗi được collator coi ngang nhau không có nghĩa chúng là cùng ID hay cùng tài khoản. Không dùng compare bằng 0 làm lý do tự gộp bản ghi, bỏ kiểm tra uniqueness hoặc thay thế chính sách đăng nhập.

4. Khi tên ngang nhau, thêm khóa phụ rõ ràng

const rows = [
  { id: 'b', name: 'File 2' },
  { id: 'a', name: 'File 2' },
  { id: 'c', name: 'File 10' }
];
const byName = new Intl.Collator('en', { numeric: true });
const byId = (a, b) => a < b ? -1 : a > b ? 1 : 0;
const ordered = [...rows].sort((a, b) =>
  byName.compare(a.name, b.name) || byId(a.id, b.id)
);

console.log(ordered.map(row => row.id).join(',')); // a,b,c

Trong ví dụ, id là chuỗi duy nhất và được so theo thứ tự chuỗi để phá hòa; đây là lựa chọn tường minh. Nếu ID là chuỗi số lớn nhưng sản phẩm cần thứ tự số, cần comparator khác, tránh ép sang Number làm mất chính xác.

Khóa phụ giúp kết quả ít phụ thuộc thứ tự đầu vào khi tên ngang nhau. Nó không bảo đảm frontend và database sẽ cùng thứ tự nếu hai nơi dùng collation khác nhau. API phân trang cần công bố thứ tự và khóa phụ do server áp dụng.

5. Kiểm tra locale thực tế

const supported = Intl.Collator.supportedLocalesOf(['vi']);
const collator = new Intl.Collator('vi', { numeric: true });

console.log(supported.includes('vi'));          // true trong môi trường kiểm tra
console.log(collator.resolvedOptions().numeric); // true

supportedLocalesOf cho biết locale được hỗ trợ mà không cần rơi về locale mặc định của runtime. resolvedOptions giúp xem lựa chọn đã được phân giải. Các môi trường có thể khác dữ liệu ngôn ngữ, vì vậy cần kiểm tra Node.js và trình duyệt thực tế thay vì chỉ nhìn một kết quả local.

6. Checklist trước khi áp dụng

  • Thống nhất locale, numeric và sensitivity theo nhu cầu đọc danh sách.
  • Thử tên có chữ số, dấu, hoa/thường, khoảng trắng và giá trị trùng.
  • Quy định xử lý null hoặc thiếu tên trước khi gọi comparator.
  • Kiểm tra mảng nguồn giữ nguyên nếu ứng dụng yêu cầu.
  • Dùng khóa phụ và thống nhất với thứ tự ở API khi phân trang.
  • Đo với danh sách thực tế trước khi tối ưu hoặc chuyển việc sắp xếp.

Các đoạn code đã chạy bằng Node.js local có hỗ trợ locale vi. Chưa kiểm thử giao diện trình duyệt hoặc collation database production. Tài liệu đối chiếu: Intl.Collator và các tùy chọn khởi tạo.

Một thứ tự dễ đọc bắt đầu từ quy tắc sản phẩm rõ ràng. Dùng collator cho so sánh hiển thị, rồi kiểm tra riêng kiểu dữ liệu, định danh và thứ tự toàn bộ tập kết quả.

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.