Skip to content

Latest commit

 

History

History
197 lines (139 loc) · 4.72 KB

File metadata and controls

197 lines (139 loc) · 4.72 KB

@openworkflowspec/i18n

A lightweight internationalization (i18n) package for React applications, providing simple translation support with automatic locale detection.

Overview

This package provides a minimal i18n solution built on React Context, designed for use in the Open Workflow Diagram Editor and other React applications.

Features

  • React Context-based: Simple provider/hook pattern
  • Automatic locale detection: Uses browser language preferences
  • Type-safe: Built with TypeScript
  • Lightweight: No heavy dependencies
  • Fallback support: Returns keys when translations are missing

Installation

pnpm add @openworkflowspec/i18n

API Reference

Exports

  • I18nProvider - React context provider for translations
  • useI18n() - Hook to access translation function and current locale
  • createI18n() - Core translation logic (typically used internally)
  • detectLocale() - Automatically detect user's preferred language

Types

type Dictionary = Record<string, string>;
type Dictionaries = Record<string, Dictionary>;

Usage

1. Define your translation dictionaries

Create a file with your translations for each supported language:

// i18n/locales.ts
export const dictionaries = {
  en: {
    save: "Save",
    cancel: "Cancel",
    delete: "Delete",
  },
  fr: {
    save: "Enregistrer",
    cancel: "Annuler",
    delete: "Supprimer",
  },
};

Important: Translation keys must be consistent across all languages.

2. Detect or specify locale

Choose the user's locale either manually or through automatic detection:

import { detectLocale } from "@openworkflowspec/i18n";
import { dictionaries } from "./i18n/locales";

const supportedLocales = Object.keys(dictionaries) as Array<keyof typeof dictionaries>;

// Auto-detect with fallback to "en"
const locale = detectLocale(supportedLocales);

// Or specify manually
const locale = "fr";

// Or combine both approaches
const locale = props.locale ?? detectLocale(supportedLocales, "en");

detectLocale() behavior:

  • Uses navigator.languages and navigator.language to detect user preferences
  • Normalizes locales to their base language code (e.g., "en-US""en")
  • Returns the fallback parameter (default: "en") if no match found
  • Returns fallback in non-browser environments (SSR-safe)

3. Wrap your app with I18nProvider

import { I18nProvider } from "@openworkflowspec/i18n";
import { dictionaries } from "./i18n/locales";

function App() {
  const locale = detectLocale(Object.keys(dictionaries));

  return (
    <I18nProvider locale={locale} dictionaries={dictionaries}>
      <YourAppContent />
    </I18nProvider>
  );
}

4. Use translations with useI18n()

Inside any component within the provider:

import { useI18n } from "@openworkflowspec/i18n";

function MyComponent() {
  const { t, locale } = useI18n();

  return (
    <div>
      <p>Current locale: {locale}</p>
      <button>{t("save")}</button>
      <button>{t("cancel")}</button>
    </div>
  );
}

Translation fallback: If a key is missing, t() returns the key itself:

t("unknown_key"); // Returns: "unknown_key"

Error handling: useI18n() must be used inside I18nProvider or it will throw an error.

Architecture

src/
├── index.ts                    # Public exports
├── core/
│   └── createI18n.ts          # Core translation logic
├── react/
│   └── I18nProvider.tsx       # React Context provider and hook
└── utils/
    └── detectLocale.ts        # Browser locale detection

Development

Build

# Development build
pnpm build:dev

# Production build (includes tests)
pnpm build:prod

Test

pnpm test

Tests are located in the tests/ directory and use Vitest.

TypeScript

This package is written in TypeScript and includes type definitions. The build outputs:

  • dist/index.js - ESM JavaScript
  • dist/index.d.ts - TypeScript declarations

License

Apache-2.0

Repository

Part of the Open Workflow Editor monorepo.