Skip to main content

Locale-Aware String Sorting API

REAL DATA

Sort and compare strings the way a locale actually orders them: German sorts ä with a, Swedish sorts it after z. Every option visibly changes the answer.

Authoritative reference data or standards computation

Base URL
/api/collation
Capabilities
4 routes
Last updated
July 29, 2026
Data source

GET /api/collation/sort

Returns the input order and the sorted order side by side, plus the collator's resolved options. The sort is stable, so equal-comparing entries keep their input order in both directions.

Live requestRuns against the public API
No key required
GET/api/collation/sort?items=b%2Ca%2Cz%2C%C3%A4&locale=de

Request parameters

Comma-separated strings to sort: at most 200 entries, at most 100 characters each and at most 8000 characters in total. Entries are trimmed, empty entries are dropped, and an entry cannot contain a comma.

Unicode BCP 47 locale identifier whose ordering rules to use. It is canonicalized first; a malformed tag returns 400 instead of falling back to English, and a tag this runtime has no collation data for still answers but reports 'hasCollationData': false plus a warning naming the locale that actually served it. Tags carrying a Unicode '-u-' extension are rejected — use the option parameters.

ECMA-402 comparison strength. base: a = á = A. accent: a ≠ á, a = A. case: a = á, a ≠ A. variant: everything counts (the default for sorting).

Compare digit runs as numbers (the '-u-kn' key), so 'item2' sorts before 'item10' instead of after it.

Which case wins when only case separates two strings (the '-u-kf' key). 'false' keeps the locale's own default.

Named CLDR collation to request through the '-u-co-' key, e.g. phonebk, pinyin or stroke. Values outside this runtime's Intl.supportedValuesOf('collation') return 400; a value the locale does not tailor is reported as a warning, and a 'search…' tailoring is answered with a warning that its order is not a display order.

Reverse the comparator. Equal-comparing entries still keep their input order.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/collation/sort?items=b%2Ca%2Cz%2C%C3%A4&locale=de"
const res = await fetch("https://randomapi.dev/api/collation/sort?items=b%2Ca%2Cz%2C%C3%A4&locale=de");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/collation/sort?items=b%2Ca%2Cz%2C%C3%A4&locale=de").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/collation/sort?items=b%2Ca%2Cz%2C%C3%A4&locale=de"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 7
items list required

Comma-separated strings to sort: at most 200 entries, at most 100 characters each and at most 8000 characters in total. Entries are trimmed, empty entries are dropped, and an entry cannot contain a comma.

example: items=b,a,z,ä
locale string

Unicode BCP 47 locale identifier whose ordering rules to use. It is canonicalized first; a malformed tag returns 400 instead of falling back to English, and a tag this runtime has no collation data for still answers but reports 'hasCollationData': false plus a warning naming the locale that actually served it. Tags carrying a Unicode '-u-' extension are rejected — use the option parameters.

default: en
allowed: 2 – 64
example: locale=de
sensitivity enum

ECMA-402 comparison strength. base: a = á = A. accent: a ≠ á, a = A. case: a = á, a ≠ A. variant: everything counts (the default for sorting).

default: variant
allowed: base | accent | case | variant
example: sensitivity=base
numeric boolean

Compare digit runs as numbers (the '-u-kn' key), so 'item2' sorts before 'item10' instead of after it.

default: false
example: numeric=true
caseFirst enum

Which case wins when only case separates two strings (the '-u-kf' key). 'false' keeps the locale's own default.

default: false
allowed: false | upper | lower
example: caseFirst=upper
collation string

Named CLDR collation to request through the '-u-co-' key, e.g. phonebk, pinyin or stroke. Values outside this runtime's Intl.supportedValuesOf('collation') return 400; a value the locale does not tailor is reported as a warning, and a 'search…' tailoring is answered with a warning that its order is not a display order.

allowed: 3 – 32
example: collation=phonebk
descending boolean

Reverse the comparator. Equal-comparing entries still keep their input order.

default: false
example: descending=true
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=locale,hasCollationData
exclude list

Return all fields except these (comma-separated).

example: exclude=movedCount
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 7
locale string

The requested locale in canonical BCP 47 form — what was asked for, before the runtime resolved it.

example: de

hasCollationData boolean

Whether this runtime has collation data for the requested locale (Intl.Collator.supportedLocalesOf). False means the ordering below is the fallback locale named in resolvedLocale, not the one you asked for — check it before trusting a locale-specific result, because ICU builds differ and an edge runtime can lack languages a Node build has.

example: true

resolvedLocale string

The locale Intl.Collator actually used, including any '-u-co-' keyword it kept.

example: de

resolvedOptions object

