npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@urcolor/i18n

v2.0.1

Published

Multilingual colour naming and channel-label translations for urcolor.

Readme

@urcolor/i18n

Multilingual colour naming and channel-label translations for urcolor.

import { ColorNames, ChannelNames } from "@urcolor/i18n";
import { Color } from "@urcolor/core";

// Default chain: uwdata where it has the locale, wikidata for the rest.
const ko = await ColorNames.load("ko");
ko.of(Color.parse("#3b82f6")!);          // "파랑색"  (uwdata)
const ka = await ColorNames.load("ka");
ka.resolvedOptions().source;             // "wikidata"

// Pin to one source when provenance must be fixed.
const names = await ColorNames.load("ko", { source: "uwdata" });
names.resolve(Color.parse("#3b82f6")!);
// { name, term, probability, candidates, model, source, coverage, binDistance,
//   hueProjectionDistance }  // only set for hue-model locales

new ChannelNames("ko").of("hue"); // "색조"

The API follows the ECMAScript Intl classes: of(), resolvedOptions(), and supportedLocalesOf() behave as they do on Intl.DisplayNames.

Coverage

Colour-name data comes from two independent sources: uwdata and wikidata.

uwdata

The uwdata source covers 20 languages. Fourteen have a full-colour-space model (de en es fa fi fr ko nl pl pt ro ru sv zh); six more have a hue-circle model that only describes saturated colours (ar da el hu it tr). Upstream's raw files list dozens of additional languages, but at the pinned commit only these 20 actually have the binned naming data this package's lookup depends on — the rest have term centroids only, with no distribution to sample from, so they aren't shipped.

Sample volume is heavily skewed — English has roughly two orders of magnitude more data than Romanian — so resolvedOptions().coverage (the fraction of sRGB-reachable Oklab space that has data) varies widely: en 96.0%, ko 83.5%, zh 73.4%, ru 21.9%, ro 4.4%. resolve() reports a per-lookup coverage ("exact", "nearest", "none") rather than inventing a name.

A caveat worth knowing

With the default fallback: "nearest", colours near the achromatic extremes — very light, very dark, near-grey — can come back with a wrong but confident-looking answer. Those regions sit at the edge of the sampled space, where little or no data exists, so the nearest populated bin can be a noticeable perceptual distance away. For example, pure white (#ffffff) resolves to 연분홍색 ("light pink", 36% probability, binDistance 0.050) in Korean, and to 浅蓝色 ("light blue", 22%, binDistance 0.071) in Chinese.

The default is intentional — most callers want an answer rather than undefined — but if you need to know whether an answer came from real data or a reach, check coverage and binDistance on resolve() (which always reports the true values, regardless of fallback). Pass fallback: "none" if you'd rather get undefined than a nearest-bin guess.

This only matters for the 14 full-model languages. The 6 hue-model ones (ar da el hu it tr) either land in a populated hue bin or report no coverage at all — there's no neighbouring-bin fallback for fallback: "none" to have an opinion about, so it's a no-op there. resolve() on a hue-model locale also returns hueProjectionDistance, the Oklab distance from the query to the fully saturated colour at the same hue.

wikidata

The wikidata source covers 298 languages with a discrete-palette model: 964 catalogued colours, each with one exact sRGB value, named in whatever languages Wikidata editors have supplied. This is where the long tail lives — Georgian, Cherokee, Aymara, Amharic, and Aramaic have colour names here and none in uwdata.

It answers a different question from uwdata. Where uwdata models how speakers spontaneously name a region of colour space, wikidata records the established name of a catalogued colour. There is no sampled distribution, so resolve() reports probability as a proximity confidence, not a naming frequency — read binDistance for the underlying Oklab distance.

Coverage is terms / 964: en 93%, de 50%, ja 28%, ka 1.5%. Thin languages are shipped rather than pruned — Georgian's 14-term chunk (32 other locales carry just a single term) can't name an arbitrary colour, but it resolves colorOf("ყვითელი") correctly.

Wikidata is CC0-1.0. The "no license declared upstream, make your own assessment" caveat in Licensing below is about uwdata specifically — it does not apply here.

Default source chain

Omitting source walks the default chain — uwdata first, then wikidata. uwdata answers the 20 locales it covers, wikidata answers the other 278, and resolvedOptions().source always names whichever one actually did while resolvedOptions().sources reports the whole chain that was considered. Call getDefaultSources() to read that chain directly, without constructing a ColorNames instance first:

import { getDefaultSources } from "@urcolor/i18n";

getDefaultSources(); // ["uwdata", "wikidata"]

A tag one source has exactly outranks a tag another source only reaches by stripping subtags: load("zh-Hant") resolves to wikidata's Traditional Chinese chunk rather than falling back to uwdata's Simplified zh chunk. load("zh") still resolves to uwdata.

uwdata covers 20 locales but several of them thinly — Romanian has 4 terms, Finnish 11, Swedish 16 — where wikidata has 65, 65, and 170. Because the rule is locale-level, load("ro") stays on uwdata's 4 terms. That is deliberate: the two sources answer different questions, and switching between them on a coverage threshold would return perceptual data for one language and catalogue data for another with no defensible cutoff. Pass { source: ["wikidata"] } if you want breadth over perceptual fidelity.

Data source and attribution

Sources are never merged. Exactly one source answers an entire ColorNames instance — chosen at load time and fixed thereafter, so two colours resolved from the same instance always come from the same dataset. Omitting source lets the package pick using the default chain (uwdata, then wikidata); provenance is then implicit in the request but still explicit in the result, since resolve().source and resolvedOptions().source always name the dataset that answered. Passing a single id pins the instance and throws if that source lacks the locale.

Attribution below is scoped the same way: each source's provenance is stated separately, because the two caveats do not transfer between them.

uwdata

Colour-name data is derived from Color Naming in Different Languages, pinned at commit f0d3e30db9e4b2c3b703bde0d816043eb48a6cb5.

Kim, Y., Thayer, K., Silva Gorsky, G., & Heer, J. (2019). Color Names Across Languages: Salient Colors and Term Translation in Multilingual Color Naming Models. EuroVis.

The dataset authors' own caveat, which applies to every name uwdata returns (not to wikidata):

We represent the color labels provided by the participants in our study, which may include misspellings, but also whatever racial biases they have (e.g., the color 'skin'). This is not meant to be a prescriptive definition of what colors fit what labels.

wikidata

Colour-name data is derived from Wikidata, items whose instance-of/subclass-of chain reaches Q1075 (colour) and which carry a P465 sRGB hex triplet — exactly the citation and disclaimer exposed on getSource("wikidata"):

Wikidata contributors. Wikidata, the free knowledge base. https://www.wikidata.org/ — content available under CC0 1.0.

Names are editorial labels contributed by Wikidata editors, not measured naming behaviour. Coverage is uneven across languages, and a name's presence does not imply it is the term speakers would actually choose.

Licensing

uwdata's upstream repository declares no license file. Its README asks only that the paper be cited, which this package does — in the source, in this README, and in the documentation. Downstream users redistributing the data should make their own assessment.

wikidata content is CC0-1.0 — no such caveat applies to names from that source.

Adding a source

Sources are namespaced and never merged. A new dataset means a new directory under src/sources/, a NameSource descriptor, and generated chunks — no changes to the lookup engine. Every result carries the source that produced it, so a caller can never get an answer without knowing where it came from, whether they named that source explicitly or let the default chain pick.