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

@cjean-fr/i18n-tiny

v1.0.1

Published

Zero-dependency, type-safe, minimalist internationalization library.

Readme

@cjean-fr/i18n-tiny

Zero-dependency, type-safe, minimalist internationalization library.

Provides a simple way to manage translations with strict TypeScript inference, ensuring you never miss a translation key or a required parameter.

Features

  • 📦 Tiny: Minimal footprint, zero external dependencies.
  • 🔒 Type-Safe: Autocompletion for keys and validation for required parameters.
  • 🚀 Fast: Simple string interpolation.
  • 🛠 Flexible: "Define Spec First" approach.
  • 🤖 AI-Friendly: Built-in skill for agentic adoption.

Installation

bun add @cjean-fr/i18n-tiny
# or
npm install @cjean-fr/i18n-tiny

Usage

1. Define your Translation Specification

Define the structure of your translations (Keys -> List of required params). It's recommended to define a type with readonly arrays.

import { createTranslator, defineTranslations } from "@cjean-fr/i18n-tiny";

export type AppTranslationSpec = {
  welcome: readonly ["name"]; // Requires 'name'
  notifications: readonly ["count"]; // Requires 'count'
  logout: readonly []; // No parameters
  "user-profile": readonly ["id"]; // Supports dashes in keys
};

2. Implement Languages

Use the defineTranslations helper to strictly enforce keys AND inline placeholders. This is the most bulletproof way to catch typos like {nom} instead of {name} at compile time.

export const en = defineTranslations<AppTranslationSpec>()({
  welcome: "Welcome back, {name}!",
  notifications: "You have {count} new messages.",
  logout: "Log out",
  "user-profile": "User profile #{id}",
});

// A typo in a placeholder will trigger a TypeScript error!
// export const fr = defineTranslations<AppTranslationSpec>()({
//   welcome: "Bienvenue {nom} !", // ❌ Error: Type '"Bienvenue {nom} !"' is not assignable...
//   ...
// });

3. Create the Translator

const t = createTranslator<AppTranslationSpec>(en);

// ✅ Correct usage
console.log(t("welcome", { name: "Alice" })); // "Welcome back, Alice!"
console.log(t("logout")); // "Log out"

Alternative: Auto-Infer The Specification

If you prefer to write your translations first, you can use InferSpec to automatically generate the specification from a base language.

import { type InferSpec, defineTranslations, createTranslator } from "@cjean-fr/i18n-tiny";

// 1. Define base language (must use `as const`)
const baseEn = {
  welcome: "Welcome {name}",
  logout: "Log out",
} as const; 

// 2. Infer the Spec automatically
type AppSpec = InferSpec<typeof baseEn>;

// 3. Keep other languages strictly typed based on the inferred spec
const fr = defineTranslations<AppSpec>()({
  welcome: "Bienvenue {name}",
  logout: "Se déconnecter",
});

const t = createTranslator<AppSpec>(baseEn);

Interpolation

The library uses a regex-based interpolation. Supported placeholders: {variable}, {user_name}, {my-variable}.

import { interpolate } from "@cjean-fr/i18n-tiny";

interpolate("Hello {name}", { name: "Bob" }); // "Hello Bob"

Advanced: Custom Result Types (JSX, etc.)

By default, the translator returns a string. You can customize the return type (and allowed parameter types) to integrate with UI libraries like React.

import { type Translator } from "@cjean-fr/i18n-tiny";
import type { ReactNode } from "react";

// Define tx returning ReactNode and accepting ReactNode as parameters
const tx: Translator<AppTranslationSpec, ReactNode> = (key, ...args) => {
  return t(key, ...(args as any));
};

// Now you can pass JSX elements as parameters!
const element = tx("welcome", {
  name: <strong>Alice</strong>,
});

Advanced: Custom Interpolator (ICU, etc.)

By default, the library uses simple regex string replacement. You can easily plug in a more powerful interpolator like ICU MessageFormat (useful for plurals, gender, etc.) by passing an interpolate function in the config.

import { createTranslator } from "@cjean-fr/i18n-tiny";
import IntlMessageFormat from "intl-messageformat";

const translations = {
  cart: "{count, plural, =0 {No items} one {1 item} other {{count} items}} in your cart.",
} as const;

type Spec = {
  cart: readonly ["count"];
};

const t = createTranslator<Spec>(translations, {
  locale: "en-US",
  interpolate: (template, params, { locale }) => {
    return new IntlMessageFormat(template, locale).format(params) as string;
  },
});

console.log(t("cart", { count: 1 })); // "1 item in your cart."

AI-Friendly

@cjean-fr/i18n-tiny is designed with AI-first development in mind. The strict Type-safety and Spec-First approach make it easy for AI agents to write correct translations.

It includes a dedicated Skill that agents can consume to learn how to use the library optimally.

npx skills add @cjean-fr/i18n-tiny

Security

⚠️ This library does NOT sanitize inputs.

The interpolate function performs simple string replacement. Do not use the output directly in HTML (e.g., innerHTML) if parameters contain user-generated content.

License

MIT © Christophe Jean