Broiler.Unicode.Cldr.LocaleData 0.1.0-preview.3

This is a prerelease version of Broiler.Unicode.Cldr.LocaleData.
dotnet add package Broiler.Unicode.Cldr.LocaleData --version 0.1.0-preview.3
                    
NuGet\Install-Package Broiler.Unicode.Cldr.LocaleData -Version 0.1.0-preview.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Broiler.Unicode.Cldr.LocaleData" Version="0.1.0-preview.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Broiler.Unicode.Cldr.LocaleData" Version="0.1.0-preview.3" />
                    
Directory.Packages.props
<PackageReference Include="Broiler.Unicode.Cldr.LocaleData" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Broiler.Unicode.Cldr.LocaleData --version 0.1.0-preview.3
                    
#r "nuget: Broiler.Unicode.Cldr.LocaleData, 0.1.0-preview.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Broiler.Unicode.Cldr.LocaleData@0.1.0-preview.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Broiler.Unicode.Cldr.LocaleData&version=0.1.0-preview.3&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Broiler.Unicode.Cldr.LocaleData&version=0.1.0-preview.3&prerelease
                    
Install as a Cake Tool

Broiler.Unicode

Unicode property, emoji string-property, and CLDR locale-data components used by Broiler.JS. This README focuses on the Broiler.Unicode.Emoji.StringProperties package.

