mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-12 08:52:32 +00:00
Plural rules are looked up by language alone: CLDR's parent of sr-Latn and zh-Hant is the root, whose only category is other, so sr-latn rows were rejected. The baked data covers every CLDR locale (10 KB): plural rules for he, ro, nb, ca, sk, th, ms and the rest, and decimal symbols for nb-NO, sk-SK, bn-BD, ar-MA and English in Europe. Format applies a Region's separators only where the system set them, and an empty grouping separator writes none. trn_plain writes counts in 0-9 without grouping, for documents and file names. reset_format goes back to the system region. trn_decimal and Format write infinities and NaN as CLDR does and take the other form. Tests that don't set a format use en-US, not the machine's region. The ICU4X crates are pinned to ~2.3, the minor version the data is for.
71 lines
2.9 KiB
Python
71 lines
2.9 KiB
Python
"""Writes locales.rs from CLDR's JSON release: the languages with plural rules and every locale's
|
|
percent affixes.
|
|
|
|
Usage: locales.py <cldr-json-full.zip> <cldr version>
|
|
"""
|
|
|
|
import json
|
|
import re
|
|
import sys
|
|
import zipfile
|
|
|
|
|
|
def rust(s):
|
|
return '"' + "".join(c if " " <= c <= "~" and c not in '"\\' else f"\\u{{{ord(c):x}}}" for c in s) + '"'
|
|
|
|
|
|
def affixes(numbers, numsys):
|
|
pattern = numbers[f"percentFormats-numberSystem-{numsys}"]["standard"].split(";")[0].replace("'", "")
|
|
sign = numbers[f"symbols-numberSystem-{numsys}"]["percentSign"]
|
|
number = re.search(r"[#0,.]+", pattern)
|
|
return pattern[: number.start()].replace("%", sign), pattern[number.end() :].replace("%", sign)
|
|
|
|
|
|
def main():
|
|
path, version = sys.argv[1], sys.argv[2]
|
|
found = {}
|
|
with zipfile.ZipFile(path) as z:
|
|
plurals = json.loads(z.read("cldr-core/supplemental/plurals.json"))["supplemental"]["plurals-type-cardinal"]
|
|
languages = sorted(l for l in plurals if l != "root" and "-" not in l)
|
|
for name in z.namelist():
|
|
m = re.fullmatch(r"cldr-numbers-full/main/([^/]+)/numbers\.json", name)
|
|
if not m or m.group(1) == "root":
|
|
continue
|
|
locale = m.group(1)
|
|
numbers = json.loads(z.read(name))["main"][locale]["numbers"]
|
|
found[(locale, True)] = affixes(numbers, "latn")
|
|
default = numbers["defaultNumberingSystem"]
|
|
if default != "latn":
|
|
found[(locale, False)] = affixes(numbers, default)
|
|
|
|
# Kept only where the lookup by dropping trailing subtags would find something else.
|
|
kept = {}
|
|
for (locale, latin), value in sorted(found.items(), key=lambda e: (e[0][0].count("-"), e[0])):
|
|
parts = locale.split("-")
|
|
inherited = ("", "%")
|
|
for n in range(len(parts) - 1, 0, -1):
|
|
if ("-".join(parts[:n]), latin) in kept:
|
|
inherited = kept[("-".join(parts[:n]), latin)]
|
|
break
|
|
if value != inherited:
|
|
kept[(locale, latin)] = value
|
|
|
|
print(f"// @generated by generate.sh from Unicode CLDR {version} (Unicode License).")
|
|
print()
|
|
print("/// The languages CLDR has plural rules for; the baked data has them all.")
|
|
print("pub(crate) const PLURAL_LANGUAGES: &[&str] = &[")
|
|
for i in range(0, len(languages), 16):
|
|
print(" " + ", ".join(rust(l) for l in languages[i : i + 16]) + ",")
|
|
print("];")
|
|
print()
|
|
print("/// Percent signs around the number (CLDR's standard percent pattern and sign): locale, Latin")
|
|
print("/// digits or the locale's own, text before the number, text after it. A locale missing here")
|
|
print("/// takes its parent's by dropping trailing subtags, then `{n}%`.")
|
|
print("pub(crate) const PERCENT: &[(&str, bool, &str, &str)] = &[")
|
|
for (locale, latin), (before, after) in sorted(kept.items()):
|
|
print(f" ({rust(locale)}, {str(latin).lower()}, {rust(before)}, {rust(after)}),")
|
|
print("];")
|
|
|
|
|
|
main()
|