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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@fastkit/i18n

v0.15.0

Published

A library for localizing applications into multiple languages, regardless of the server/browser execution environment.

Downloads

62

Readme

@fastkit/i18n

🌐 English | 日本語

A comprehensive library for internationalizing applications to multiple languages without depending on server/browser execution environments.

Features

  • Universal Support: Same API can be used in Node.js and browser environments
  • Type Safety: Full TypeScript support with type-safe translation system
  • Hierarchical Structure: 3-layer architecture of Space, Component, and Locale
  • Intl API Integration: Full utilization of native browser internationalization features
  • Fallback: Hierarchical translation fallback mechanism
  • Asynchronous Loading: Support for dynamic translation data loading
  • Customizable: Flexible formatter and storage system

Installation

npm install @fastkit/i18n
# or
pnpm add @fastkit/i18n

Basic Usage

1. Defining Internationalization Space

import { defineI18nSpace } from '@fastkit/i18n';

// Space definition (language settings for entire project)
const Space = defineI18nSpace({
  locales: [
    'ja',
    { name: 'en', formatLocales: ['en-US'] },
    { name: 'zh', formatLocales: ['zh-CN'] }
  ],
  baseLocale: 'ja',        // Base language
  defaultLocale: 'en',     // Default language
  fallbackLocale: 'ja'     // Fallback language
});

2. Defining Component Schema

// Translation data type definition
interface Translations {
  greeting: string;
  farewell: string;
  itemCount: string;
}

// Format definition
const dateTimeFormats = {
  short: { year: 'numeric', month: 'short', day: 'numeric' },
  long: {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
    weekday: 'long'
  }
} as const;

const numberFormats = {
  currency: { style: 'currency', currency: 'JPY' },
  percent: { style: 'percent' }
} as const;

// Schema definition
const scheme = Space.defineScheme({
  translations: (t: Translations) => true,
  dateTimeFormats,
  numberFormats
});

3. Defining Locale-Specific Data

// Japanese
const ja = scheme.defineLocale.strict({
  translations: {
    greeting: 'Hello',
    farewell: 'Goodbye',
    itemCount: '{count}個のアイテム'
  },
  dateTimeFormats: {
    short: { year: 'numeric', month: 'short', day: 'numeric' }
  },
  numberFormats: {
    currency: { style: 'currency', currency: 'JPY' }
  }
});

// English
const en = scheme.defineLocale.strict({
  translations: {
    greeting: 'Hello',
    farewell: 'Goodbye',
    itemCount: '{count} items'
  },
  numberFormats: {
    currency: { style: 'currency', currency: 'USD' }
  }
});

4. Creating and Using Components

// Component definition
const Component = scheme.defineComponent({
  locales: { ja, en }
});

// Instance creation
const i18n = Component.createInstance();

// Language switching
await i18n.setLocale('ja');

// Get translation
const greeting = i18n.t.greeting; // → 'Hello'

// Translation with parameters
const count = i18n.t.itemCount.replace('{count}', '5'); // → '5個のアイテム'

// Date/time formatting
const date = i18n.d(new Date(), 'short'); // → '2024年1月15日'

// Number formatting
const price = i18n.n(1500, 'currency'); // → '¥1,500'

Advanced Usage Examples

Asynchronous Loading

const Component = scheme.defineComponent({
  locales: {
    ja: () => import('./locales/ja'),
    en: () => import('./locales/en'),
    zh: () => import('./locales/zh')
  }
});

const i18n = Component.createInstance();

// Automatic loading on language switching
await i18n.setLocale('zh');
console.log(i18n.t.greeting); // Displays Chinese translation

Components with Dependencies

// Common component
const CommonComponent = scheme.defineComponent({
  locales: { ja: commonJa, en: commonEn }
});

// Schema with dependencies
const pageScheme = Space.defineScheme({
  translations: (t: PageTranslations) => true,
  dependencies: {
    common: CommonComponent
  }
});

