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

eqqo-react

v0.1.0

Published

A fast, runtime translation library for React.

Readme

eqqo-react

Translate your React app into any language with a few lines of code. No code changes, no i18n files, no hassle. Just wrap your app and switch languages on the fly, powered by AI.

Installation

npm install eqqo-react
# or
yarn add eqqo-react
# or
pnpm add eqqo-react

Note: The LanguageSelector component works out of the box with inline styles. No CSS framework required! However, you can optionally customize it with Tailwind CSS or your own className.

Quick Start

1. Wrap Your App

import { TranslatorProvider } from "eqqo-react";

function App() {
  return (
    <TranslatorProvider publicKey="your-public-key" defaultLanguage="en">
      <YourApp />
    </TranslatorProvider>
  );
}

2. Add a Language Switcher

Option A: Use the Built-in LanguageSelector Component

The easiest way to add language switching is with the pre-built LanguageSelector component:

import { LanguageSelector } from "eqqo-react";

function App() {
  return (
    <div>
      <LanguageSelector />
      <YourContent />
    </div>
  );
}

Customize the appearance with props:

<LanguageSelector
  languages={["en", "es", "fr", "de", "ja", "zh-hans"]}
  textStyle="abbreviated"
  variant="searchable"
  className="my-custom-class"
/>

Option B: Build Your Own with useTranslation Hook

For custom UI, use the useTranslation hook:

import { useTranslation } from "eqqo-react";

function LanguageSwitcher() {
  const { switchLanguage, currentLanguage, isLoading } = useTranslation();

  return (
    <div>
      <button onClick={() => switchLanguage("es")} disabled={isLoading}>
        Español
      </button>
      <button onClick={() => switchLanguage("en")} disabled={isLoading}>
        English
      </button>
    </div>
  );
}

That's it! Your entire app will automatically translate when users switch languages.

Excluding Content from Translation

Sometimes you need to prevent certain text from being translated (like brand names, code snippets, or proper nouns). Eqqo provides three ways to mark content as "do not translate":

Using the dnt() function

The dnt() function is a quick way to mark inline text:

import { dnt } from "eqqo-react";

function App() {
  return (
    <div>
      <h1>Welcome to {dnt("MyBrand")}</h1>
      <p>Use the command {dnt("npm install")} to get started</p>
    </div>
  );
}

Using the <NoTranslate> Component

For larger blocks of content, use the NoTranslate component:

import { NoTranslate } from "eqqo-react";

function App() {
  return (
    <div>
      <h1>Welcome to our app</h1>
      <NoTranslate>
        <pre>
          <code>const greeting = "Hello, World!"; console.log(greeting);</code>
        </pre>
      </NoTranslate>
      <p>This text will be translated normally</p>
    </div>
  );
}

Using the data-no-translate Attribute

You can also add the data-no-translate attribute directly to any element:

function App() {
  return (
    <div>
      <h1>
        Welcome to <span data-no-translate="true">MyBrand</span>
      </h1>
      <p>
        Use the command <code data-no-translate="true">npm install</code> to get
        started
      </p>
    </div>
  );
}

Or in plain HTML:

<div>
  <h1>Welcome to <span data-no-translate="true">MyBrand</span></h1>
  <pre data-no-translate="true">
    <code>const greeting = "Hello, World!";</code>
  </pre>
</div>

Note: Any content marked with dnt(), <NoTranslate>, or data-no-translate="true" will remain in its original form regardless of the selected language.

Grouped Translation

When you have text split across multiple elements (like individual <span> elements for styling), translating each word separately can lose context and produce poor translations. Use grouped translation to translate all text within a container as a single unit while preserving your formatting.

Using the <TranslateGroup> Component

Wrap your content with the TranslateGroup component:

import { TranslateGroup } from "eqqo-react";

function Hero() {
  return (
    <TranslateGroup className="w-full max-w-[692px] text-left lg:text-center">
      <span className="inline-block mr-[0.3em]">The</span>
      <span className="inline-block mr-[0.3em]">first</span>
      <span className="inline-block mr-[0.3em]">AI</span>
      <span className="inline-block mr-[0.3em]">for</span>
      <span className="inline-block mr-[0.3em]">corporate</span>
      <span className="inline-block mr-[0.3em]">events</span>
    </TranslateGroup>
  );
}

Using the data-translate-group Attribute

You can also add the attribute directly to any element:

<div data-translate-group className="your-classes">
  <span>The</span>
  <span>first</span>
  <span>AI</span>
  <span>for</span>
  <span>corporate</span>
  <span>events</span>
</div>

Or in plain HTML:

