Export ICU Unicode Properties to TOML Files with icuexportdata

icuexportdata dumps ICU's internal Unicode property tables to plain TOML files you can read, diff or feed into another build. The examples use ICU 74.2 from Ubuntu's icu-devtools package, and the whole job takes about ten minutes once you know where the output should land.

You need icuexportdata installed and write access to the destination. This is an ordinary, unprivileged workflow. Do not reach for sudo just because ICU lives under /usr: the program only reads ICU's installed data and writes new files where you point it.

1. Check the installed tool

Confirm the executable and the package version before you build a script around its output:

$ command -v icuexportdata
/usr/bin/icuexportdata
$ icuexportdata --version
icuexportdata version 74.2, ICU tool to dump data files for external consumers
$ dpkg-query -W -f='${Package} ${Version}\n' icu-devtools
icu-devtools 74.2-1ubuntu3.1

The exact Debian revision can differ from machine to machine. What matters is that the command reports ICU 74.2 and the package is icu-devtools. On a different installation, ask the built-in usage text instead of guessing:

$ icuexportdata --help
usage: icuexportdata -m mode [-options] [--all | properties...]
        dump Unicode property data to .toml files

The installed build has three modes: uprops for Unicode properties, ucase for casing data and norm for normalisation data. The mode is mandatory, every time.

2. Create a dedicated destination

Pick a new directory so exported files never mix with application data. This only touches the directory you name:

$ export ICU_EXPORT_DIR="$PWD/icu-export"
$ mkdir -p "$ICU_EXPORT_DIR"
$ test -w "$ICU_EXPORT_DIR" && echo 'destination is writable'
destination is writable

Swap $PWD/icu-export for an explicit path if a build expects a particular location. The program creates or truncates files under the names it exports, with no confirmation prompt.

Warning: if the directory already holds useful TOML files, stop and pick an empty directory or take a backup first. There is no rollback command in icuexportdata; recovery means restoring the old files from that backup or removing the separate export directory entirely.

3. Export one property

Start with a single property to prove the workflow before you scale it up. Pass the property name after the options, and use --destdir for the output directory:

$ icuexportdata --mode uprops --destdir "$ICU_EXPORT_DIR" Alphabetic
Writing to: /home/example/project/icu-export/Alphabetic.toml

The displayed path shows your own working directory. Check the file actually landed, then peek at its header:

$ test -s "$ICU_EXPORT_DIR/Alphabetic.toml" && echo 'export is non-empty'
export is non-empty
$ sed -n '1,12p' "$ICU_EXPORT_DIR/Alphabetic.toml"
# file name: Alphabetic
# machine-generated by: icuexportdata.cpp
...

The file holds a generated TOML representation of that property. Property names are interpreted by ICU, not the shell, so use one the installed ICU data actually recognises, such as Alphabetic. An arbitrary name is not a safe placeholder for a real export.

4. Export all Unicode properties

When a consumer needs the complete uprops set, add --all. Add --index too, to get a manifest of everything that gets written:

$ icuexportdata --mode uprops --all --index --destdir "$ICU_EXPORT_DIR"
Writing to: /home/example/project/icu-export/Alpha.toml
Writing to: /home/example/project/icu-export/AHex.toml
Writing to: /home/example/project/icu-export/Bidi_C.toml
...
$ test -s "$ICU_EXPORT_DIR/_index.toml" && echo 'index created'
index created
$ sed -n '1,10p' "$ICU_EXPORT_DIR/_index.toml"
# file name: _index
# machine-generated by: icuexportdata.cpp

index = [

--all produces a lot of files, including properties with abbreviated names and normalisation-related data. Treat the directory as one set: copying only a few files out of an all-property export can leave a consumer working from incomplete data. The index records file names, but it is no substitute for checking which files your application actually needs.

5. Choose the other data modes when needed

Reach for ucase or norm only when the downstream format specifically expects those data sets. A full run is cheap to test in its own directory:

$ ucase_dir="$PWD/icu-ucase"
$ mkdir -p "$ucase_dir"
$ icuexportdata --mode ucase --all --destdir "$ucase_dir"
Writing to: /home/example/project/icu-ucase/ucase.toml
$ test -s "$ucase_dir/ucase.toml" && echo 'casing data created'
casing data created

$ norm_dir="$PWD/icu-norm"
$ mkdir -p "$norm_dir"
$ icuexportdata --mode norm --all --destdir "$norm_dir"
Writing to: /home/example/project/icu-norm/compositions.toml
Writing to: /home/example/project/icu-norm/decompositionex.toml
...
$ find "$norm_dir" -maxdepth 1 -type f -name '*.toml' -printf '%f\n' | sort
compositions.toml
decompositionex.toml
nfd.toml
nfdex.toml
nfkd.toml
nfkdex.toml
uts46d.toml

Do not assume uprops --all, ucase --all and norm --all are interchangeable. They produce different files for different consumers. Keep each mode's output in its own place and write down which mode made which files.

6. Select trie size deliberately

For property data, --trie-type accepts small or fast; the default is small. Leave it alone unless the consumer explicitly asks for the other representation:

$ fast_dir="$PWD/icu-uprops-fast"
$ mkdir -p "$fast_dir"
$ icuexportdata --mode uprops --trie-type fast --destdir "$fast_dir" Alphabetic
Writing to: /home/example/project/icu-uprops-fast/Alphabetic.toml
$ test -s "$fast_dir/Alphabetic.toml" && echo 'fast trie export created'
fast trie export created

The trie choice is part of the generated data contract, not a cosmetic setting. Compare output against what your reader expects before you replace an existing export. If a mode or option gets rejected, read the local --help output rather than guessing: the program exits non-zero for an invalid mode such as bad.

7. Make a repeatable verification check

For a script or a build step, check the exit status and the files that matter, rather than trying to match every progress line. That also keeps host-specific absolute paths out of your comparisons:

$ icuexportdata --mode uprops --all --index --quiet --destdir "$ICU_EXPORT_DIR"
$ printf 'export status: %s\n' "$?"
export status: 0
$ test -s "$ICU_EXPORT_DIR/_index.toml" && test -s "$ICU_EXPORT_DIR/Alpha.toml"
$ echo 'required export files are present'
required export files are present

--quiet suppresses warnings and progress output; it does not turn a failed export into a successful one. Reach for --verbose when you are diagnosing a problem instead. --copyright asks for a copyright notice in generated files. Only commit generated output to source control once your project has actually decided how to handle ICU's data and licensing notices.

Done means