const PageComponent = pageScheme.defineComponent({
  locales: { ja: pageJa, en: pageEn }
});

const pageI18n = PageComponent.createInstance();

// Access dependent components
const commonGreeting = pageI18n.common.t.greeting;
const pageTitle = pageI18n.t.title;

Custom Storage

import { createI18nObjectStorage } from '@fastkit/i18n';

// Redis storage example
const redisStorage = createI18nObjectStorage({
  get: async (key) => {
    return await redis.get(key);
  },
  set: async (key, value) => {
    await redis.set(key, JSON.stringify(value));
  }
});

const Component = scheme.defineComponent({
  locales: { ja, en },
  storage: redisStorage
});

API

defineI18nSpace

Defines an internationalization space.

const Space = defineI18nSpace({
  locales: LocaleSource[],           // Locale settings
  baseLocale: string,                // Base language
  defaultLocale?: string,            // Default language
  fallbackLocale?: FallbackConfig    // Fallback settings
});

Space.defineScheme

Defines a component schema.

const scheme = Space.defineScheme({
  translations: (t: T) => boolean,            // Translation type definition
  dateTimeFormats?: DateTimeFormats,          // Date/time formats
  relativeTimeFormats?: RelativeTimeFormats,  // Relative time formats
  numberFormats?: NumberFormats,              // Number formats
  listFormats?: ListFormats,                  // List formats
  dependencies?: Dependencies                 // Dependent components
});

scheme.defineLocale

Defines locale-specific data.

const locale = scheme.defineLocale({
  translations: TranslationsData,     // Translation data
  dateTimeFormats?: DateTimeFormats,  // Date/time formats
  numberFormats?: NumberFormats,      // Number formats
  // ...other formats
});

scheme.defineComponent

Defines a component.

const Component = scheme.defineComponent({
  locales: LocaleMap,          // Locale map
  storage?: Storage,           // Storage settings
  strict?: boolean            // Strict mode
});

Instance API

Language Operations

// Get current language
const currentLocale = i18n.locale;

// Switch language
await i18n.setLocale('en');

// List of available languages
const available = i18n.availableLocales;

Translation

// Get translation
const text = i18n.t.keyName;

// Translation function (with parameter support)
const formatted = i18n.translate('keyName', { param: 'value' });

Formatters

// Date/time formatting
i18n.d(new Date())                    // Default
i18n.d(new Date(), 'short')           // Named format
i18n.d(new Date(), { year: '2-digit' }) // Custom options

// Number formatting
i18n.n(1234.56)                       // Default
i18n.n(1234.56, 'currency')          // Currency format
i18n.n(0.95, 'percent')              // Percent

// Relative time
i18n.rt(-2, 'day')                    // '2 days ago'

// List
i18n.l(['apple', 'banana', 'orange']) // 'apple, banana, orange'

Fallback Mechanism

const Space = defineI18nSpace({
  locales: ['ja', 'en', 'zh'],
  baseLocale: 'ja',
  fallbackLocale: {
    en: 'ja',      // English → Japanese
    zh: ['en', 'ja'] // Chinese → English → Japanese
  }
});

Search order when translation is not found:

  1. Current locale
  2. Specified fallback locale
  3. Base locale

TypeScript Integration

// Automatic inference of translation types
interface AppTranslations {
  nav: {
    home: string;
    about: string;
    contact: string;
  };
  messages: {
    welcome: string;
    error: string;
  };
}

const scheme = Space.defineScheme({
  translations: (t: AppTranslations) => true
});

// Type-safe translation access
const welcome = i18n.t.messages.welcome; // ✅ Type checked
const invalid = i18n.t.invalid;          // ❌ Compile error

Dependencies

  • @fastkit/helpers: Helper utilities
  • @fastkit/tiny-logger: Logging functionality

Documentation

For detailed documentation, please visit here.

License

MIT