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.
- 💪 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.
npm install locl-js
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."
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 totrue
.devMode
(optional): Whether to enable development mode. Defaults tofalse
.useCache
(optional): Whether to use caching. Defaults totrue
.
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.
Translates a key with pluralization.
key
: The key to translate.values
: An object with acount
property and other values to interpolate.format
(optional): An object with formatting options.
Changes the current language.
lang
: The language to switch to.
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.
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.
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.
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.
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!"
LocL
supports two ways of handling plurals:
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."
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."
LocL
comes with a set of built-in formatters that you can use to format your translations.
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 usingIntl.NumberFormat
.currency
: Formats a currency value usingIntl.NumberFormat
.date
: Formats a date usingIntl.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"
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!"
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"
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"'.
Contributions are welcome! Please open an issue or submit a pull request if you have any ideas or suggestions.
This project is licensed under the MIT License.