<div data-translate-group class="w-full max-w-[692px]">
  <span class="inline-block mr-[0.3em]">The</span>
  <span class="inline-block mr-[0.3em]">first</span>
  <span class="inline-block mr-[0.3em]">AI</span>
  <span class="inline-block mr-[0.3em]">for</span>
  <span class="inline-block mr-[0.3em]">corporate</span>
  <span class="inline-block mr-[0.3em]">events</span>
</div>

How It Works

  1. Combines text: All text nodes within the group are combined into a single string (e.g., "The first AI for corporate events")
  2. Translates as one: The combined text is sent to the translation API as a single phrase, preserving context
  3. Preserves formatting: After translation, the text is intelligently distributed back to the original elements, maintaining your styling and structure

Note: The system automatically handles cases where the translated text has a different number of words by distributing them across the available elements.

API Reference

<TranslatorProvider>

Wrap your app with this component to enable translations.

Props

| Prop | Type | Required | Description | | ----------------- | ----------- | -------- | ------------------------------------------------------------- | | publicKey | string | ✅ Yes | Your Eqqo public API key | | defaultLanguage | string | ✅ Yes | The language of your original content (e.g., "en") | | children | ReactNode | ✅ Yes | Your app components | | rootElement | HTMLElement | ❌ No | Custom root element to translate. Defaults to document.body |

Example

<TranslatorProvider publicKey="pk_live_abc123xyz" defaultLanguage="en">
  <App />
</TranslatorProvider>

<LanguageSelector>

A ready-to-use language selector component with dropdown UI. Includes loading states, searchable variant, and customizable styling.

Props

| Prop | Type | Default | Description | | ----------- | ---------------------------- | -------------- | --------------------------------------- | | languages | string[] | ["en", "es"] | Array of language codes to display | | textStyle | "abbreviated" \| "default" | "default" | Display style: "EN" vs "English" | | variant | "default" \| "searchable" | "default" | Dropdown variant: simple or with search | | className | string | "" | Additional CSS class for custom styling |

Examples

Default variant:

<LanguageSelector languages={["en", "es", "fr", "de"]} />

With language variants:

<LanguageSelector
  languages={["en-gb", "en-us", "pt-br", "pt-pt", "zh-hans", "zh-hant"]}
/>

Searchable variant with abbreviated text:

<LanguageSelector variant="searchable" textStyle="abbreviated" />

Custom styling with Tailwind:

<LanguageSelector
  className="shadow-xl"
  languages={["en", "es", "fr", "de", "ja"]}
/>

You can override any of the default Tailwind classes by passing your own className.

useTranslation()

Access translation controls from any component. Must be used inside TranslatorProvider.

Returns

| Property | Type | Description | | ----------------- | --------------------------------- | ------------------------------ | | switchLanguage | (lang: string) => Promise<void> | Switch to a different language | | currentLanguage | string | Currently active language code | | isLoading | boolean | True while translating |

Example

function LanguageMenu() {
  const { switchLanguage, currentLanguage, isLoading } = useTranslation();

  return (
    <select
      value={currentLanguage}
      onChange={(e) => switchLanguage(e.target.value)}
      disabled={isLoading}
    >
      <option value="en">English</option>
      <option value="es">Español</option>
      <option value="fr">Français</option>
      <option value="de">Deutsch</option>
      <option value="ja">日本語</option>
    </select>
  );
}

<NoTranslate>

Component that prevents its children from being translated.

Props

| Prop | Type | Required | Description | | ---------- | --------- | -------- | ----------------------------------- | | children | ReactNode | ✅ Yes | Content to exclude from translation |

Example

<NoTranslate>
  <div>This content will not be translated</div>
</NoTranslate>

Note: You can also use the data-no-translate="true" attribute directly on any HTML element instead of using this component.

dnt()

Helper function that wraps text in a component to exclude it from translation.

Parameters

| Parameter | Type | Description | | --------- | ------ | ------------------------------------ | | text | string | The text to exclude from translation |

Returns

A React element that prevents the text from being translated.

Example

<p>Welcome to {dnt("GitHub")} - the world's leading platform</p>

<TranslateGroup>

Component that marks its children to be translated as a group. All text nodes within this component will be combined and translated together, preserving context while maintaining the original formatting structure.

Props

| Prop | Type | Required | Description | | ---------- | -------------- | -------- | ----------------------------------------------------------------------- | | children | ReactNode | ✅ Yes | Content to translate as a group | | groupId | string | ❌ No | Optional group identifier. Defaults to "true" | | ...props | HTMLAttributes | ❌ No | All standard HTML div attributes (className, style, etc.) are supported |

Example

