Intl-T: Fully-Typed Object-Based i18n Translation Library

repository·main·Indexed 43 days ago

https://github.com/nivandres/intl-t

A type-safe internationalization library for TypeScript environments that treats translation files as a navigable tree. Version 1.3.0 supports ICU message format, dynamic imports, and zero external dependencies. It includes a core engine, a CLI for generating TypeScript declarations, and specialized integrations for React and Next.js (including App Router and RSC support).

Tokens
44.7K
Snippets
152
Records
182
Agent score
52%

What's inside Intl-T

  1. Overview of @intl-t/utils

    main
    @intl-t/utils is a utility package that bundles small, reusable functions used throughout the Intl-T ecosystem. It provides essential helpers for internationalization tasks such as locale negotiation, URL and path matching, format helpers, and inject/resolver helpers for managing translation data and runtime environments.
  2. What is @intl-t/declarations?

    main
    @intl-t/declarations is a lightweight CLI and library designed to generate TypeScript declaration files from your intl-t translation JavaScript objects. Its primary purpose is to ensure that your TypeScript autocompletion and strict typing remain perfectly synchronized with your actual translation source files.
  3. Overview of @intl-t/core

    main
    @intl-t/core is the typed, Node.js-based i18n engine for the Intl-T ecosystem. It is responsible for building the translation tree using safe keys and values, managing variable inheritance, handling dynamic imports, and providing ICU-compatible formatting. This core engine powers all framework-specific integrations (such as React and Next.js).
  4. Overview of @intl-t/format

    main
    @intl-t/format provides formatting and injection utilities for the Intl-T ecosystem. It is designed to handle ICU message parsing, variable interpolation, and provides helpers to construct rich outputs—such as strings or UI elements—while maintaining consistent, type-friendly behavior.
  5. Overview of @intl-t/next

    main
    @intl-t/next is a specialized package that integrates the intl-t library into Next.js applications. It provides helpers designed for the Next.js App Router, including support for navigation, middleware, React Server Components (RSC), and locale-aware links. A key benefit is that it maintains full type safety for your translation tree throughout the Next.js integration, ensuring that your i18n logic remains robust during server-side rendering and client-side navigation.
  6. Use @intl-t/locales for consistent locale typing

    main
    @intl-t/locales provides shared locale typing and helpers used across the intl-t ecosystem. It ensures that ISO language codes and metadata remain consistent when negotiating languages or performing formatting operations throughout your application.
  7. Use @intl-t/react for React-based internationalization

    main

    @intl-t/react provides lightweight React bindings for the intl-t library. It enables full TypeScript safety for translations and rich content through three main features:

    1. A Provider: To supply translation context to your React component tree.
    2. A typed useTranslation hook: To access translations within functional components with full type safety.
    3. Component-safe variable injection: To safely render translations that include dynamic variables or rich content.

    This package is designed to work seamlessly with the core intl-t ecosystem to ensure that your i18n keys and variables are checked at compile time.

  8. Define default values and complex logic in translations

    main

    Translations can include default values for specific nodes (useful for variable injection) and support extended ICU message formats for pluralization and date formatting. You can even inject code snippets using specific syntax.

    {
      // ICU Pluralization
      "summary": "{count, plural, =0 {no items} one {# item} other {# items}}",
      
      // ICU Date formatting
      "main": "It is {now, date, sm}",
    
      // Node with default values for variables
      "account": {
        "options": {
          "change": "Change your account settings. Your account id is {accountId}"
        },
        "values": {
          "accountId": 0
        }
      },
    
      // Injecting code/dynamic values
      "values": {
        "now": "{(Date.now())}"
      }
    }
  9. Understand the core intl-t API pattern

    main

    Intl-T uses a typed factory pattern. Instead of providing a collection of unrelated utilities, the library provides factories like createTranslation() and createNavigation() that return a single, cohesive, and fully-typed API surface.

    When using these factories, you should prefer destructuring the helpers you need directly from the returned object rather than creating manual wrappers. This ensures you maintain the full type safety and features provided by the library.

    Key concepts:

    • Typed Callable Surface: createTranslation() returns an object that acts as a typed facade. It includes various aliases and helpers (like t, Translation, useTranslation, etc.) that all belong to the same translation context.
    • Derived API Surface: The helpers you use are derived from your specific configuration, meaning they are aware of your locale structure and TypeScript types.
    // Recommended pattern: Destructuring helpers directly
    const { Translation, useTranslation, getTranslation } = createTranslation(config);
    
    // Alternative pattern: Using the returned object as a single surface
    const t = createTranslation(config);
    // 't' itself carries the same typed surface and aliases
  10. How translation nodes work

    main

    In Intl-T, translation nodes are not plain strings. They are sophisticated objects that behave differently depending on the context in which they are used:

    1. As a Function: They can be called to resolve specific paths or pass arguments.
    2. As an Object: They can be traversed via property access (e.g., t.errors.notFound).
    3. As a String-like value: They can be rendered directly in JSX or converted to strings for text output.

    Nodes support advanced features like variable inheritance (where a child node inherits variables from its parent) and locale-prefixed access. When designing your locale JSON, remember that nodes can use base for text with children and values for default variables.

  11. Design locale JSON structure

    main

    When creating your translation files, follow these structural rules to ensure consistency and proper node behavior:

    • Structural Identity: All locale files must be structurally identical.
    • Simple Leaves: Use plain strings for simple text nodes.
    • base key: Use base when a node needs to contain both text and child nodes.
    • values key: Use values to declare or override default variables for a node.
    • Arrays: Use arrays only when the branch is genuinely a list.
    • Reserved Keys: Avoid using these names for your own node keys: base, values, children, parent, node, path, settings, key, default, catch, then.
  12. Migrate translations to the Intl-T tree model

    main

    Intl-T uses a tree-shaped structure for locale files. If your existing translations are in a flat JSON format (e.g., "home.title": "Welcome"), you must convert them into nested objects (e.g., { "home": { "title": "Welcome" } }).

    Best Practices:

    • Keep every locale file structurally identical to ensure type safety and consistency.
    • Review reserved keys before naming new nodes in your tree.
    • Only introduce base and values keys if they provide tangible improvements to your structure or TypeScript typing.