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

locl-js

v1.0.2

Published

Modern TypeScript internationalization (i18n) library with type-safety, performance, and backend usability

Readme

LocL.js 🌐

Coverage

LocL is a powerful, lightweight, and fully-featured TypeScript internationalization (i18n) library. It is designed to be flexible, easy to use, and highly extensible, providing a seamless experience for adding multiple languages to your projects. With built-in support for plurals, formatting, and modularization, LocL is the perfect tool for developers looking for a modern and robust i18n solution.

It is inspired by libraries like i18next and react-i18next, but with a focus on type-safety, simplicity, performance and backend usability like discord bot and other apps.

Features ✨

  • 💪 Type-Safe: Leverages TypeScript to provide compile-time safety for your translation keys, ensuring that you never miss a translation or use an incorrect key.
  • - 📦 Lightweight: With zero dependencies, LocL is a small library that won't bloat your project.
  • - 🚀 Powerful: Supports plurals, interpolation, formatting, and modularization out of the box.
  • - 🔧 Extensible: Easily extend the library with custom formatters to fit your needs.
  • - 🌍 Modular: Organize your translations into modules to keep your codebase clean and maintainable.
  • - ⚡ Fast: Uses caching to provide fast and efficient translations.
  • - 💻 Dev-Friendly: Provides helpful warnings in development mode to help you catch missing translations.

Installation

npm install locl-js

Quick Start

import { initLocL, LangWithPlurals } from "locl-js";

const resources = {
    en: {
        hello: "Hello, {name}!",
        messages: {
            one: "You have one message.",
            other: "You have {count} messages.",
        },
    },
    fr: {
        hello: "Bonjour, {name}!",
        messages: {
            one: "Vous avez un message.",
            other: "Vous avez {count} messages.",
        },
    },
};

const translator = initLocL({
    resources,
    fallbackLanguage: "en",
});

console.log(translator.t("hello", { name: "John" })); // "Hello, John!"
console.log(translator.plural("messages", { count: 1 })); // "You have one message."
console.log(translator.plural("messages", { count: 5 })); // "You have 5 messages."

translator.changeLanguage("fr");

console.log(translator.t("hello", { name: "John" })); // "Bonjour, John!"
console.log(translator.plural("messages", { count: 1 })); // "Vous avez un message."
console.log(translator.plural("messages", { count: 5 })); // "Vous avez 5 messages."

API

initLocL(config)

Initializes a new LocL instance.

  • config: An object with the following properties:
    • resources: An object where keys are language codes and values are translation objects.
    • fallbackLanguage: The language to use when a translation is not available in the current language.
    • language (optional): The initial language to use.
    • scope (optional): The scope to load translations from.
    • formatters (optional): An object with custom formatters.
    • useDefaultFormatters (optional): Whether to use the default formatters. Defaults to true.
    • devMode (optional): Whether to enable development mode. Defaults to false.
    • useCache (optional): Whether to use caching. Defaults to true.

translator.t(key, values, format)

Translates a key.

  • key: The key to translate.
  • values (optional): An object with values to interpolate into the translation.
  • format (optional): An object with formatting options.

translator.plural(key, values, format)

Translates a key with pluralization.

  • key: The key to translate.
  • values: An object with a count property and other values to interpolate.
  • format (optional): An object with formatting options.

translator.changeLanguage(lang)

Changes the current language.

  • lang: The language to switch to.

translator.withConfig(config)

Creates a new proxy translator instance with a different configuration. This is useful for creating a translator with a different scope or language without creating a new instance.

  • config: An object with the following properties:
    • scope (optional): The scope to load translations from.
    • language (optional): The language to use.

translator.clone(language, scope)

Creates a new LocL instance with a different language or scope.

  • language (optional): The language to use.
  • scope (optional): The scope to load translations from.

translator.get(key)

Gets a translation object or a specific translation value.

  • key (optional): The key of the translation to get. If not provided, it returns the entire translation object for the current language and scope.

translator.format(value, formatter, args)

Formats a value using a specific formatter.

  • value: The value to format.
  • formatter: The name of the formatter to use.
  • args (optional): An array of arguments to pass to the formatter.