The collator's complete ECMA-402 resolvedOptions: locale, usage, sensitivity, ignorePunctuation, collation, numeric and caseFirst. Echoed so the answer stays auditable against the serving runtime's ICU/CLDR version. numeric and caseFirst are null on a runtime that does not implement the optional '-u-kn'/'-u-kf' keys.

example: {"locale":"de","usage":"sort","sensitivity":"variant","ignorePunctuation":false,"collation":"default","numeric":false,"caseFirst":"false"}

items string[]

The parsed input list, in the order supplied.

example: ["b","a","z","ä"]

sorted string[]

The same entries in this locale's collation order.

example: ["a","ä","b","z"]

movedCount integer

How many positions hold a different string than the input did; 0 means the input was already in this order.

example: 4

Documented examples

Build-generated requests and complete responses
5
German sorts ä with a
GET /api/collation/sort?items=b%2Ca%2Cz%2C%C3%A4&locale=de
{
  "data": {
    "locale": "de",
    "hasCollationData": true,
    "resolvedLocale": "de",
    "resolvedOptions": {
      "locale": "de",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "default",
      "numeric": false,
      "caseFirst": "false"
    },
    "items": [
      "b",
      "a",
      "z",
      "ä"
    ],
    "sorted": [
      "a",
      "ä",
      "b",
      "z"
    ],
    "movedCount": 4
  },
  "meta": {
    "endpoint": "collation",
    "route": "/sort",
    "params": {
      "items": [
        "b",
        "a",
        "z",
        "ä"
      ],
      "locale": "de",
      "sensitivity": "variant",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Swedish sorts ä after z
GET /api/collation/sort?items=b%2Ca%2Cz%2C%C3%A4&locale=sv
{
  "data": {
    "locale": "sv",
    "hasCollationData": true,
    "resolvedLocale": "sv",
    "resolvedOptions": {
      "locale": "sv",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "default",
      "numeric": false,
      "caseFirst": "false"
    },
    "items": [
      "b",
      "a",
      "z",
      "ä"
    ],
    "sorted": [
      "a",
      "b",
      "z",
      "ä"
    ],
    "movedCount": 2
  },
  "meta": {
    "endpoint": "collation",
    "route": "/sort",
    "params": {
      "items": [
        "b",
        "a",
        "z",
        "ä"
      ],
      "locale": "sv",
      "sensitivity": "variant",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Natural order for numbered items
GET /api/collation/sort?items=item10%2Citem2%2Citem1&numeric=true
{
  "data": {
    "locale": "en",
    "hasCollationData": true,
    "resolvedLocale": "en",
    "resolvedOptions": {
      "locale": "en",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "default",
      "numeric": true,
      "caseFirst": "false"
    },
    "items": [
      "item10",
      "item2",
      "item1"
    ],
    "sorted": [
      "item1",
      "item2",
      "item10"
    ],
    "movedCount": 2
  },
  "meta": {
    "endpoint": "collation",
    "route": "/sort",
    "params": {
      "items": [
        "item10",
        "item2",
        "item1"
      ],
      "locale": "en",
      "sensitivity": "variant",
      "numeric": true,
      "caseFirst": "false",
      "descending": false
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Uppercase before lowercase
GET /api/collation/sort?items=a%2CA%2Cb%2CB&caseFirst=upper
{
  "data": {
    "locale": "en",
    "hasCollationData": true,
    "resolvedLocale": "en",
    "resolvedOptions": {
      "locale": "en",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "default",
      "numeric": false,
      "caseFirst": "upper"
    },
    "items": [
      "a",
      "A",
      "b",
      "B"
    ],
    "sorted": [
      "A",
      "a",
      "B",
      "b"
    ],
    "movedCount": 4
  },
  "meta": {
    "endpoint": "collation",
    "route": "/sort",
    "params": {
      "items": [
        "a",
        "A",
        "b",
        "B"
      ],
      "locale": "en",
      "sensitivity": "variant",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
German phonebook collation sorts Ä as AE
GET /api/collation/sort?items=Alter%2CApfel%2C%C3%84pfel&locale=de&collation=phonebk
{
  "data": {
    "locale": "de",
    "hasCollationData": true,
    "resolvedLocale": "de-u-co-phonebk",
    "resolvedOptions": {
      "locale": "de-u-co-phonebk",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "phonebk",
      "numeric": false,
      "caseFirst": "false"
    },
    "items": [
      "Alter",
      "Apfel",
      "Äpfel"
    ],
    "sorted": [
      "Äpfel",
      "Alter",
      "Apfel"
    ],
    "movedCount": 3
  },
  "meta": {
    "endpoint": "collation",
    "route": "/sort",
    "params": {
      "items": [
        "Alter",
        "Apfel",
        "Äpfel"
      ],
      "locale": "de",
      "sensitivity": "variant",
      "numeric": false,
      "caseFirst": "false",
      "collation": "phonebk",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

GET /api/collation/compare

Live requestRuns against the public API
No key required
GET/api/collation/compare?left=a&right=%C3%A1

Request parameters

First string, compared exactly as sent (leading and trailing spaces included).

Second string, compared exactly as sent (leading and trailing spaces included).

Unicode BCP 47 locale identifier whose ordering rules to use. It is canonicalized first; a malformed tag returns 400 instead of falling back to English, and a tag this runtime has no collation data for still answers but reports 'hasCollationData': false plus a warning naming the locale that actually served it. Tags carrying a Unicode '-u-' extension are rejected — use the option parameters.

ECMA-402 comparison strength. base: a = á = A. accent: a ≠ á, a = A. case: a = á, a ≠ A. variant: everything counts (the default for sorting).

Compare digit runs as numbers (the '-u-kn' key), so 'item2' sorts before 'item10' instead of after it.

Which case wins when only case separates two strings (the '-u-kf' key). 'false' keeps the locale's own default.

Named CLDR collation to request through the '-u-co-' key, e.g. phonebk, pinyin or stroke. Values outside this runtime's Intl.supportedValuesOf('collation') return 400; a value the locale does not tailor is reported as a warning, and a 'search…' tailoring is answered with a warning that its order is not a display order.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/collation/compare?left=a&right=%C3%A1"
const res = await fetch("https://randomapi.dev/api/collation/compare?left=a&right=%C3%A1");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/collation/compare?left=a&right=%C3%A1").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/collation/compare?left=a&right=%C3%A1"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 7
left string required

First string, compared exactly as sent (leading and trailing spaces included).

allowed: 1 – 200
example: left=a
right string required

Second string, compared exactly as sent (leading and trailing spaces included).

allowed: 1 – 200
example: right=A
locale string

Unicode BCP 47 locale identifier whose ordering rules to use. It is canonicalized first; a malformed tag returns 400 instead of falling back to English, and a tag this runtime has no collation data for still answers but reports 'hasCollationData': false plus a warning naming the locale that actually served it. Tags carrying a Unicode '-u-' extension are rejected — use the option parameters.

default: en
allowed: 2 – 64
example: locale=de
sensitivity enum

ECMA-402 comparison strength. base: a = á = A. accent: a ≠ á, a = A. case: a = á, a ≠ A. variant: everything counts (the default for sorting).

default: variant
allowed: base | accent | case | variant
example: sensitivity=base
numeric boolean

Compare digit runs as numbers (the '-u-kn' key), so 'item2' sorts before 'item10' instead of after it.

default: false
example: numeric=true
caseFirst enum

Which case wins when only case separates two strings (the '-u-kf' key). 'false' keeps the locale's own default.

default: false
allowed: false | upper | lower
example: caseFirst=upper
collation string

Named CLDR collation to request through the '-u-co-' key, e.g. phonebk, pinyin or stroke. Values outside this runtime's Intl.supportedValuesOf('collation') return 400; a value the locale does not tailor is reported as a warning, and a 'search…' tailoring is answered with a warning that its order is not a display order.

allowed: 3 – 32
example: collation=phonebk
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=left,right
exclude list

Return all fields except these (comma-separated).

example: exclude=decidedAt
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 9
left string

The left operand as supplied.

example: a

right string

The right operand as supplied.

example: á

result integer (-1 | 0 | 1)

-1 when left sorts first, 0 when the two are equivalent at the requested sensitivity, 1 when right sorts first.

example: -1

relation string (before | equivalent | after)

The same answer in words: where left falls relative to right.

example: before

locale string

The requested locale in canonical BCP 47 form — what was asked for, before the runtime resolved it.

example: en

hasCollationData boolean

Whether this runtime has collation data for the requested locale (Intl.Collator.supportedLocalesOf). False means the ordering below is the fallback locale named in resolvedLocale, not the one you asked for — check it before trusting a locale-specific result, because ICU builds differ and an edge runtime can lack languages a Node build has.

example: true

resolvedLocale string

The locale Intl.Collator actually used, including any '-u-co-' keyword it kept.

example: en

resolvedOptions object

The collator's complete ECMA-402 resolvedOptions: locale, usage, sensitivity, ignorePunctuation, collation, numeric and caseFirst. Echoed so the answer stays auditable against the serving runtime's ICU/CLDR version. numeric and caseFirst are null on a runtime that does not implement the optional '-u-kn'/'-u-kf' keys.

example: {"locale":"en","usage":"sort","sensitivity":"variant","ignorePunctuation":false,"collation":"default","numeric":false,"caseFirst":"false"}

decidedAt string (base | accent | case | variant | equivalent-at-all-levels)

Coarsest sensitivity at which the strings still differ, found by re-running the comparison at base, accent, case then variant with the other options unchanged. Independent of the requested sensitivity.

example: accent

Documented examples

Build-generated requests and complete responses
7
Accents decide it: a vs á
GET /api/collation/compare?left=a&right=%C3%A1
{
  "data": {
    "left": "a",
    "right": "á",
    "result": -1,
    "relation": "before",
    "locale": "en",
    "hasCollationData": true,
    "resolvedLocale": "en",
    "resolvedOptions": {
      "locale": "en",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "default",
      "numeric": false,
      "caseFirst": "false"
    },
    "decidedAt": "accent"
  },
  "meta": {
    "endpoint": "collation",
    "route": "/compare",
    "params": {
      "left": "a",
      "right": "á",
      "locale": "en",
      "sensitivity": "variant",
      "numeric": false,
      "caseFirst": "false"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Case decides it: a vs A
GET /api/collation/compare?left=a&right=A
{
  "data": {
    "left": "a",
    "right": "A",
    "result": -1,
    "relation": "before",
    "locale": "en",
    "hasCollationData": true,
    "resolvedLocale": "en",
    "resolvedOptions": {
      "locale": "en",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "default",
      "numeric": false,
      "caseFirst": "false"
    },
    "decidedAt": "case"
  },
  "meta": {
    "endpoint": "collation",
    "route": "/compare",
    "params": {
      "left": "a",
      "right": "A",
      "locale": "en",
      "sensitivity": "variant",
      "numeric": false,
      "caseFirst": "false"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Precomposed é equals decomposed é
GET /api/collation/compare?left=%C3%A9&right=e%CC%81
{
  "data": {
    "left": "é",
    "right": "é",
    "result": 0,
    "relation": "equivalent",
    "locale": "en",
    "hasCollationData": true,
    "resolvedLocale": "en",
    "resolvedOptions": {
      "locale": "en",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "default",
      "numeric": false,
      "caseFirst": "false"
    },
    "decidedAt": "equivalent-at-all-levels"
  },
  "meta": {
    "endpoint": "collation",
    "route": "/compare",
    "params": {
      "left": "é",
      "right": "é",
      "locale": "en",
      "sensitivity": "variant",
      "numeric": false,
      "caseFirst": "false"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Swedish puts ä after z
GET /api/collation/compare?left=%C3%A4&right=z&locale=sv
{
  "data": {
    "left": "ä",
    "right": "z",
    "result": 1,
    "relation": "after",
    "locale": "sv",
    "hasCollationData": true,
    "resolvedLocale": "sv",
    "resolvedOptions": {
      "locale": "sv",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "default",
      "numeric": false,
      "caseFirst": "false"
    },
    "decidedAt": "base"
  },
  "meta": {
    "endpoint": "collation",
    "route": "/compare",
    "params": {
      "left": "ä",
      "right": "z",
      "locale": "sv",
      "sensitivity": "variant",
      "numeric": false,
      "caseFirst": "false"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Numeric collation compares digit runs
GET /api/collation/compare?left=item2&right=item10&numeric=true
{
  "data": {
    "left": "item2",
    "right": "item10",
    "result": -1,
    "relation": "before",
    "locale": "en",
    "hasCollationData": true,
    "resolvedLocale": "en",
    "resolvedOptions": {
      "locale": "en",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "default",
      "numeric": true,
      "caseFirst": "false"
    },
    "decidedAt": "base"
  },
  "meta": {
    "endpoint": "collation",
    "route": "/compare",
    "params": {
      "left": "item2",
      "right": "item10",
      "locale": "en",
      "sensitivity": "variant",
      "numeric": true,
      "caseFirst": "false"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Uppercase first flips the a/A verdict
GET /api/collation/compare?left=a&right=A&caseFirst=upper
{
  "data": {
    "left": "a",
    "right": "A",
    "result": 1,
    "relation": "after",
    "locale": "en",
    "hasCollationData": true,
    "resolvedLocale": "en",
    "resolvedOptions": {
      "locale": "en",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "default",
      "numeric": false,
      "caseFirst": "upper"
    },
    "decidedAt": "case"
  },
  "meta": {
    "endpoint": "collation",
    "route": "/compare",
    "params": {
      "left": "a",
      "right": "A",
      "locale": "en",
      "sensitivity": "variant",
      "numeric": false,
      "caseFirst": "upper"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
German phonebook order puts Äpfel before Alter
GET /api/collation/compare?left=%C3%84pfel&right=Alter&locale=de&collation=phonebk
{
  "data": {
    "left": "Äpfel",
    "right": "Alter",
    "result": -1,
    "relation": "before",
    "locale": "de",
    "hasCollationData": true,
    "resolvedLocale": "de-u-co-phonebk",
    "resolvedOptions": {
      "locale": "de-u-co-phonebk",
      "usage": "sort",
      "sensitivity": "variant",
      "ignorePunctuation": false,
      "collation": "phonebk",
      "numeric": false,
      "caseFirst": "false"
    },
    "decidedAt": "base"
  },
  "meta": {
    "endpoint": "collation",
    "route": "/compare",
    "params": {
      "left": "Äpfel",
      "right": "Alter",
      "locale": "de",
      "sensitivity": "variant",
      "numeric": false,
      "caseFirst": "false",
      "collation": "phonebk"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

GET /api/collation/locales

One row per tag you send, in the order you sent them. ECMA-402 leaves Intl.Collator's locale list implementation-defined, and reduced-ICU builds genuinely lack whole languages, so this asks the serving runtime directly with Intl.Collator.supportedLocalesOf instead of consulting a pinned table. A tag with no data reports resolvedLocale and defaultCollation as null, because what it would fall back to is the runtime's own default locale rather than anything derived from your tag.

Live requestRuns against the public API
No key required
GET/api/collation/locales?locales=de%2Csv%2Cja%2Czz

Request parameters

Comma-separated Unicode BCP 47 locale identifiers to check — at most 50. Each is canonicalized first (so 'iw' is checked as 'he'), and a malformed tag or one carrying a '-u-' extension returns 400 naming the offending entry.

Advanced response options6 options

Limit the number of returned records (1–100). Defaults to all matches.

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Response format: json envelope, ndjson (one record per line) or csv.

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/collation/locales?locales=de%2Csv%2Cja%2Czz"
const res = await fetch("https://randomapi.dev/api/collation/locales?locales=de%2Csv%2Cja%2Czz");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/collation/locales?locales=de%2Csv%2Cja%2Czz").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/collation/locales?locales=de%2Csv%2Cja%2Czz"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 1
locales list required

Comma-separated Unicode BCP 47 locale identifiers to check — at most 50. Each is canonicalized first (so 'iw' is checked as 'he'), and a malformed tag or one carrying a '-u-' extension returns 400 naming the offending entry.

example: locales=de,sv,ja,zz
Universal parameters Shared response and formatting options 6
count int

Limit the number of returned records (1–100). Defaults to all matches.

default: all matches
allowed: 1 – 100
example: count=3
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=requested,locale
exclude list

Return all fields except these (comma-separated).

example: exclude=defaultCollation
format enum

Response format: json envelope, ndjson (one record per line) or csv.

default: json
allowed: json | ndjson | csv
example: format=csv
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 5
requested string

The tag exactly as you sent it (trimmed), so a row maps back to your input list even when canonicalization renames it.

example: de

locale string

The same tag in canonical Unicode BCP 47 form.

example: de

hasCollationData boolean

Whether Intl.Collator.supportedLocalesOf reports collation data for this tag on the runtime answering the request. False means /sort and /compare will answer this tag with the runtime's default ordering and warn about it.

example: true

resolvedLocale string nullable

The locale Intl.Collator resolves this tag to — usually the tag itself, sometimes a parent when the runtime has no data for the exact tag ('en-GB' typically resolves to 'en', while 'fr-CA' keeps its own backwards-accent tailoring). Always the same language as 'locale'. Null when the runtime has no data for the tag.

example: de

defaultCollation string nullable

resolvedOptions().collation with no '-u-co-' keyword: the ordering you get when no collation is requested. Reported verbatim, so a runtime that names a locale's standard ordering after its CLDR tailoring (for example 'pinyin' for 'zh') shows that name rather than 'default'. Null when the runtime has no data for the tag.

example: default

Documented examples

Build-generated requests and complete responses
3
Four tags at once, one of them unknown
GET /api/collation/locales?locales=de%2Csv%2Cja%2Czz
{
  "data": [
    {
      "requested": "de",
      "locale": "de",
      "hasCollationData": true,
      "resolvedLocale": "de",
      "defaultCollation": "default"
    },
    {
      "requested": "sv",
      "locale": "sv",
      "hasCollationData": true,
      "resolvedLocale": "sv",
      "defaultCollation": "default"
    },
    {
      "requested": "ja",
      "locale": "ja",
      "hasCollationData": true,
      "resolvedLocale": "ja",
      "defaultCollation": "default"
    },
    {
      "requested": "zz",
      "locale": "zz",
      "hasCollationData": false,
      "resolvedLocale": null,
      "defaultCollation": null
    }
  ],
  "meta": {
    "endpoint": "collation",
    "route": "/locales",
    "count": 4,
    "params": {
      "locales": [
        "de",
        "sv",
        "ja",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Check the locales of a European release
GET /api/collation/locales?locales=en%2Cde%2Cfr%2Ces%2Cit%2Cnl
{
  "data": [
    {
      "requested": "en",
      "locale": "en",
      "hasCollationData": true,
      "resolvedLocale": "en",
      "defaultCollation": "default"
    },
    {
      "requested": "de",
      "locale": "de",
      "hasCollationData": true,
      "resolvedLocale": "de",
      "defaultCollation": "default"
    },
    {
      "requested": "fr",
      "locale": "fr",
      "hasCollationData": true,
      "resolvedLocale": "fr",
      "defaultCollation": "default"
    },
    {
      "requested": "es",
      "locale": "es",
      "hasCollationData": true,
      "resolvedLocale": "es",
      "defaultCollation": "default"
    },
    {
      "requested": "it",
      "locale": "it",
      "hasCollationData": true,
      "resolvedLocale": "it",
      "defaultCollation": "default"
    },
    {
      "requested": "nl",
      "locale": "nl",
    …
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Legacy tags are canonicalized before the check
GET /api/collation/locales?locales=iw%2Cin%2Ctl
{
  "data": [
    {
      "requested": "iw",
      "locale": "he",
      "hasCollationData": true,
      "resolvedLocale": "he",
      "defaultCollation": "default"
    },
    {
      "requested": "in",
      "locale": "id",
      "hasCollationData": true,
      "resolvedLocale": "id",
      "defaultCollation": "default"
    },
    {
      "requested": "tl",
      "locale": "fil",
      "hasCollationData": true,
      "resolvedLocale": "fil",
      "defaultCollation": "default"
    }
  ],
  "meta": {
    "endpoint": "collation",
    "route": "/locales",
    "count": 3,
    "params": {
      "locales": [
        "iw",
        "in",
        "tl"
      ]
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

GET /api/collation/collations

The bare route lists every identifier Intl.supportedValuesOf('collation') reports. ECMA-402 leaves that set implementation-defined, so it varies between JavaScript runtimes and ICU versions. Add 'locale' to see which of them that locale actually tailors.

Live requestRuns against the public API
No key required
GET/api/collation/collations?locale=de&search=phonebk

Request parameters

Optional Unicode BCP 47 locale identifier, validated exactly as on the other routes (malformed tags 400; '-u-' extensions rejected). When given, every row reports whether that locale tailors the collation, what the runtime resolved, and the locale's default collation; when omitted those fields are null rather than guessed.

Case-insensitive substring filter over the collation identifiers. No match returns an empty list plus a warning listing what this runtime does support.

Advanced response options6 options

Limit the number of returned records (1–100). Defaults to all matches.

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Response format: json envelope, ndjson (one record per line) or csv.

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/collation/collations?locale=de&search=phonebk"
const res = await fetch("https://randomapi.dev/api/collation/collations?locale=de&search=phonebk");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/collation/collations?locale=de&search=phonebk").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/collation/collations?locale=de&search=phonebk"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 2
locale string

Optional Unicode BCP 47 locale identifier, validated exactly as on the other routes (malformed tags 400; '-u-' extensions rejected). When given, every row reports whether that locale tailors the collation, what the runtime resolved, and the locale's default collation; when omitted those fields are null rather than guessed.

allowed: 2 – 64
example: locale=de
search string

Case-insensitive substring filter over the collation identifiers. No match returns an empty list plus a warning listing what this runtime does support.

allowed: 1 – 32
example: search=phonebk
Universal parameters Shared response and formatting options 6
count int

Limit the number of returned records (1–100). Defaults to all matches.

default: all matches
allowed: 1 – 100
example: count=3
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=collation,supportedForLocale
exclude list

Return all fields except these (comma-separated).

example: exclude=resolvedOptions
format enum

Response format: json envelope, ndjson (one record per line) or csv.

default: json
allowed: json | ndjson | csv
example: format=csv
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 6
collation string

Collation identifier, usable as the 'collation' parameter or a '-u-co-' keyword.

example: phonebk

supportedForLocale boolean nullable

True when the runtime kept the '-u-co-' keyword in the resolved locale, which ECMA-402 does only when that locale's collation list contains this identifier. Null when no locale was given.

example: true

resolvedCollation string nullable

resolvedOptions().collation for this locale plus this collation. To detect a dropped keyword, compare it with localeDefaultCollation — equal values mean the requested collation was not applied; a runtime may report a locale's standard ordering by its CLDR name ('pinyin' for 'zh') rather than as 'default'. Null when no locale was given.

example: phonebk

resolvedLocale string nullable

The locale the runtime resolved for this collation. Null when no locale was given.

example: de-u-co-phonebk

localeDefaultCollation string nullable

resolvedOptions().collation for the locale with no '-u-co-' keyword — the ordering you get when no collation is requested. Runtimes report this either as 'default' or as the underlying CLDR tailoring's name, so it is echoed verbatim rather than normalized. Null when no locale was given.

example: default

resolvedOptions object nullable

The complete ECMA-402 resolvedOptions for this locale plus this collation. Null when no locale was given.

example: {"locale":"de-u-co-phonebk","usage":"sort","sensitivity":"variant","ignorePunctuation":false,"collation":"phonebk","numeric":false,"caseFirst":"false"}

Documented examples

Build-generated requests and complete responses
3
German tailors the phonebook collation
GET /api/collation/collations?locale=de&search=phonebk
{
  "data": [
    {
      "collation": "phonebk",
      "supportedForLocale": true,
      "resolvedCollation": "phonebk",
      "resolvedLocale": "de-u-co-phonebk",
      "localeDefaultCollation": "default",
      "resolvedOptions": {
        "locale": "de-u-co-phonebk",
        "usage": "sort",
        "sensitivity": "variant",
        "ignorePunctuation": false,
        "collation": "phonebk",
        "numeric": false,
        "caseFirst": "false"
      }
    }
  ],
  "meta": {
    "endpoint": "collation",
    "route": "/collations",
    "count": 1,
    "params": {
      "locale": "de",
      "search": "phonebk"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
English has no phonebook tailoring
GET /api/collation/collations?locale=en&search=phonebk
{
  "data": [
    {
      "collation": "phonebk",
      "supportedForLocale": false,
      "resolvedCollation": "default",
      "resolvedLocale": "en",
      "localeDefaultCollation": "default",
      "resolvedOptions": {
        "locale": "en",
        "usage": "sort",
        "sensitivity": "variant",
        "ignorePunctuation": false,
        "collation": "default",
        "numeric": false,
        "caseFirst": "false"
      }
    }
  ],
  "meta": {
    "endpoint": "collation",
    "route": "/collations",
    "count": 1,
    "params": {
      "locale": "en",
      "search": "phonebk"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Spanish keeps a traditional collation
GET /api/collation/collations?locale=es&search=trad
{
  "data": [
    {
      "collation": "trad",
      "supportedForLocale": true,
      "resolvedCollation": "trad",
      "resolvedLocale": "es-u-co-trad",
      "localeDefaultCollation": "default",
      "resolvedOptions": {
        "locale": "es-u-co-trad",
        "usage": "sort",
        "sensitivity": "variant",
        "ignorePunctuation": false,
        "collation": "trad",
        "numeric": false,
        "caseFirst": "false"
      }
    }
  ],
  "meta": {
    "endpoint": "collation",
    "route": "/collations",
    "count": 1,
    "params": {
      "locale": "es",
      "search": "trad"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

About this API

Coverage & behavior

Sorting and comparison through the runtime's standards-based Intl.Collator — the engine behind String.prototype.localeCompare — so strings order by a language's real alphabet instead of UTF-16 code-unit order. A plain array.sort() puts ä (U+00E4) after z (U+007A) in every language; here German orders ä with a, Swedish orders it after z, and Spanish keeps ñ between n and o.

Every documented option demonstrably changes the output:

  • sensitivity picks the comparison strength: base (a = á = A), accent (a ≠ á, a = A), case (a = á, a ≠ A) or variant (everything, and the default for sorting).
  • numeric=true turns on numeric collation, so item2 sorts before item10.
  • caseFirst=upper|lower decides which case wins when only case separates two strings.
  • collation requests a named CLDR tailoring through the -u-co- key: phonebk sorts German ä as ae, stroke orders Han characters by stroke count.
  • descending flips the comparator. Ties keep their input order in both directions, because the underlying sort is stable.

/compare additionally reports decidedAt — the coarsest level at which the two strings still differ. The comparison is re-run at base, then accent, then case, then variant with your other options unchanged, and the first level returning a non-zero result is named. a vs á is decided at accent and a vs A at case. equivalent-at-all-levels means the pair differs at no level: canonically equivalent strings such as NFC é (U+00E9) and NFD é (U+0065 U+0301), but also anything the locale's tailoring folds together at tertiary strength — hiragana and katakana under the ja tailoring (they are decided at variant in en), or a-b and ab in th, whose locale data defaults ignorePunctuation to true. resolvedOptions echoes that default so you can see it.

/locales answers the question you have to settle before trusting any of the above: does the runtime serving you actually have collation data for your tags?

Scope and limits

  • Locale coverage is neither universal nor the same everywhere. ECMA-402 leaves [[AvailableLocales]] implementation-defined, and a reduced-ICU build — which is what edge runtimes commonly ship — can lack whole languages: Icelandic, Welsh, Irish, Armenian, Georgian, Albanian, Zulu and Mongolian are the kind of tags that come back with no collation data at all on a lean build while a full Node build handles every one of them. On such a build that is a large minority of common language tags, not an exotic edge case. Such a request still answers, and never pretends: hasCollationData is false, resolvedLocale names the locale that really served it, and a warning spells it out. Check your own tags with /locales — it reports what the runtime behind this API has, not a list we pinned. (The sibling plural-rules endpoint returns 400 for an unsupported locale instead. The difference is deliberate: a plural category from the wrong language is indistinguishable from a right one, whereas here the fallback is visible in the payload — and reproducing exactly what localeCompare does on a given runtime is the point of this endpoint.)
  • Answers come from the serving runtime's ICU/CLDR data, not from a table this API pins, and ECMA-402 explicitly leaves both the collation list and the locale data implementation-defined. A future ICU or CLDR release can therefore change an ordering, so every collator this endpoint builds echoes its full resolvedOptions back to you, and /collations reports exactly the identifier set this runtime supports rather than a curated list.
  • This is not database collation. PostgreSQL orders by the collation its database or column was created with (usually the operating system's LC_COLLATE, or an ICU locale), and MySQL by its own utf8mb4_* collations. The same list can come back in a different order from your database than from JavaScript. Diagnosing that mismatch is exactly what this endpoint is for — but it cannot tell you what your database will do.
  • We do not implement the Unicode Collation Algorithm ourselves and offer no tailoring beyond what the runtime exposes: no custom rules, and the ECMA-402 usage option is always sort (never search-usage matching). A runtime's collation list can still contain a search tailoring such as searchjl (CLDR: "Special collation type for Korean initial consonant search"); it is accepted, because it is a real collation this runtime supports, but the response warns that ECMA-402 does not guarantee any particular order for it.
  • An invalid locale tag returns 400 with the runtime's own reason. The grammar enforced is UTS #35's unicode_locale_id, which is what Intl.getCanonicalLocales accepts and is narrower than RFC 5646 — root, for instance, is a legal BCP 47 tag and still rejected here.
  • items is a comma-separated list, so an entry cannot itself contain a comma, and each entry is trimmed of surrounding whitespace. Up to 200 entries, up to 100 characters each and up to 8 000 characters in total. /compare keeps left and right exactly as sent, including leading and trailing spaces, and accepts up to 200 characters each.

Use it for

  • Reproduce an ORDER BY mismatch between JavaScript and a database in a bug report
  • Assert in CI that a name list renders in German, Swedish or Spanish alphabetical order
  • Decide whether numbered labels need numeric collation before shipping a sorted UI
  • Show a reviewer which collation level made two strings compare as equal
  • Check which of an app's shipped locales the serving runtime has real collation data for

Frequently asked questions

Why does JavaScript sort ä after z?

Array.prototype.sort compares UTF-16 code units, and ä is U+00E4 while z is U+007A, so it lands last in every language. /sort?items=b,a,z,ä&locale=de answers a, ä, b, z, and the identical request with locale=sv answers a, b, z, ä.

How do I sort item2 before item10?

Set numeric=true, which switches on ECMA-402 numeric collation so digit runs compare as numbers. With the default numeric=false, item10 still sorts before item2.

Which collation level decided that two strings differ?

/compare returns decidedAt. The comparison is re-run at base, accent, case and variant with your other options unchanged, and the first level with a non-zero result is reported. equivalent-at-all-levels means no level separated them — identical or canonically equivalent input, but also any pair the locale's tailoring treats as equal at tertiary strength, such as hiragana vs katakana in ja or punctuation in th, where ignorePunctuation defaults to true.

Does every language have collation data?

No. Coverage comes from the serving runtime's ICU build, and reduced-ICU builds — common on edge runtimes — can lack languages such as Icelandic, Welsh or Georgian outright. Those requests still answer, with hasCollationData: false, a warning, and resolvedLocale naming the locale that really served them. /locales?locales=is,cy,ka reports what this deployment actually has.

Will this match my PostgreSQL or MySQL ORDER BY?

Not necessarily. Databases sort with their own collations — PostgreSQL with the database or column collation (often the OS LC_COLLATE), MySQL with its utf8mb4_* collations. This endpoint reports what ECMA-402 Intl.Collator does in the serving runtime, which is the JavaScript half of that mismatch.

What happens if a locale has no data for the collation I ask for?

The request succeeds but never pretends: en has no phonebk tailoring, so the response carries a warning, resolvedOptions.collation reads default, and /collations?locale=en&search=phonebk reports supportedForLocale: false.

Standards & references