Files
skills/docs/localization/i18n/i18n-formatter-collator/src/helpers/helpers.md
2026-05-29 08:20:56 +01:00

3.3 KiB

Collator ergonomic helpers

(no submodules)

Purpose

The three ergonomic helpers (compareCaseInsensitive, compareNumericAware, sortStrings) pre-bind compareStrings and formatCollation with the most common option configurations so consumers don't have to remember which sensitivity value matches case-insensitive comparison or which boolean flag enables natural sort.

Features

  • compareCaseInsensitive(a, b, locale) — pre-binds sensitivity: "accent" (case-insensitive but accent-aware)
  • compareNumericAware(a, b, locale) — pre-binds numeric: true (natural sort: "file2" < "file10")
  • sortStrings(values, locale, options?) — alias for formatCollation with a more familiar name

Usage: Basic Example

import {
    compareCaseInsensitive,
    compareNumericAware,
    sortStrings,
} from "@suaveplan/i18n-formatter-collator";

compareCaseInsensitive("apple", "Apple", "en-GB"); // 0
compareNumericAware("file2", "file10", "en-GB"); // -1

sortStrings(["c", "a", "b"], "en-GB"); // ["a", "b", "c"]
sortStrings(["file10", "file2"], "en-GB", { numeric: true });
// ["file2", "file10"]

Usage: Advanced Example

import {
    compareCaseInsensitive,
    compareNumericAware,
    sortStrings,
} from "@suaveplan/i18n-formatter-collator";

// Build a case-insensitive search filter.
function findItems(needle: string, items: string[], locale: string) {
    return items.filter(
        (item) => compareCaseInsensitive(needle, item, locale) === 0
    );
}

// Sort a list of file names naturally.
const files = ["log10.txt", "log2.txt", "log1.txt"];
const sorted = sortStrings(files, "en-GB", { numeric: true });
// ["log1.txt", "log2.txt", "log10.txt"]

// Sort then group names case-insensitively.
function groupBy<T>(
    items: readonly T[],
    keyFn: (item: T) => string,
    locale: string
): Record<string, T[]> {
    const sortedItems = [...items].sort((x, y) =>
        compareCaseInsensitive(keyFn(x), keyFn(y), locale)
    );
    const out: Record<string, T[]> = {};
    for (const item of sortedItems) {
        const key = keyFn(item);
        const bucket = out[key] ?? [];
        bucket.push(item);
        out[key] = bucket;
    }
    return out;
}

API Reference

compareCaseInsensitive(a, b, locale): -1 | 0 | 1

Pre-binds sensitivity: "accent". Treats "a" and "A" as equal (case-insensitive) but distinguishes "a" from "á" (accent-sensitive). For full base-letter comparison (treating "a" and "á" equal as well), call compareStrings directly with sensitivity: "base".

compareNumericAware(a, b, locale): -1 | 0 | 1

Pre-binds numeric: true. Embedded numbers sort by their numeric value, not their lexicographic order: "file2" sorts before "file10" (lexicographic would put "file10" first).

sortStrings(values, locale, options?): string[]

Alias for formatCollation with a familiar name. Returns a NEW sorted array; the input is never mutated. All options forwarded.

Implementation Notes

  • Each helper is a one-line wrapper around compareStrings / formatCollation. The underlying per-(locale, options-hash) cache applies — calling compareCaseInsensitive twice with the same locale reuses one Intl.Collator.
  • The helpers are pure functions with no shared state.