Managed, allocation-light matching of Unicode RGI emoji string properties (UTS #51) for .NET, backed by a generated trie. No ICU, no native dependency, no runtime downloads, no giant regex.

Preview status: This is unstable, substantially AI-assisted first-preview software. Generated tables and their generators require human source and data-provenance review. Human-review approval is revision-scoped; consult HUMAN_REVIEW.md for the reviewed revision and conditions before describing the current checkout as approved.

  • Supported Unicode emoji version: 16.0
  • Target frameworks: net8.0, net10.0
  • Dependencies: none (pure managed C#)
using UnicodeEmoji.StringProperties;

EmojiStringProperties.IsRgiEmoji("๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ");   // true  (family ZWJ sequence)
EmojiStringProperties.IsBasicEmoji("โค๏ธ");         // true  (U+2764 U+FE0F)
EmojiStringProperties.IsBasicEmoji("โค");          // false (missing U+FE0F presentation selector)
EmojiStringProperties.IsEmojiZwjSequence("๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป"); // true  (woman technologist, medium skin tone)

Why a string property and not a code point property?

Emoji-ness is not a property of a single code point. The "woman technologist, medium skin tone" emoji ๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป is the sequence U+1F469 U+1F3FD U+200D U+1F4BB โ€” four scalar values, six UTF-16 chars. Whether something is an emoji depends on the whole sequence: the presence of U+FE0F, the zero-width joiners, regional-indicator pairs, tag characters, skin-tone modifiers, and so on.

RGI_Emoji (Recommended for General Interchange) is defined by UTS #51 as the union of several string properties:

Property Example Shape
Basic_Emoji ๐Ÿ˜€ โค๏ธ one emoji code point, optionally + U+FE0F
Emoji_Keycap_Sequence 1๏ธโƒฃ digit U+FE0F U+20E3
RGI_Emoji_Flag_Sequence ๐Ÿ‡ฉ๐Ÿ‡ช a pair of regional indicator symbols
RGI_Emoji_Tag_Sequence ๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ black flag + tag characters + U+E007F
RGI_Emoji_Modifier_Sequence ๐Ÿ‘‹๐Ÿฝ base emoji + skin-tone modifier
RGI_Emoji_ZWJ_Sequence ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ ๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ emoji joined with U+200D
RGI_Emoji = Basic_Emoji
          โˆช Emoji_Keycap_Sequence
          โˆช RGI_Emoji_Flag_Sequence
          โˆช RGI_Emoji_Tag_Sequence
          โˆช RGI_Emoji_Modifier_Sequence
          โˆช RGI_Emoji_ZWJ_Sequence

This library matches on Unicode scalar values, decoding surrogate pairs first, so it never assumes one UTF-16 char equals one character.

Installation

The repository ships three packages, each targeting net8.0 and net10.0:

Package Purpose
Broiler.Unicode.Properties Unicode character properties, scripts, categories, and case mappings
Broiler.Unicode.Emoji.StringProperties Unicode RGI emoji sequence matching
Broiler.Unicode.Cldr.LocaleData CLDR locale data for Intl implementations

Select prerelease packages while the libraries are in preview:

dotnet add package Broiler.Unicode.Emoji.StringProperties --prerelease

For maintainer instructions, see publishing previews.

Earlier GitHub previews used the package IDs UnicodeEmoji.StringProperties and UnicodeCldr.LocaleData. Update those PackageReference entries (and central PackageVersion entries, if used) to the new IDs above. C# namespaces remain UnicodeEmoji.StringProperties and UnicodeCldr.LocaleData.

API

All exact-match APIs require the entire input to be a single, fully-qualified emoji. They come in string and ReadOnlySpan<char> overloads.

// Exact whole-string predicates
bool  EmojiStringProperties.IsRgiEmoji(string value);
bool  EmojiStringProperties.IsRgiEmoji(ReadOnlySpan<char> value);
bool  EmojiStringProperties.IsBasicEmoji(/* string | ReadOnlySpan<char> */);
bool  EmojiStringProperties.IsEmojiZwjSequence(/* string | ReadOnlySpan<char> */);

// Full property set for a single sequence (None if not an exact RGI emoji)
EmojiSequenceProperties EmojiStringProperties.GetProperties(/* string | ReadOnlySpan<char> */);

// Test for a specific combination of properties
bool  EmojiStringProperties.HasProperties(ReadOnlySpan<char> value, EmojiSequenceProperties mask);

// Allocation-free enumeration of emoji embedded in text (greedy / leftmost-longest)
EmojiSequenceEnumerator EmojiStringProperties.EnumerateRgiEmoji(ReadOnlySpan<char> text);
EmojiSequenceEnumerator EmojiStringProperties.Enumerate(ReadOnlySpan<char> text, EmojiSequenceProperties filter);

// The Unicode emoji version the tables were generated from
string EmojiStringProperties.UnicodeEmojiVersion; // "16.0"

Enumeration without allocating strings

EnumerateRgiEmoji returns a ref struct enumerator that yields EmojiMatch values describing each emoji by index and length (in UTF-16 code units). No substrings are allocated โ€” slice the original text yourself if you need the characters.

ReadOnlySpan<char> text = "Hi ๐Ÿ‘‹ family ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ from ๐Ÿ‡ฉ๐Ÿ‡ช!";

foreach (EmojiMatch m in EmojiStringProperties.EnumerateRgiEmoji(text))
{
    ReadOnlySpan<char> emoji = text.Slice(m.Index, m.Length);
    Console.WriteLine($"{m.Index}..{m.End} -> {m.Properties}");
}

Classifying a single value

EmojiSequenceProperties p = EmojiStringProperties.GetProperties("๐Ÿ‡ฉ๐Ÿ‡ช");
// p == EmojiSequenceProperties.RgiEmojiFlagSequence
//   (and p has the RgiEmoji bits, since every sequence property is a subset of RGI_Emoji)

How it works

The official Unicode data files are treated as the source of truth and are committed under data/unicode/16.0/:

  • emoji-test.txt
  • emoji-sequences.txt
  • emoji-zwj-sequences.txt

A build-time generator parses those files, normalizes every entry into an array of Unicode scalar values, classifies it into one of the six properties above, and builds a flattened trie keyed on scalar values. The trie is emitted as compact, diff-friendly C# arrays (EmojiTrieData.g.cs) that are committed to source control. At runtime the library only walks those arrays โ€” it never parses data files, uses reflection, or emits code.

Matching uses leftmost-longest semantics so the longest valid emoji (e.g. the complete four-person family) wins over its shorter prefixes, and exact-match APIs require the entire input to terminate on a trie node, so partial sequences are never reported as RGI.

Updating to a new Unicode version

The DataTool downloads the official files and regenerates the lookup tables:

# Download data/unicode/<version>/ and regenerate src/.../Generated/EmojiTrieData.g.cs
dotnet run --project src/UnicodeEmoji.StringProperties.DataTool -- update 16.0

# Or as separate steps:
dotnet run --project src/UnicodeEmoji.StringProperties.DataTool -- download 16.0
dotnet run --project src/UnicodeEmoji.StringProperties.DataTool -- generate 16.0

Then bump UnicodeEmojiVersion in Directory.Build.props, review the diff of the generated file, run the tests, and commit. Data is fetched only by this tool โ€” never during a normal build or at runtime.

Benchmarks

benchmarks/ compares the generated trie against a naive HashSet<string> and a single large compiled Regex, for both exact matching and enumeration:

dotnet run -c Release --project benchmarks/UnicodeEmoji.StringProperties.Benchmarks -- --filter '*'

The trie matches in time proportional to the input length (independent of the ~3,800-entry data set), allocates nothing on the hot path, and avoids the large startup and memory cost of compiling a giant alternation regex.

Limitations

  • RGI only. This library implements the recommended-for-general-interchange set. It does not recognize valid-but-not-recommended emoji ZWJ sequences, arbitrary tag sequences, or every emoji-presentation code point in isolation.
  • Exact match means fully-qualified. Minimally-qualified / unqualified forms (those missing a required U+FE0F) are intentionally not reported as RGI by the exact-match APIs.
  • Not a grapheme segmenter. EnumerateRgiEmoji finds RGI emoji; it is not a general Unicode text-segmentation (UAX #29) implementation.
  • Emoji presentation is matching-only. The library reports properties of text; it does not render, normalize, or transform emoji.
  • Version-pinned. The data is generated for a single Unicode version (currently 16.0). Use the DataTool to move to another version.

Project layout

src/
  UnicodeEmoji.StringProperties/            # the NuGet library (net8.0; net10.0)
  UnicodeEmoji.StringProperties.Generator/  # parser + trie builder + source emitter
  UnicodeEmoji.StringProperties.DataTool/   # downloads data + drives the generator
tests/
  UnicodeEmoji.StringProperties.Tests/      # golden + data-driven xUnit tests
benchmarks/
  UnicodeEmoji.StringProperties.Benchmarks/ # trie vs HashSet vs Regex
data/
  unicode/16.0/                             # committed official Unicode data files

License

Broiler.Unicode source code is licensed under the Apache License 2.0. Unicode-provided data files and derived tables remain ยฉ Unicode, Inc. and subject to the Unicode Terms of Use; see THIRD_PARTY_NOTICES.md. The Apache license provides the software on an โ€œAS ISโ€ basis without warranties or conditions.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Broiler.Unicode.Cldr.LocaleData:

Package Downloads
Broiler.JavaScript.BuiltIns

Broiler.JS ECMAScript built-ins: Array, Map, Set, Promise, Proxy, RegExp, String, Symbol, typed arrays, and the rest of the standard library objects.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-preview.3 102 10/11/2026
0.1.0-preview.2 1,957 9/23/2026