<TranslateGroup className="text-center">
  <span>The</span>
  <span>first</span>
  <span>AI</span>
  <span>for</span>
  <span>corporate</span>
  <span>events</span>
</TranslateGroup>

Note: You can also use the data-translate-group attribute directly on any element instead of using the component.

Supported Languages

eqqo-react supports 40+ language codes, including source languages and target language variants:

Source Languages

  • AR - Arabic (العربية)
  • BG - Bulgarian (Български)
  • CS - Czech (Čeština)
  • DA - Danish (Dansk)
  • DE - German (Deutsch)
  • EL - Greek (Ελληνικά)
  • EN - English (all English variants)
  • ES - Spanish (all Spanish variants)
  • ET - Estonian (Eesti)
  • FI - Finnish (Suomi)
  • FR - French (Français)
  • HE - Hebrew (עברית) - next-gen models only
  • HU - Hungarian (Magyar)
  • ID - Indonesian (Bahasa Indonesia)
  • IT - Italian (Italiano)
  • JA - Japanese (日本語)
  • KO - Korean (한국어)
  • LT - Lithuanian (Lietuvių)
  • LV - Latvian (Latviešu)
  • NB - Norwegian Bokmål (Norsk Bokmål)
  • NL - Dutch (Nederlands)
  • PL - Polish (Polski)
  • PT - Portuguese (all Portuguese variants)
  • RO - Romanian (Română)
  • RU - Russian (Русский)
  • SK - Slovak (Slovenčina)
  • SL - Slovenian (Slovenščina)
  • SV - Swedish (Svenska)
  • TH - Thai (ไทย) - next-gen models only
  • TR - Turkish (Türkçe)
  • UK - Ukrainian (Українська)
  • VI - Vietnamese (Tiếng Việt) - next-gen models only
  • ZH - Chinese (all Chinese variants)

Target Language Variants

  • EN-GB - English (British)
  • EN-US - English (American)
  • ES-419 - Spanish (Latin American)
  • PT-BR - Portuguese (Brazilian)
  • PT-PT - Portuguese (European)
  • ZH-HANS - Chinese (Simplified)
  • ZH-HANT - Chinese (Traditional)

Note: Language codes are case-insensitive. You can use "en-gb", "EN-GB", or "En-Gb" - they all work the same way.

Customization

The LanguageSelector component works out of the box with built-in styles. You can customize it by passing a className prop with your own CSS classes (Tailwind, CSS modules, or plain CSS):

With Tailwind CSS

<LanguageSelector
  className="shadow-2xl ring-2 ring-blue-500"
  languages={["en", "es"]}
/>

With Custom CSS

<LanguageSelector className="my-custom-selector" languages={["en", "es"]} />
.my-custom-selector {
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
}

Build Your Own UI

If you need complete control, build your own UI using the useTranslation hook:

function CustomLanguageSelector() {
  const { switchLanguage, currentLanguage, isLoading } = useTranslation();

  return (
    <div>
      <button onClick={() => switchLanguage("en")} disabled={isLoading}>
        {currentLanguage === "en" ? "✓" : ""} English
      </button>
      <button onClick={() => switchLanguage("es")} disabled={isLoading}>
        {currentLanguage === "es" ? "✓" : ""} Español
      </button>
    </div>
  );
}

Features

  • Zero Configuration - Just wrap and go
  • No Code Changes - Works with your existing app
  • Instant Translations - Fast, on-demand translation
  • Smart Deduplication - Only translates unique text to save API calls
  • Original Text Restoration - Switch back to default language instantly
  • TypeScript Support - Full type definitions included
  • SSR Safe - Works with Next.js, Remix, and other SSR frameworks
  • Framework Agnostic - Works with any React setup
  • Styled & Ready - Pre-built component that works out of the box, customizable with any CSS

Framework Support

Works seamlessly with all major React frameworks:

  • Next.js (App Router & Pages Router)
  • Vite
  • Create React App
  • Remix
  • Gatsby
  • Any React 16.8+ app

Error Handling

Handle translation errors gracefully:

function LanguageButton() {
  const { switchLanguage, isLoading } = useTranslation();
  const [error, setError] = useState(null);

  const handleSwitch = async (lang) => {
    try {
      setError(null);
      await switchLanguage(lang);
    } catch (err) {
      setError("Translation failed. Please try again.");
      console.error(err);
    }
  };

  return (
    <div>
      <button onClick={() => handleSwitch("es")} disabled={isLoading}>
        Translate to Español
      </button>
      {error && <p style={{ color: "red" }}>{error}</p>}
    </div>
  );
}

Getting Your API Key

Private access only at this moment...

License

MIT