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

@comvi/plugin-locale-detector

v0.2.0

Published

Locale detection plugin for Comvi — auto-detect from browser, URL, cookies, or storage

Readme


LocaleDetector restores a saved locale from the first configured cache target, then walks an ordered list of detection sources, returns the first match, and persists the user's choice back to one or more caches. SSR-safe (gracefully skips browser-only APIs on the server) and supports BCP 47 lookup so de-DE matches de and vice versa.

About Comvi i18n

Comvi i18n is a modern, framework-agnostic internationalization library — ICU MessageFormat, rich-text component embedding, and locale-aware Intl formatters in ~8 kB gzipped with zero runtime dependencies and no eval (CSP-safe for Chrome extensions, Cloudflare Workers, and locked-down enterprise apps).

  • Same API across Vue, React, SolidJS, Svelte, Next.js, and Nuxt.
  • Real ICU MessageFormat — locale-correct plurals, ordinals, and gender via Intl.PluralRules. Recognized by every major TMS.
  • Type-safe translation keys via TypeScript declaration merging — autocomplete and parameter validation everywhere.
  • Pluggable — translation loading, locale detection, and in-context editing are opt-in plugins.

See the main repo for the full library overview, runnable demos, and the framework binding matrix.

Why @comvi/plugin-locale-detector?

  • Multi-source detection with configurable priority. Detect from URL query string, cookie, localStorage, sessionStorage, or navigator.language in any order you choose.
  • Persists user choice. Automatically saves the detected or manually-changed locale to storage so it survives page reloads.
  • SSR-safe. Gracefully degrades when browser APIs (window, navigator, document) aren't available on the server.

📖 Documentation: https://comvi.io/docs/i18n/plugins/locale-detector/

Install

npm install @comvi/plugin-locale-detector
# Peer: @comvi/core

Quick start

import { createI18n } from "@comvi/core";
import { LocaleDetector } from "@comvi/plugin-locale-detector";

const i18n = createI18n({ locale: "en" }).use(
  LocaleDetector({
    supportedLocales: ["en", "uk", "de"],
    order: ["querystring", "localStorage", "cookie", "navigator"],
    caches: ["localStorage", "cookie"],
  }),
);

await i18n.init();
// → if URL has ?lng=uk, locale becomes "uk" and is saved to localStorage + cookie

How detection works

On initialization, the detector first checks the first entry in caches as the saved user preference. If no cached value exists, it walks order from first to last and returns the first non-empty match. Concrete walk-through with the Quick start config above and an empty cache:

| Step | Source | Looks at | Match? | | ---- | -------------- | ------------------------ | ------------- | | 1 | querystring | ?lng=uk in the URL | uk → done | | 2 | localStorage | i18n_locale key | (skipped) | | 3 | cookie | i18n_lang cookie | (skipped) | | 4 | navigator | navigator.languages[0] | (skipped) |

Once a locale is chosen — by detection or by an explicit setLocale() call — it's written to every entry in caches. Because the first cache entry is read before order, put your preferred saved-locale source first, or set caches: [] when query string / navigator detection should always run first.

BCP 47 lookup means de-DE matches de if supportedLocales: ["en", "de"], and zh-Hant-TW falls back to zh-Hant then zh. Unsupported detected locales resolve to fallbackLocale (defaulting to the configured i18n locale) and are not cached.

Pair with your framework

// React
import { createI18n, I18nProvider } from "@comvi/react";
import { LocaleDetector } from "@comvi/plugin-locale-detector";

const i18n = createI18n({ locale: "en", fallbackLocale: "en" }).use(
  LocaleDetector({
    supportedLocales: ["en", "uk", "de"],
    order: ["querystring", "cookie", "navigator"],
    caches: ["cookie", "localStorage"],
  }),
);

<I18nProvider i18n={i18n}>{/* ... */}</I18nProvider>;

Same setup works in Vue, Solid, Svelte. For Next.js and Nuxt, prefer the framework's middleware (@comvi/next's createMiddleware() or @comvi/nuxt's detectBrowserLanguage config) — they detect on the server before the page renders.

For all detection sources, cookie/storage key options, BCP 47 normalization rules, and the full options reference, see the documentation.

License

MIT © Comvi