Advanced Usage

Interpolation

You can interpolate values into your translations using curly braces:

const en = {
    hello: "Hello, {name}!",
};

Then, pass the values to the t function:

translator.t("hello", { name: "John" }); // "Hello, John!"

Pluralization

LocL supports two ways of handling plurals:

1. Object Pluralization

You can define plurals as an object with different forms:

const en = {
    messages: {
        one: "You have one message.",
        other: "You have {count} messages.",
    },
};

Then, use the plural function:

translator.plural("messages", { count: 1 }); // "You have one message."
translator.plural("messages", { count: 5 }); // "You have 5 messages."

2. Suffix Pluralization

You can also define plurals using suffixes:

const en = {
    message_one: "You have one message.",
    message_other: "You have {count} messages.",
};

Then, use the plural function with the base key:

translator.plural("message", { count: 1 }); // "You have one message."
translator.plural("message", { count: 5 }); // "You have 5 messages."

Formatting

LocL comes with a set of built-in formatters that you can use to format your translations.

Default Formatters

  • upper: Converts the value to uppercase.
  • lower: Converts the value to lowercase.
  • capitalize: Capitalizes the first letter of the value.
  • trim: Trims the value.
  • truncate: Truncates the value to a specific length.
  • number: Formats a number using Intl.NumberFormat.
  • currency: Formats a currency value using Intl.NumberFormat.
  • date: Formats a date using Intl.DateTimeFormat.
  • relativeDate: Formats a date as a relative time (e.g., "2 hours ago").
  • json: Converts a value to a JSON string.
  • yesNo: Returns "Yes" or "No" based on the value.
  • boolean: Returns "true" or "false" based on the value.
  • padStart: Pads the start of the value with a string.
  • padEnd: Pads the end of the value with a string.

You can use formatters in your translations like this:

const en = {
    greeting: "Hello, {name | upper}!",
};

translator.t("greeting", { name: "John" }); // "Hello, JOHN!"

You can also pass arguments to formatters:

const en = {
    price: "The price is {price | currency:USD}",
};

translator.t("price", { price: 123 }); // "The price is $123.00"

Custom Formatters

You can also define your own custom formatters:

const translator = initLocL({
    resources,
    fallbackLanguage: "en",
    formatters: {
        reverse: (value) => String(value).split("").reverse().join(""),
    },
});

const en = {
    greeting: "Hello, {name | reverse}!",
};

translator.t("greeting", { name: "John" }); // "Hello, nhoJ!"

Modules

You can organize your translations into scopes to keep your codebase clean and maintainable.

const resources = {
    en: {
        common: {
            hello: "Hello",
        },
        home: {
            title: "Welcome to the home page",
        },
    },
};

Then, you can create a translator for a specific scope:

const homeTranslator = translator.withConfig({ scope: "home" });

console.log(homeTranslator.t("title")); // "Welcome to the home page"

You can also load multiple scopes at once:

const multiScopeTranslator = translator.withConfig({ scope: ["common", "home"] });

console.log(multiScopeTranslator.t("common.hello")); // "Hello"
console.log(multiScopeTranslator.t("home.title")); // "Welcome to the home page"

Type-Safe Translations

LocL provides type-safety for your translation keys. To enable this, you can use the LangWithPlurals type to define your translation resources:

import { LangWithPlurals } from "locl-js";

const en: LangWithPlurals<typeof en> = {
    hello: "Hello, {name}!",
    messages: {
        one: "You have one message.",
        other: "You have {count} messages.",
    },
};
const fr: LangWithPlurals<typeof en> = {
    hello: "Bonjour, {name}!",
    messages: {
        one: "Vous avez un message.",
        few: "Vous avez quelques messages.", 
        // Typescript error for missing "other" plural key
    },
};

Now, you will get autocompletion and type-checking for your translation keys:

translator.t("hell"); // TypeScript error: Argument of type '"hell"' is not assignable to parameter of type '"hello" | "messages"'.

Contributing

Contributions are welcome! Please open an issue or submit a pull request if you have any ideas or suggestions.

License

This project is licensed under the MIT License.