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

@aminnairi/react-translate

v2.1.0

Published

Type-safe translation for React.js

Readme

@aminnairi/react-translate

npm version types license

Type-safe translation for React

Features

  • 🛡️ 100% Type-Safe: Say goodbye to missing translations. TypeScript ensures every locale is defined for every translation at compile time.
  • 🏭 Tailored to Your App: The createTranslations factory creates a bespoke Provider and Hooks specifically typed to your app's supported locales, preventing global state pollution.
  • 💬 Dynamic Interpolation: Easily pass variables to your translations using plain TypeScript functions—no custom parsing or complex string interpolation syntax required.
  • ⚛️ React-Native Integration: Built on top of React Context and Hooks for a seamless, idiomatic integration with your React applications.
  • 🪶 Zero Dependencies: Lightweight and built directly on top of React's built-in APIs.

Prior Art

While there are many excellent internationalization libraries in the React ecosystem, @aminnairi/react-translate takes a different approach by prioritizing zero-dependency, native TypeScript type-safety without the need for code generation or complex runtime string parsing.

Here is how it compares to some of the most popular alternatives:

  • react-i18next / i18next: The industry standard. It is extremely feature-rich (async loading, pluralization, formatting) but comes with a larger bundle size. Achieving full type-safety for translation keys and interpolation arguments usually requires complex configuration or external CLI tools to parse JSON files into TypeScript types. Furthermore, it parses interpolation strings at runtime (e.g., "Hello {{name}}") rather than using native TypeScript functions.
  • react-intl (FormatJS): A powerful library built on standard Intl APIs, excelling at complex date, number, and plural formatting. However, it relies heavily on the ICU MessageFormat syntax, which can be verbose, and like react-i18next, strict type-safety is not trivial out of the box without extra tooling.
  • typesafe-i18n: Shares the goal of strong type-safety. However, it requires running a background process or generator to compile TypeScript types from its custom format, introducing an additional build step to your workflow. @aminnairi/react-translate relies purely on TypeScript's inference.
  • next-intl: An excellent choice if you are using Next.js, especially with the App Router and React Server Components. However, it is deeply coupled with Next.js paradigms and relies on ICU message formats, whereas @aminnairi/react-translate is framework-agnostic (works with standard React, React Native, Vite, etc.) and uses plain TypeScript functions.

If you need advanced features like asynchronous translation loading, complex pluralization rules out of the box, or if your translators prefer working directly with JSON files instead of TypeScript code, libraries like react-i18next or react-intl might be a better fit.

However, if you want a lightweight, zero-dependency, and instantly type-safe solution where translations live as plain TypeScript code, @aminnairi/react-translate provides a much simpler and strictly typed developer experience.

Requirements

Installation

npm install @aminnairi/react-translate

Usage

1. Initialize Translations

Create a translate.ts file to set up your locales and generate the components and hooks you will need for your application. We use createTranslations to configure the library and extract the functions we need.

// translate.ts
import { createTranslations, createLocalStorageAdapter } from "@aminnairi/react-translate";

export const {
  LocaleProvider,
  useTranslate,
  useLocale,
  defineTranslation
} = createTranslations({
  initialLocale: "en",
  locales: [
    "en",
    "fr"
  ],
  storage: createLocalStorageAdapter("locale")
});

2. Define Translations

Use defineTranslation to define type-safe translations safely outside of your components. This avoids re-creation on every render and ensures strong typing. If you add a new locale to your configuration later, TypeScript will immediately flag every defineTranslation call as an error until you provide the missing translation.

// translations.ts
import { defineTranslation } from "./translate";

export const title = defineTranslation((emails: number) => ({
  en: `Hello! You have ${emails} unread emails.`,
  fr: `Bonjour ! Vous avez ${emails} emails non-lus.`
}));

3. Provide the Context

Wrap your application in the LocaleProvider so that your components can access the current locale.

// main.tsx
import React from "react";
import { createRoot } from "react-dom/client";
import { LocaleProvider } from "./translate";
import { App } from "./app";

const rootElement = document.getElementById("root");

if (!rootElement) {
  throw new Error("Root element not found.");
}

const root = createRoot(rootElement);

root.render(
  <React.StrictMode>
    <LocaleProvider>
      <App />
    </LocaleProvider>
  </React.StrictMode>
);

4. Use in your Components

Use the useTranslate hook to get the actual translated string according to your component's current locale. Use useLocale to read or change the current language.

// app.tsx
import React, { useCallback } from "react";
import { useTranslate, useLocale } from "./translate";
import { title } from "./translations";

export function App() {
  const { locale, setLocale } = useLocale();

  const onEnglishSwitchButtonClick = useCallback(() => {
    setLocale("en");
  }, [setLocale]);

  const onFrenchSwitchButtonClick = useCallback(() => {
    setLocale("fr");
  }, [setLocale]);

  // Pass your defined translation function to the useTranslate hook
  const translateTitle = useTranslate(title);

  return (
    <div>
      <p>Current Locale: {locale}</p>
      
      <button onClick={onEnglishSwitchButtonClick}>
        Switch to English
      </button>
      <button onClick={onFrenchSwitchButtonClick}>
        Passer en français
      </button>
      
      {/* Call the resulting function with your arguments */}
      <h1>{translateTitle(456)}</h1>
    </div>
  );
}

Example

You can find a complete, working example in the apps/example directory.

API

createTranslations(options)

Initializes the translations for your app and returns the provider, hooks, and helpers tailored to your specific locales.

  • Arguments:
    • options.initialLocale: The locale to use by default on initialization.
    • options.locales: An array of all possible locales in your application.
    • options.storage (Optional): An object with get and set methods to persist the locale. You can use the built-in createLocalStorageAdapter(key) for standard web projects.
  • Returns:
    • LocaleProvider: A React component to wrap your application.
    • useLocale: A hook to get and update the current locale.
    • defineTranslation: A helper to define a typed translation function.
    • useTranslate: A hook to apply a defined translation and get a function that returns the translated text for the current locale.

LocaleProvider

A React Context Provider component to be placed at the root of your React tree. It stores the current locale state.

  • Props:
    • children: The React components to render.

useLocale()

A React Hook that returns the current locale state and a setter function.

  • Returns:
    • locale: The currently active locale (e.g., "en" or "fr").
    • setLocale: A state setter function to update the current locale.

defineTranslation(translate)

A helper function that returns the same function you pass to it, but enforces type-safety ensuring that all configured locales are present in the returned object. This is particularly useful for maintenance: adding a new locale to your app will trigger a compilation error for every translation that hasn't been updated yet.

  • Arguments:
    • translate: A function that receives your dynamic inputs and returns an object containing keys for every locale, with the translated strings as values.

useTranslate(translate)

A React Hook that connects your defined translation function to the current locale.

  • Arguments:
    • translate: A translation function created by defineTranslation.
  • Returns: A function that accepts the same arguments as your translate function but directly returns the final translated string for the currently active locale.

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Code of Conduct

We are committed to providing a welcoming and inspiring community for all. Please read our Code of Conduct.

Security

Please report any security vulnerabilities following our Security Policy.

Changelog

See the Changelog for a list of changes.

License

MIT