@intl-party/core
v1.3.0
Published
Core internationalization library with type-safe translations and advanced locale detection
Downloads
77
Maintainers
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/coreBasic 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-messageformati18n.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 errorGeneric 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
