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 🙏

© 2024 – Pkg Stats / Ryan Hefner

ukti

v4.1.1

Published

~1kB Type-safe i18n and l10n JavaScript utility.

Downloads

379

Readme

Ukti (उक्ति)

version tests codefactor npm bundle size downloads github stars license

~1kB Type-safe i18n and l10n JavaScript utility.

Ukti uses ISO 639-1 for language codes and ISO 3166-1 alpha-2 for region codes by default.

"Ukti" from Sanskrit "उक्ति" translates Speech or Language.

Install

For any ESM and CommonJS JavaScript environment. If TypeScript is used, version 4.5+ is required.

npm i ukti

For UMD version:

import { createUktiTranslator } from 'ukti/build/umd/ukti.umd.cjs'
<script src="https://cdn.jsdelivr.net/npm/ukti/build/umd/ukti.umd.cjs" />
<script src="https://unpkg.com/ukti/build/umd/ukti.umd.cjs" />

Basic Usage

Ukti accepts any ISO 639-1 language codes for translations.

import { createUktiTranslator } from 'ukti'

type Definition = {
  title: undefined
  form: {
    label: undefined
    error: [{ name: string }]
  }
}

const translator = createUktiTranslator<Definition>({
  translations: {
    en: {
      title: 'Language',
      form: {
        label: 'Type your language',
        error: 'The language {{name}} is invalid.'
      }
    },
    es: {
      title: 'Idioma',
      form: {
        label: 'Escribe tu idioma',
        error: 'El idioma {{name}} no está soportado.'
      }
    }
  }
})

const t = translator('en')

console.log(t.title()) // 'Language'
console.log(t.form.label()) // 'Type your language'
console.log(t.form.error({ name: 'Spanglish' })) // 'The language Spanglish is invalid.'

If the language used is not defined in the translations, the default language is used. If no configured, 'en' (English) is used.

The translations object definition can only have two levels of depth for simplicity.

Constraints

The available languages and default language can be specified to constraint the translations. All translations are optional, except the default one. They can be any string but ISO 639-1 codes are recommended.

import { createUktiTranslator } from 'ukti'

type Definition = {
  name: undefined
}
type Languages = 'es' | 'fr' | 'hi'
type LanguagesDefault = 'es'

const translator = createUktiTranslator<Definition, Languages, LanguagesDefault>({
  languageDefault: 'es',
  translations: {
    es: {
      name: 'Nombre'
    },
    fr: {
      name: 'Nom'
    }
  }
})

const t = translator('hi')

console.log(t.name()) // 'Nombre'

If the specified language to be used is not defined ('hi') then the default language ('es') is used.

Language translations are optional (except the default one) but all definition properties have to be specified in each one.

If there is an incomplete language translation defined (such as partially defined), an empty string is returned when trying to translate it. This is to prevent inconsistent translations with some parts in one language and others in another one.

Regionalization

Ukti can optionally have regions by language. ISO 3166-1 alpha-2 country codes list is used by default.

import { createUktiTranslator } from 'ukti'

type Definition = {
  friend: undefined
}

const translator = createUktiTranslator<Definition>({
  translations: {
    en: {
      friend: 'Friend',
      regions: {
        US: {
          // United States
          friend: 'Dude'
        },
        CA: {
          // Canada
          friend: 'Buddy'
        }
      }
    },
    es: {
      friend: 'Amigo',
      regions: {
        CO: {
          // Colombia
          friend: 'Parce'
        },
        VN: {
          // Venezuela
          friend: 'Pana'
        }
      }
    }
  }
})

const t = translator('es', 'CO') // Spanish from Colombia

console.log(t.friend()) // 'Parce'

If an unknown region is specified, the general language translation is used.

Custom regions can be specified similar to the IETF language tag spec.

import { type UktiLanguages, createUktiTranslator } from 'ukti'

type Definition = {
  friend: undefined
}
type LanguageDefault = 'en'
type Regions = 'USA' | 'Canada'

const translator = createUktiTranslator<Definition, UktiLanguages, LanguageDefault, Regions>({
  translations: {
    en: {
      friend: 'Friend',
      regions: {
        USA: {
          friend: 'Dude'
        },
        Canada: {
          friend: 'Buddy'
        }
      }
    }
  }
})

const t = translator('en', 'Canada')

console.log(t.friend()) // 'Buddy'

Templates

Translations texts are templates supporting variables interpolations. e.g. displaying different words based on conditions.

import { createUktiTranslator } from 'ukti'

type Definition = {
  stock: [{ qty: number }]
}

const translator = createUktiTranslator<Definition>({
  translations: {
    en: {
      stock: "There {{qty == 1 ? 'is' : 'are'}} {{qty}} product{{qty == 1 ? '' : 's'}} available"
    }
  }
})

const t = translator('en')

console.log(t.stock({ qty: 1 })) // 'There is 1 product available'
console.log(t.stock({ qty: 3 })) // 'There are 3 products available'

The variables can be formatted using the native JavaScript Intl object methods before providing them to the translator.

import { createUktiTranslator } from 'ukti'

type Definition = {
  list: [{ items: string; length: number; location: string }]
}

const translator = createUktiTranslator<Definition>({
  translations: {
    en: {
      list: 'The land vehicle{{length == 1 ? "" : "s"}} used {{length == 1 ? "is" : "are"}} {{items}} in the {{location}}.'
    }
  }
})

const t = translator('en')

const items = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' }).format([
  'motorcycle',
  'bus',
  'car'
])

console.log(t.list({ items, length: items.length, location: 'countryside' }))
// 'The land vehicles used are motorcycle, bus, and car in the countryside.'

console.log(t.list({ items: 'car', length: 1, location: 'city' }))
// 'The land vehicle used is car in the city.'

Ukti supports the comparison operators ==, ===, !=, !==, >, >=, <, <= in the template conditionals. All comparators are strict, so == and === are interchangeably.

If the template requires variables but they are not provided or undefined when calling the translation, an empty string is returned to prevent incorrect translations. An error message is logged in the console too.

Modularization

Ukti provides some type utilities to allow modularization in translations.

import {
  type UktiLanguages, // Language code list of ISO 639-1
  type UktiRegions, // Countries code list of ISO 3166-1 alpha-2
  type UktiTranslations, // UktiTranslations<Definition, Languages?, DefaultLocale = 'en', Regions?>
  type UktiTranslation, // UktiTranslation<Definition, Regions?>
  type UktiTranslationData, // UktiTranslationData<Definition>
  type UktiTranslationDataPartial, // UktiTranslationDataPartial<Definition>
  createUktiTranslator
} from 'ukti'

type Definition = {
  friend: undefined
}

const translation_EN_Core: UktiTranslationData<Definition> = {
  friend: 'Friend'
}

const translation_EN_US: UktiTranslationDataPartial<Definition> = {
  friend: 'Dude'
}

const translation_EN_CA: UktiTranslationDataPartial<Definition> = {
  friend: 'Buddy'
}

const translation_EN: UktiTranslation<Definition, UktiRegions> = {
  ...translation_EN_Core,
  regions: {
    US: translation_EN_US,
    CA: translation_EN_CA
  }
}

type LanguageDefault = 'en'

const translations: UktiTranslations<Definition, UktiLanguages, LanguageDefault, UktiRegions> = {
  en: translation_EN
}

const translator = createUktiTranslator<Definition, UktiLanguages, LanguageDefault, UktiRegions>({
  translations
})

const language = 'en' as const satisfies UktiLanguages
const region = 'CA' as const satisfies UktiRegions
const t = translator(language, region)

console.log(t.friend()) // 'Buddy'