Trin

internationalization for TypeScript with type-checked keys, arguments and plural rules.

Trin is a compile-time and runtime-safe internationalization (i18n) engine designed for TypeScript applications. it enables structured, type-safe translation management with support for dynamic logic, nested key validation, conditional rendering, pluralization, switch-case logic, and modifier pipelines. Trin ensures that translation keys, argument values, and transformation syntax are validated at compile time where possible, dramatically reducing the risk of runtime errors. it also supports runtime locale switching, safe fallback mechanisms, and custom embedded logic using regular expressions, all while having zero dependencies.

features

  • type-safe translation keys

    ensures only valid keys are used through deep object traversal and TypeScript inference.

  • dynamic argument substitution

    allows transformations like {{ name | capitalize }} at runtime using safe substitution pipelines.

  • conditional expressions

    supports ternary logic in strings, e.g., {{ ?.isAdmin ? 'Admin' : 'User' }}.

  • pluralization

    handles pluralization with syntax like [plural.key].

  • switch-case logic

    use key-value logic to resolve strings, e.g., {{ !.role k:'admin' v:'Admin' }}.

  • modifier pipelines

    supports string modifiers like uppercase, lowercase, and capitalize in sequence.

  • locale management

    provides runtime validation and switching of active locales.

usage

import { createTranslation } from '@smaiill/trin'

// Example 1: Basic placeholder with capitalize filter
const { t } = createTranslation(
  {
    en: {
      greeting: 'Hello, {{ name | capitalize }}.',
    },
  },
  {
    locale: 'en',
  },
)

t('greeting', { name: 'john' })
// Output: Hello, John.
import { createTranslation } from '@smaiill/trin'

// Example 2: Ternary conditional rendering
const { t } = createTranslation(
  {
    en: {
      status: "{{ ?.isLoggedIn ? 'Welcome back' : 'Please log in' }}",
    },
  },
  {
    locale: 'en',
  },
)

t('status', { isLoggedIn: false })
// Output: Please log in

t('status', { isLoggedIn: true })
// Output: Welcome back
import { createTranslation } from '@smaiill/trin'

// Example 3: Pluralization with item count
const { t } = createTranslation(
  {
    en: {
      itemCount: 'You have {{ itemCount }} item[plural.itemCount].',
    },
  },
  {
    locale: 'en',
  },
)

t('itemCount', { itemCount: 1 })
// Output: You have 1 item.

t('itemCount', { itemCount: 3 })
// Output: You have 3 items.
import { createTranslation } from '@smaiill/trin'

// Example 4: Role-based view with key-value matching
const { t } = createTranslation(
  {
    en: {
      roleView: '{{ !.role k:"admin" v:"Admin Panel" k:"user" v:"User Dashboard" }}',
    },
  },
  {
    locale: 'en',
  },
)

t('roleView', { role: 'admin' })
// Output: Admin Panel

t('roleView', { role: 'user' })
// Output: User Dashboard

stack

TypeScript, TypeScript type-level programming