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

@vixen-tech/lynguist

v1.0.2

Published

A lightweight, type-safe internationalization (i18n) library for JavaScript/TypeScript applications with Laravel translation format support.

Readme

Lynguist

A lightweight, type-safe internationalization (i18n) library for JavaScript/TypeScript applications with Laravel translation format support.

For Laravel version, see vixen-tech/laravel-lynguist.

Inspired by laravel-translator-js and lingua.

Features

  • Multi-language support - 60+ languages with proper pluralization rules
  • Runtime locale switching - Dynamically change languages with event notifications
  • Smart placeholders - Laravel-style variable replacement with case transformation
  • Advanced pluralization - Pipe-separated and interval notation support
  • Link parsing - Convert [text] placeholders to HTML anchor tags
  • Vite integration - Virtual module plugin for loading JSON translation files (supports any framework)
  • Type-safe - Full TypeScript support with typed translation keys

Installation

npm install @vixen-tech/lynguist
yarn install @vixen-tech/lynguist

Quick Start

With Vite

1. Configure the Vite plugin:

// vite.config.ts
import { defineConfig } from 'vite'
import { lynguist } from '@vixen-tech/lynguist/vite'

export default defineConfig({
    plugins: [
        lynguist({
            langPath: 'lang', // default
            additionalLangPaths: ['vendor/package/lang'] // optional
        })
    ]
})

2. Create translation files:

File: /lang/en.json

{
    "greeting": "Hello :name",
    "items": "One item|:count items",
    "welcome": "Hello World"
}

Works best with its Laravel counterpart: vixen-tech/laravel-lynguist.

3. Use in your application:

import { __, setLocale } from '@vixen-tech/lynguist'

// Simple translation
__('welcome') // "Hello World"

// With placeholder
__('greeting', { name: 'John' }) // "Hello John"

// With pluralization
__('items', 5) // "5 items"

// Switch locale
setLocale('de')

Manual Setup

import { Lynguist, __ } from '@vixen-tech/lynguist'

Lynguist({
    locale: 'en',
    translations: {
        welcome: 'Hello World',
        greeting: 'Hello :name'
    }
})

__('welcome') // "Hello World"

Inertia.js

To reactively switch locale, you can create a wrapper component that assigns current locale to document's lang attribute:

const locale = usePage().props.locale

if (typeof window !== 'undefined') {
    document.documentElement.lang = locale
}

Here's what it looks like in React:

export function Wrapper({ children }: PropsWithChildren) {
    const locale = usePage<SharedData>().props.locale

    if (typeof window !== 'undefined') {
        document.documentElement.lang = locale
    }

    return <>{children}</>
}

Placeholders

Lynguist supports Laravel-style placeholder replacement with automatic case transformation:

const translations = {
    greeting: 'Hello :name',
    welcome: 'Welcome :Name',       // capitalized
    shout: 'HEY :NAME'              // uppercase
}

__('greeting', { name: 'John' })    // "Hello John"
__('welcome', { Name: 'john' })     // "Welcome John"
__('shout', { NAME: 'john' })       // "HEY JOHN"

Pluralization

Basic Pluralization

Use pipe-separated values for simple plural forms:

const translations = {
    items: 'One item|:count items'
}

__('items', 1)  // "One item"
__('items', 5)  // "5 items"

Interval Notation

For more control, use interval notation:

const translations = {
    apples: '{0} No apples|{1} One apple|[2,*] :count apples'
}

__('apples', 0)   // "No apples"
__('apples', 1)   // "One apple"
__('apples', 5)   // "5 apples"

Language-Specific Rules

Lynguist handles complex pluralization rules for languages like Russian, Arabic, and Polish:

// Russian has 3 plural forms
const translations = {
    apples: ':count яблоко|:count яблока|:count яблок'
}

__('apples', 1)   // "1 яблоко"
__('apples', 2)   // "2 яблока"
__('apples', 5)   // "5 яблок"
__('apples', 21)  // "21 яблоко"

API Reference

__(key, countOrReplace?, replace?)

Main translation function supporting both simple translations and pluralization.

__('welcome')                        // Simple translation
__('greeting', { name: 'John' })     // With placeholders
__('items', 5)                       // With count
__('items', 5, { type: 'file' })     // With count and placeholders

trans(key, replace?)

Simple translation without pluralization.

trans('greeting', { name: 'John' })  // "Hello John"

transChoice(key, count, replace?)

Plural-aware translation.

transChoice('items', 5)              // "5 items"

setLocale(locale)

Change the current language.

setLocale('de')

getLocale()

Get the current language code.

getLocale()  // "en"

getAvailableLocales()

Get all available language codes.

getAvailableLocales()  // ["en", "de", "fr"]

getTranslations(locale?)

Get translations for a specific or current locale.

getTranslations()       // Current locale translations
getTranslations('de')   // German translations

onLocaleChange(callback)

Subscribe to locale change events. Returns an unsubscribe function.

const unsubscribe = onLocaleChange((newLocale, previousLocale) => {
    console.log(`Changed from ${previousLocale} to ${newLocale}`)
})

// Later: stop listening
unsubscribe()

linkify(text, urls)

Parse link placeholders in a string and replace with HTML anchor tags. Use [text] to mark link text.

// Single link
linkify('Click [here] to continue', 'https://example.com')
// → 'Click <a href="https://example.com">here</a> to continue'

// Multiple links (matched by index)
linkify('[First] and [second] links', ['https://a.com', 'https://b.com'])
// → '<a href="https://a.com">First</a> and <a href="https://b.com">second</a> links'

// Escape brackets with backslash
linkify('Use \\[brackets\\] literally', 'https://example.com')
// → 'Use [brackets] literally'

Unmatched placeholders (more [...] than URLs) are left as-is.

Vite Plugin Options

| Option | Type | Default | Description | |-----------------------|------------|-------------|----------------------------------------| | langPath | string | 'lang' | Path to the translation directory | | additionalLangPaths | string[] | undefined | Additional paths for translation files |

Supported Languages

Lynguist supports 60+ languages with proper pluralization rules including:

Afrikaans, Amharic, Arabic, Belarusian, Bengali, Bosnian, Bulgarian, Catalan, Czech, Welsh, Danish, German, Greek, English, Esperanto, Spanish, Estonian, Basque, Persian, Finnish, Filipino, French, Irish, Galician, Hebrew, Hindi, Croatian, Hungarian, Armenian, Icelandic, Italian, Japanese, Korean, Lithuanian, Latvian, Macedonian, Mongolian, Maltese, Dutch, Norwegian, Polish, Portuguese, Romanian, Russian, Slovak, Slovenian, Serbian, Swedish, Tamil, Thai, Turkish, Ukrainian, Urdu, Vietnamese, Chinese, and more.

License

ISC