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

@intl-party/core

v1.3.0

Published

Core internationalization library with type-safe translations and advanced locale detection

Downloads

77

Readme

@intl-party/core

Core internationalization library that powers the entire IntlParty ecosystem.

✨ Features

  • 🔒 Type-Safe: Full TypeScript support with auto-completion
  • 🎯 Framework Agnostic: Works with any JavaScript framework
  • ⚡ Lightweight: Minimal bundle size and maximum performance
  • 🌍 Advanced Locale Detection: Smart locale detection from multiple sources
  • 🛠️ Extensible: Plugin system for custom functionality
  • 📊 Validation: Built-in validation and consistency checking

🚀 Quick Start

Installation

npm install @intl-party/core

Basic Usage

import { createI18n } from "@intl-party/core";

// Create i18n instance
const i18n = createI18n({
  locales: ["en", "es", "fr"],
  defaultLocale: "en",
  namespaces: ["common", "navigation"],
});

// Add translations
i18n.addTranslations("en", "common", {
  welcome: "Welcome to IntlParty!",
  hello: "Hello {{name}}!",
});

// Use translations
const message = i18n.t("welcome"); // "Welcome to IntlParty!"
const greeting = i18n.t("hello", { interpolation: { name: "World" } }); // "Hello World!"

🎯 API Reference

createI18n(config)

Creates a new i18n instance.

const i18n = createI18n({
  locales: ["en", "es", "fr"],
  defaultLocale: "en",
  namespaces: ["common", "navigation"],
  fallbackChain: { es: "en", fr: "en" },
});

Configuration Options

interface I18nConfig {
  locales: string[]; // Supported locales
  defaultLocale: string; // Default locale
  namespaces: string[]; // Available namespaces
  fallbackChain?: Record<string, string>; // Fallback locales
  interpolation?: {
    prefix?: string; // Interpolation prefix (default: "{{")
    suffix?: string; // Interpolation suffix (default: "}}")
  };
  validation?: {
    strict?: boolean; // Strict validation mode
    logMissing?: boolean; // Log missing translations
  };
}

Core Methods

t(key, options?)

Main translation function.

// Simple translation
i18n.t("welcome"); // "Welcome!"

// With interpolation
i18n.t("greeting", { interpolation: { name: "John" } }); // "Hello John!"

// With namespace
i18n.t("navigation.home", { namespace: "navigation" }); // "Home"

// With count (for plurals)
i18n.t("items", { count: 5 }); // "5 items"

addTranslations(locale, namespace, translations)

Add translations for a specific locale and namespace.

i18n.addTranslations("en", "common", {
  welcome: "Welcome",
  goodbye: "Goodbye",
});

i18n.addTranslations("es", "common", {
  welcome: "Bienvenido",
  goodbye: "Adiós",
});

setLocale(locale)

Change the current locale.

i18n.setLocale("es");
console.log(i18n.getLocale()); // "es"

setNamespace(namespace)

Change the current namespace.

i18n.setNamespace("navigation");
console.log(i18n.getNamespace()); // "navigation"

getLocale()

Get the current locale.

const currentLocale = i18n.getLocale();

getNamespace()

Get the current namespace.

const currentNamespace = i18n.getNamespace();

hasTranslation(key, namespace?)

Check if a translation exists.

if (i18n.hasTranslation("welcome")) {
  console.log("Translation exists");
}

🌐 Advanced Features

Locale Detection

import { detectLocale } from "@intl-party/core";

// Detect from multiple sources
const locale = detectLocale({
  locales: ["en", "es", "fr"],
  sources: [
    "localStorage", // User preference
    "cookie", // Server-side persistence
    "acceptLanguage", // Browser setting
    "queryParam", // URL parameter
  ],
  fallback: "en",
});

Fallback Chains

const i18n = createI18n({
  locales: ["en", "es", "fr", "de"],
  defaultLocale: "en",
  fallbackChain: {
    // If translation missing in Spanish, try English
    es: "en",
    // If translation missing in French, try English
    fr: "en",
    // If translation missing in German, try Spanish, then English
    de: "es",
  },
});

Interpolation (Legacy Format)

const i18n = createI18n({
  interpolation: {
    prefix: "{{", // Custom prefix
    suffix: "}}", // Custom suffix
  },
});

i18n.addTranslations("en", "common", {
  greeting: "Hello {{name}}! You have {{count}} messages.",
});

i18n.t("greeting", { interpolation: { name: "John", count: 5 } });
// "Hello John! You have 5 messages."

ICU MessageFormat

For advanced pluralization, gender selection, and locale-specific formatting, IntlParty supports ICU MessageFormat:

# Install the optional dependency
npm install intl-messageformat
i18n.addTranslations("en", "common", {
  // ICU plural
  items: "{count, plural, one {# item} other {# items}}",
  // ICU select
  pronoun: "{gender, select, male {He} female {She} other {They}}",
  // Simple ICU argument
  welcome: "Hello {name}!",
});

