L Ling

Generated from docs/*.md

Ling Getting Started

Install Ling, add I18nProvider, create modules, and wire up the CLI and ESLint plugin.

Getting Started

Choose a Package

For most projects, install the umbrella package:

pnpm add @orderofchaos/ling

That gives you:

  • React runtime APIs
  • core utilities
  • ling-scan
  • ling-lint
  • @orderofchaos/ling/eslint-plugin

If you want a smaller dependency surface, install the granular packages instead:

pnpm add @orderofchaos/ling-react
pnpm add -D @orderofchaos/ling-cli @orderofchaos/eslint-plugin-ling

Create Translation Files

Create a directory such as src/i18n/translations/:

// src/i18n/translations/en.ts
export const en = {
  App: {
    "Hello World": "Hello World",
    "Welcome, {{name}}!": "Welcome, {{name}}!",
  },
};

export default en;
// src/i18n/translations/ru.ts
export const ru = {
  App: {
    "Hello World": "Privet mir",
    "Welcome, {{name}}!": "Dobro pozhalovat, {{name}}!",
  },
};

export default ru;

Wrap the App with I18nProvider

// src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import {
  I18nProvider,
  type Translations,
} from "@orderofchaos/ling";

import App from "./App";
import { en } from "./i18n/translations/en";
import { ru } from "./i18n/translations/ru";

type AppLang = "en" | "ru";

const translations: Record<AppLang, Translations> = { en, ru };

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <I18nProvider<AppLang>
      translations={translations}
      defaultLanguage="en"
      supportedLanguages={["en", "ru"]}
    >
      <App />
    </I18nProvider>
  </React.StrictMode>,
);

Create a Namespace Module

// src/App.tsx
import { initI18nModule } from "@orderofchaos/ling";

const { useI18n } = initI18nModule<"en" | "ru">("App");

export function App() {
  const { t, language, changeLanguage } = useI18n();

  return (
    <div>
      <h1>{t("Hello World")}</h1>
      <p>{t("Welcome, {{name}}!", { name: "User" })}</p>
      <p>{t("Current language: {{lang}}", { lang: language })}</p>

      <button onClick={() => changeLanguage("ru")}>Russkii</button>
      <button onClick={() => changeLanguage("en")}>English</button>
    </div>
  );
}

Extract New Keys

ling-scan creates or updates translation files by scanning t("...") calls.

pnpm ling-scan src

Then check for missing translations:

pnpm ling-lint en src/i18n/translations

Add ESLint Guardrails

Use the ESLint plugin to enforce literal translation keys:

// eslint.config.mjs
import ling from "@orderofchaos/ling/eslint-plugin";

export default [
  {
    plugins: { ling },
    rules: {
      "ling/require-literal-keys": "error",
    },
  },
];

Next Steps