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

react-scoped-i18n

v0.0.5

Published

A scoped internationalization (i18n) library for React applications

Downloads

28

Readme

react-scoped-i18n 🌐

A React i18n library where translations live next to the components that render them - no keys, no JSON files, fully type-safe at compile time.

Works with React and React Native (vanilla & Expo).


The problem with key-based i18n

Every other i18n library makes you name things. You write a key in your component, then jump to a JSON file to write the actual string, then come back. Keys get stale. Typos go unnoticed until runtime. Your translation file becomes a graveyard of strings you're not sure are still used.

react-scoped-i18n flips this: translations are just code, written inline, where you need them.

const { t } = useI18n();

const name = `Oto`;

return <Heading>
  {t({
    en: `Welcome back, ${name}!`,
    es: `¡Bienvenido de nuevo, ${name}!`,
  })}
</Heading>;

No keys. No files. ctrl+f on any rendered string takes you straight to the component.


Type safety that actually catches bugs

Forget to add a translation for a language you support? TypeScript error. Reference an unsupported language? TypeScript error. At compile time, not in production.

return <Heading>
  {t({
    en: `Welcome back, ${name}!`,
    // TS Error: Property 'es' is missing - your app supports Spanish
  })}
</Heading>;

Getting started


Key features

  • Colocated translations - live in the component, not a separate file
  • Compile-time safety - missing or unsupported languages are TypeScript errors
  • No build-time transforms - no Babel plugins, no magic, lives in React runtime (React Context)
  • No custom syntax - plain JS template literals, no {count, plural, ...} to memorise
  • Out-of-the-box formatting - numbers, currencies, dates and times via the native Intl API
  • Hot-reload friendly - language switches are reflected immediately
  • Minimal setup - takes 30 seconds

Examples

Interpolation

export const WelcomeMessage = () => {
    const { t } = useI18n();
    const name = `John`;

    return (
        <Heading>
            {t({
                en: `Welcome to the website, ${name}!`,
                es: `¡Bienvenido al sitio web, ${name}!`,
                sl: `Dobrodošli na spletno stran, ${name}!`,
            })}
        </Heading>
    );
};

Number & currency formatting

export const PriceTag = () => {
    const { t, format } = useI18n();

    const price = 19.99;

    return (
        <Text>
            {t({
                en: `The price is ${format.currency(price, "USD")}.`,
                es: `El precio es ${format.currency(price, "USD")}.`,
                sl: `Cena je ${format.currency(price, "USD")}.`,
            })}
        </Text>
    );
};

Pluralization

Full ICU category support (one, two, many, etc.), including a negative shorthand and the ability to target specific numbers.

export const Apples = () => {
    const { tPlural } = useI18n();

    const count = 12;

    return (
        <Text>
            {tPlural(count, {
                en: {
                    negative: `You are in apple debt...`,
                    one: `You have one apple.`,
                    many: `You have ${count} apples.`,
                    42: `You have the perfect number of apples!`,
                },
                es: {
                    one: `Tienes una manzana.`,
                    many: `Tienes ${count} manzanas.`,
                },
                sl: {
                    one: `Imaš eno jabolko.`,
                    two: `Imaš dve jabolki.`, // handling the Slovenian dual form
                    many: `Imaš ${count} jabolk.`,
                },
            })}
        </Text>
    );
};

Shared / common translations

const { t, commons } = useI18n();

return <Button>{t(commons.continue)}</Button>;

Who this is for

react-scoped-i18n is built for small teams and indie developers who:

  • Write and maintain their own translations (or work directly with translators in code)
  • Support a small-to-medium number of languages
  • Want TypeScript to enforce correctness, not just assist with autocomplete
  • Prefer reading code over managing JSON files

If your workflow involves external translation platforms like Crowdin or Lokalise (or third party translators touching files directly), this approach is likely not for you.


License: MIT