// Usage
i18n.t("items", { count: 1 }); // "1 item"
i18n.t("items", { count: 5 }); // "5 items"
i18n.t("pronoun", { interpolation: { gender: "female" } }); // "She"
i18n.t("welcome", { interpolation: { name: "World" } }); // "Hello World!"

Locale-Specific Plural Rules

ICU MessageFormat automatically uses the correct plural rules for each locale:

// Russian has complex plural rules (one, few, many, other)
i18n.addTranslations("ru", "common", {
  items: "{count, plural, one {# товар} few {# товара} many {# товаров} other {# товара}}",
});

i18n.setLocale("ru");
i18n.t("items", { count: 1 });  // "1 товар"
i18n.t("items", { count: 2 });  // "2 товара"
i18n.t("items", { count: 5 });  // "5 товаров"
i18n.t("items", { count: 21 }); // "21 товар"

Format Detection

IntlParty automatically detects which format each message uses:

import { isICUFormat, isLegacyFormat, detectMessageFormat } from "@intl-party/core";

isICUFormat("{count, plural, one {#} other {#}}"); // true
isICUFormat("Hello {{name}}!");                    // false

isLegacyFormat("Hello {{name}}!");                 // true
isLegacyFormat("{count, plural, one {#} other {#}}"); // false

detectMessageFormat("{count, plural, ...}"); // "icu"
detectMessageFormat("Hello {{name}}!");      // "legacy"
detectMessageFormat("Hello world!");         // "plain"

Both formats can coexist in the same project - use whichever is appropriate for each message.

Validation

const i18n = createI18n({
  validation: {
    strict: true, // Throw errors for missing translations
    logMissing: true, // Console log missing translations
  },
});

// Will log warning if key doesn't exist
i18n.t("nonexistent.key");

🔧 Utilities

createScopedTranslator(namespace)

Create a translation function scoped to a namespace.

const t = i18n.createScopedTranslator("navigation");

t("home"); // Same as i18n.t("navigation.home", { namespace: "navigation" })
t("about"); // Same as i18n.t("navigation.about", { namespace: "navigation" })

getAvailableLocales()

Get all available locales.

const locales = i18n.getAvailableLocales(); // ["en", "es", "fr"]

getAvailableNamespaces()

Get all available namespaces.

const namespaces = i18n.getAvailableNamespaces(); // ["common", "navigation"]

validateTranslations()

Validate all translations for completeness and consistency.

const validation = i18n.validateTranslations();

console.log(validation.missing); // Missing translations
console.log(validation.unused); // Unused translations
console.log(validation.inconsistent); // Inconsistent translations

📊 Events

Listen to i18n events:

// Locale change
i18n.on("localeChange", ({ locale }) => {
  console.log(`Locale changed to ${locale}`);
});

// Namespace change
i18n.on("namespaceChange", ({ namespace }) => {
  console.log(`Namespace changed to ${namespace}`);
});

// Translations loading
i18n.on("translationsLoading", ({ locale, namespace }) => {
  console.log(`Loading ${namespace} for ${locale}`);
});

// Translations loaded
i18n.on("translationsLoaded", ({ locale, namespace }) => {
  console.log(`Loaded ${namespace} for ${locale}`);
});

🎨 TypeScript Support

Type-Safe Translation Keys

interface Translations {
  common: {
    welcome: string;
    navigation: {
      home: string;
      about: string;
    };
  };
}

const i18n = createI18n<Translations>({
  locales: ["en", "es"],
  defaultLocale: "en",
  namespaces: ["common"],
});

// Fully typed translation function
const t = i18n.t;

t("welcome"); // ✅ Type-safe
t("navigation.home"); // ✅ Type-safe
t("invalid.key"); // ❌ TypeScript error

Generic Types

interface AppTranslations {
  common: CommonTranslations;
  navigation: NavigationTranslations;
  auth: AuthTranslations;
}

const i18n = createI18n<AppTranslations>({
  // ... config
});

🔄 Migration from other libraries

From react-i18next

// react-i18next
import i18n from "i18next";
i18n.t("key");

// intl-party/core
import { createI18n } from "@intl-party/core";
const i18n = createI18n(config);
i18n.t("key");

From FormatJS

// FormatJS
import { IntlProvider } from "react-intl";

// intl-party/core
import { createI18n } from "@intl-party/core";
const i18n = createI18n(config);

📦 Package Structure

@intl-party/core/
├── src/
│   ├── index.ts           # Main exports
│   ├── i18n.ts           # Core I18n class
│   ├── detection/         # Locale detection utilities
│   ├── types/            # TypeScript types
│   ├── utils/            # Utility functions
│   └── validation/       # Validation utilities
└── dist/                # Built distribution

🤝 Contributing

See the main README for contribution guidelines.

📄 License

MIT