data(emoji): every emoji, with its CLDR names in English, Korean, and Japanese

emoji.src was a seed of thirty emoji.  cldr2emoji now generates it from
Unicode's emoji-test.txt (Emoji 17.0) and CLDR 48.2.0's annotations: the
1914 fully-qualified emoji without their skin-tone variants, each with
its names and keywords in the three languages, so that a search finds
what fcitx5's emoji picker finds.  The data is under the Unicode License,
added to LICENSES.
This commit is contained in:
2026-08-17 01:07:24 +09:00
parent abff5ed122
commit 95dff0b82b
7 changed files with 17599 additions and 58 deletions

50
map/cldr2emoji Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env python3
"""Write emoji.src: every fully-qualified emoji of Unicode's emoji-test.txt
but the skin-tone variants, each with its CLDR names and keywords in the
languages given, as result-first TAB-separated rows for mkemoji."""
import json
import sys
from pathlib import Path
def emoji(path):
out = []
for line in path.open(encoding="utf-8"):
if "; fully-qualified" not in line:
continue
cps = [int(cp, 16) for cp in line.split(";")[0].split()]
if any(0x1F3FB <= cp <= 0x1F3FF for cp in cps):
continue
out.append("".join(map(chr, cps)))
return out
def annotations(path):
"""CLDR annotations.json, plain or derived: emoji -> names, keywords."""
root = json.load(path.open(encoding="utf-8"))
table = root[next(iter(root))]["annotations"]
return {e: a.get("tts", []) + a.get("default", []) for e, a in table.items()}
def main():
if len(sys.argv) < 3:
print(f"usage: {sys.argv[0]} emoji-test.txt annotations.json...",
file=sys.stderr)
return 2
tables = [annotations(Path(arg)) for arg in sys.argv[2:]]
print("# Result first, then its CLDR names and keywords; see map/README.")
for e in emoji(Path(sys.argv[1])):
aliases = []
for table in tables:
for alias in table.get(e.replace("", ""), table.get(e, [])):
alias = alias.strip()
if alias and alias not in aliases:
aliases.append(alias)
if aliases:
print(e + "\t" + "\t".join(aliases))
return 0
if __name__ == "__main__":
sys.exit(main())