A lightweight internationalization (i18n) package for React applications, providing simple translation support with automatic locale detection.
This package provides a minimal i18n solution built on React Context, designed for use in the Open Workflow Diagram Editor and other React applications.
- 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
pnpm add @openworkflowspec/i18nI18nProvider- React context provider for translationsuseI18n()- Hook to access translation function and current localecreateI18n()- Core translation logic (typically used internally)detectLocale()- Automatically detect user's preferred language
type Dictionary = Record<string, string>;
type Dictionaries = Record<string, Dictionary>;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.
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.languagesandnavigator.languageto detect user preferences - Normalizes locales to their base language code (e.g.,
"en-US"→"en") - Returns the
fallbackparameter (default:"en") if no match found - Returns
fallbackin non-browser environments (SSR-safe)
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>
);
}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.
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
pnpm build:dev
# Production build (includes tests)
pnpm build:prodpnpm testTests are located in the tests/ directory and use Vitest.
This package is written in TypeScript and includes type definitions. The build outputs:
dist/index.js- ESM JavaScriptdist/index.d.ts- TypeScript declarations
Apache-2.0
Part of the Open Workflow Editor monorepo.