Tổ hợp emoji thay đổi ý nghĩa - Sự khác biệt về lượng thông tin giữa 1 ký tự và 2 ký tự trở lên
Khi bạn chọn "👨👩👧👦" từ bàn phím emoji trên điện thoại, bạn nghĩ mình đang nhập 1 emoji. Thực tế, emoji gia đình này là sự nối tiếp của 7 điểm mã: "👨 + ZWJ + 👩 + ZWJ + 👧 + ZWJ + 👦". Bề ngoài là 1 ký tự, bên trong là 7. Trong thế giới emoji, tùy cách tổ hợp mà ý nghĩa và số ký tự của 1 biểu tượng có thể thay đổi đáng kể.
Chuỗi ZWJ - Keo dán vô hình hợp nhất emoji
ZWJ (Zero Width Joiner) là "ký tự nối không chiều rộng" được gán cho điểm mã Unicode U+200D. Nó không hiển thị gì trên màn hình nhưng đóng vai trò keo dán gắn kết các emoji trước và sau thành một.
Cơ chế rất đơn giản. Đặt emoji A + ZWJ + emoji B liên tiếp, nếu hệ điều hành hoặc ứng dụng có glyph (hình ảnh hiển thị) cho tổ hợp đó, A và B sẽ hợp nhất hiển thị thành một emoji. Nếu không có glyph phù hợp, A và B đơn giản hiển thị cạnh nhau. Nói cách khác, chuỗi ZWJ là cơ chế linh hoạt: "hợp nhất được thì hợp, không thì giữ nguyên".
| Chuỗi ZWJ | Thành phần | Số điểm mã | Hiển thị |
|---|---|---|---|
| 👨👩👧👦 | 👨 + ZWJ + 👩 + ZWJ + 👧 + ZWJ + 👦 | 7 | Gia đình (bố mẹ con gái con trai) |
| 👩💻 | 👩 + ZWJ + 💻 | 3 | Nữ kỹ thuật viên |
| 🏳️🌈 | 🏳️ + ZWJ + 🌈 | 4 | Cờ cầu vồng |
| 👨🍳 | 👨 + ZWJ + 🍳 | 3 | Đầu bếp nam |
| 🧑🚀 | 🧑 + ZWJ + 🚀 | 3 | Phi hành gia |
| ❤️🔥 | ❤️ + ZWJ + 🔥 | 4 | Trái tim bốc cháy |
| 👩❤️👨 | 👩 + ZWJ + ❤️ + ZWJ + 👨 | 5 | Cặp đôi |
Emoji gia đình nằm trong số các chuỗi ZWJ có nhiều điểm mã nhất. Gia đình 4 người "👨👩👧👦" có 7 điểm mã, mã hóa UTF-8 lên đến 25 byte. Chỉ 1 emoji mà tiêu tốn lượng dữ liệu tương đương 25 chữ cái tiếng Anh.
Điều thú vị của chuỗi ZWJ là về lý thuyết có thể thử nối bất kỳ hai emoji nào. Nhập "🐱 + ZWJ + 🐉" (mèo và rồng) - tổ hợp chưa được định nghĩa - sẽ không gây lỗi. Vì không có glyph phù hợp, mèo và rồng đơn giản hiển thị cạnh nhau. Unicode Consortium đã chính thức định nghĩa khoảng 600 chuỗi ZWJ, nhưng các nhà cung cấp đôi khi tự thêm hỗ trợ.
Emoji cờ quốc gia - 2 ký tự chỉ báo khu vực vẽ 1 lá cờ
🇯🇵 (cờ Nhật Bản) trông như 1 emoji, nhưng thực tế là tổ hợp 2 ký tự: "Ký hiệu chỉ báo khu vực chữ J" (U+1F1EF) và "Ký hiệu chỉ báo khu vực chữ P" (U+1F1F5). Mã quốc gia ISO 3166-1 alpha-2 "JP" được biểu diễn bằng các ký tự Unicode chuyên dụng.
| Cờ | Mã quốc gia | Chỉ báo khu vực | Điểm mã |
|---|---|---|---|
| 🇯🇵 | JP | 🇯 + 🇵 | U+1F1EF U+1F1F5 |
| 🇺🇸 | US | 🇺 + 🇸 | U+1F1FA U+1F1F8 |
| 🇬🇧 | GB | 🇬 + 🇧 | U+1F1EC U+1F1E7 |
| 🇫🇷 | FR | 🇫 + 🇷 | U+1F1EB U+1F1F7 |
| 🇧🇷 | BR | 🇧 + 🇷 | U+1F1E7 U+1F1F7 |
| 🇰🇷 | KR | 🇰 + 🇷 | U+1F1F0 U+1F1F7 |
Có 26 ký hiệu chỉ báo khu vực (A đến Z), lý thuyết có 26 × 26 = 676 tổ hợp. Tuy nhiên chỉ khoảng 250 mã quốc gia và vùng lãnh thổ đăng ký trong ISO 3166-1 mới hiển thị thành cờ. Tổ hợp chưa đăng ký (ví dụ "🇽🇽") có thể hiển thị thành văn bản "XX" hoặc khoảng trắng tùy nền tảng.
Thiết kế này chứa đựng cân nhắc chính trị. Unicode Consortium tránh phán xét chính trị "khu vực nào được coi là quốc gia" bằng cách không định nghĩa trực tiếp emoji cờ, mà ủy thác cho tiêu chuẩn quốc tế hiện có ISO 3166-1. Nếu quốc gia mới độc lập và đăng ký trong ISO 3166-1, emoji cờ tự động khả dụng mà không cần thay đổi đặc tả Unicode.
Như đã thảo luận trong giới hạn ký tự URL, mã quốc gia xuất hiện ở nhiều nơi trên internet. ccTLD (tên miền cấp cao nhất mã quốc gia) ".jp" cũng dựa trên cùng mã quốc gia ISO 3166-1.
Bộ điều chỉnh tông da - 1 emoji biến thành 5 màu
Bộ điều chỉnh tông da (Emoji Modifier) được giới thiệu trong Unicode 8.0 năm 2015, dùng để thay đổi màu da của emoji người. 5 cấp độ bộ điều chỉnh dựa trên thang Fitzpatrick dùng trong da liễu.
| Bộ điều chỉnh | Điểm mã | Phân loại Fitzpatrick | Ví dụ (👋 + bộ điều chỉnh) |
|---|---|---|---|
| 🏻 | U+1F3FB | Type I-II (da sáng) | 👋🏻 |
| 🏼 | U+1F3FC | Type III (da hơi sáng) | 👋🏼 |
| 🏽 | U+1F3FD | Type IV (da trung bình) | 👋🏽 |
| 🏾 | U+1F3FE | Type V (da hơi tối) | 👋🏾 |
| 🏿 | U+1F3FF | Type VI (da tối) | 👋🏿 |
Thêm bộ điều chỉnh tông da biến 1 emoji thành 2 điểm mã. "👋" (U+1F44B) là 1 điểm mã, nhưng "👋🏽" là "U+1F44B U+1F3FD" - 2 điểm mã. UTF-8 là 4 byte + 4 byte = 8 byte. Chỉ định tông da đã nhân đôi kích thước dữ liệu.
Khi kết hợp chuỗi ZWJ và bộ điều chỉnh tông da, số điểm mã tăng vọt. Ví dụ emoji cặp đôi có tông da khác nhau "👩🏻❤️👨🏿" gồm 👩 + 🏻 + ZWJ + ❤️ + VS16 + ZWJ + 👨 + 🏿 - 8 điểm mã. Trông như 1 emoji nhưng bên trong mang lượng dữ liệu gần bằng cụm từ tiếng Anh "Hi there!" (9 ký tự).
Tiếng lóng emoji - Thế giới ẩn ngữ sinh ra từ tổ hợp
Emoji không chỉ được dùng với nghĩa chính thức mà còn được sử dụng như tiếng lóng độc đáo trong cộng đồng người dùng. Những emoji vô hại khi đứng riêng có thể mang ý nghĩa hoàn toàn khác khi kết hợp.
Ví dụ nổi tiếng nhất có lẽ là tổ hợp 🍑🍆. Đào và cà tím - emoji thực phẩm - nhưng trên mạng xã hội được công nhận rộng rãi là ẩn dụ tình dục. Năm 2019, Instagram đã hạn chế kết quả tìm kiếm cho bài đăng chứa tổ hợp này.
| Tổ hợp emoji | Số ký tự | Nghĩa chính thức | Nghĩa lóng |
|---|---|---|---|
| 🍑🍆 | 2 ký tự | Đào và cà tím | Ẩn dụ tình dục |
| 🧢 | 1 ký tự | Mũ bóng chày | Nói dối (cap = nói dối) |
| 💀 | 1 ký tự | Hộp sọ | Cười chết đi được |
| 🐐 | 1 ký tự | Dê | GOAT (Greatest Of All Time) |
| 👁️👄👁️ | 3 ký tự | Mắt và miệng | Biểu cảm sốc / bối rối |
| 🫠 | 1 ký tự | Mặt tan chảy | Xấu hổ / ngượng ngùng |
| 🤡 | 1 ký tự | Chú hề | Người làm điều ngốc nghếch |
"👁️👄👁️" là dạng "nghệ thuật emoji" sắp xếp 3 emoji thành khuôn mặt: mắt + miệng + mắt, biểu đạt "biểu cảm khó tả". Tổ hợp 3 ký tự này lan truyền trên TikTok từ khoảng năm 2020, dùng để thể hiện sốc, bối rối hoặc cảm giác "vừa nhìn thấy điều gì đó".
Tiếng lóng emoji khác nhau theo thế hệ và khu vực. Ở Nhật Bản, 🙏 dùng để nói "xin hãy" hoặc "cảm ơn", trong khi ở phương Tây đôi khi được hiểu là "đập tay". Như đã giải thích trong Unicode emoji và cách đếm ký tự, số ký tự kỹ thuật của emoji và "lượng ý nghĩa" con người cảm nhận hoàn toàn ở hai chiều khác nhau.
Cách đếm ký tự emoji khác nhau trên từng nền tảng SNS
Cách đếm ký tự emoji khác biệt đáng kể giữa các nền tảng. Cùng một emoji đăng trên Twitter (X) và Instagram tiêu tốn số ký tự khác nhau.
| Nền tảng | Cách đếm emoji | Đếm 👨👩👧👦 | Đếm 🇯🇵 |
|---|---|---|---|
| Twitter (X) | Số ký tự sau chuẩn hóa NFC | 1 ký tự (= tiêu tốn 2 ký tự) | 1 ký tự (= tiêu tốn 2 ký tự) |
| Số đơn vị mã UTF-16 | 11 ký tự | 4 ký tự | |
| LINE | Đếm riêng | 1 ký tự | 1 ký tự |
| SMS | UCS-2 (16-bit) | 7 ký tự | 2 ký tự |
| JavaScript | Đơn vị mã UTF-16 | .length = 11 | .length = 4 |
Twitter (X) khá rộng rãi, coi emoji gia đình chuỗi ZWJ và emoji cờ như 1 emoji theo giao diện (nhưng nội bộ mỗi cái tính 2 ký tự). Như chi tiết trong giới hạn ký tự Twitter, trong giới hạn 280 ký tự mỗi emoji tính 2 ký tự.
Thuộc tính .length của JavaScript trả về số đơn vị mã UTF-16, nên emoji chứa cặp thay thế trả về giá trị lớn hơn số ký tự nhìn thấy. Emoji gia đình "👨👩👧👦" có .length là 11. Để có số đếm chính xác, dùng Array.from(str).length hoặc [...str].length, nhưng chúng cũng phân tách chuỗi ZWJ và trả về 7. Để đếm theo cụm tự vị (grapheme cluster), dùng API Intl.Segmenter.
Bạn cũng có thể tham khảo tổng hợp giới hạn ký tự SNS. Biết cách đếm của từng nền tảng giúp tránh rắc rối "vượt giới hạn ký tự" khi đăng nội dung nhiều emoji.
Nối đuôi emoji và đoán tên phim - Số ký tự trong trò chơi
Các trò chơi dùng emoji cũng có phát hiện thú vị từ góc độ số ký tự.
"Nối đuôi emoji" là trò chơi nối từ tiếng Nhật bằng tên emoji. 🍎 (táo) → 🦍 (khỉ đột) → 🍛 (ramen)... và tiếp tục. Luật đơn giản nhưng khá khó nếu không biết tên chính thức. Ví dụ tên chính thức của 🫥 là "Dotted Line Face". Tất cả khoảng 3.600 emoji đều có tên bản địa hóa trong CLDR (Common Locale Data Repository) của Unicode.
"Đoán tên phim từ emoji" cũng rất phổ biến. Ví dụ "🦁👑" là "Vua Sư Tử" (2 ký tự biểu đạt tiêu đề), "👻👻👻🔫" là "Ghostbusters" (4 ký tự cho tiêu đề), "🧙♂️💍🌋" là "Chúa Tể Những Chiếc Nhẫn" (3 ký tự cho tiêu đề). Tổ hợp emoji có thể coi là một dạng "ngôn ngữ siêu nén" truyền đạt ý nghĩa trong khi giảm mạnh số ký tự.
Lấy "số ký tự thực" của emoji trong lập trình
Đối với lập trình viên, đếm ký tự emoji là vấn đề đau đầu vì các ngôn ngữ và runtime trả về giá trị khác nhau.
| Ngôn ngữ / Môi trường | Phương thức | Kết quả cho "👨👩👧👦" | Đơn vị đếm |
|---|---|---|---|
| JavaScript | "👨👩👧👦".length | 11 | Đơn vị mã UTF-16 |
| JavaScript | [..."👨👩👧👦"].length | 7 | Điểm mã |
| Python 3 | len("👨👩👧👦") | 7 | Điểm mã |
| Swift | "👨👩👧👦".count | 1 | Cụm tự vị |
| Rust | "👨👩👧👦".len() | 25 | Byte (UTF-8) |
| Go | len("👨👩👧👦") | 25 | Byte (UTF-8) |
Chỉ Swift trả về "1" vì Swift sử dụng cụm tự vị (grapheme cluster) làm đơn vị ký tự. Đây là kết quả gần nhất với trực giác con người, nhưng chi phí xử lý nội bộ cao hơn. Để có kết quả tương tự trong JavaScript, dùng Intl.Segmenter.
Như đã giải thích trong kiến thức cơ bản về Unicode, định nghĩa "số ký tự" khác nhau tùy ngữ cảnh. Tổ hợp emoji làm nổi bật vấn đề này rõ ràng nhất. Giống như sự khác biệt trong cách đếm ký tự toàn chiều rộng và nửa chiều rộng, hãy nhớ rằng cách đếm emoji cũng khác nhau theo nền tảng và ngôn ngữ.
Tương lai của emoji - Khả năng tổ hợp vô hạn
Tính đến Unicode 16.0 (2024), tổng số emoji khoảng 3.790. Tuy nhiên khi tính cả tổ hợp chuỗi ZWJ và bộ điều chỉnh tông da, các biến thể có thể biểu đạt lên đến hàng chục nghìn.
Năm 2024, "bộ điều chỉnh hướng" được giới thiệu, cho phép thay đổi hướng emoji người sang trái hoặc phải. Thêm bộ điều chỉnh hướng cho 🏃 (người chạy) thành 🏃➡️ (người chạy sang phải). Đây cũng là yếu tố tăng số điểm mã.
Tổ hợp emoji đã nâng cao đáng kể sức biểu đạt của giao tiếp văn bản. Trong chat hàng ngày không cần quan tâm 1 emoji gồm bao nhiêu điểm mã. Nhưng khi đăng lên mạng xã hội có giới hạn ký tự, thiết kế trường ký tự cơ sở dữ liệu, hay xử lý chuỗi trong lập trình, khoảng cách giữa "số ký tự nhìn thấy" và "số ký tự nội bộ" có thể trở thành cạm bẫy bất ngờ.
Như cũng đề cập trong bài viết về số ký tự tin nhắn LINE, tin nhắn dùng nhiều emoji có dung lượng dữ liệu lớn hơn tin nhắn chỉ có văn bản. Lần tới khi chọn emoji, thử tưởng tượng xem bao nhiêu điểm mã đang ẩn sau 1 ký tự đó.
Nếu bạn quan tâm đến cơ chế emoji và Unicode, có thể tìm sách liên quan trên Amazon.