Socket
Book a DemoInstallSign in
Socket

i18n-at

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

i18n-at

Type-safe internationalization tool for Next.js App Router with co-location and IDE code jumping

0.1.7
latest
Source
npmnpm
Version published
Weekly downloads
351
475.41%
Maintainers
1
Weekly downloads
Β 
Created
Source

i18n-at

🌍 Type-safe internationalization tool for Next.js App Router with co-location and IDE code jumping

✨ Features

  • πŸ—οΈ Co-location First - Define messages right where they're used
  • πŸ›‘οΈ 100% Type-safe - Full TypeScript support with strict typing
  • πŸ” IDE Code Jumping - Jump directly to message definitions

πŸš€ Quick Start

Installation

npm install i18n-at

1. Define Messages

// messages.ts
import { defineMessages, at } from "i18n-at";

export const { messages } = defineMessages({
  en: {
    dashboard: {
      title: "Dashboard",
      welcome: "Welcome, {name}!",
    },
  },
  ja: {
    dashboard: {
      title: "ダッシγƒ₯γƒœγƒΌγƒ‰",
      welcome: "{name} γ•γ‚“γ€γ‚ˆγ†γ“γοΌ",
    },
  },
  zh: {
    dashboard: {
      title: "δ»ͺ葨板",
      welcome: "欒迎,{name}!",
    },
  },
});
export type AppLocale = ExtractConfigLocales<typeof i18nConfig>;

2. Server Components

// app/[locale]/page.tsx
import { getI18n } from "i18n-at";
import { messages } from "./messages";

export default function Page({
  params: { locale },
}: {
  params: { locale: string };
}) {
  const { t, m } = getI18n(messages, locale); // Type-safe & IDE jumping!

  return (
    <div>
      <h1>{t(m.dashboard.title)}</h1>
      <p>{t(m.dashboard.welcome, { name: "User" })}</p>
    </div>
  );
}

3. Client Components

// components/Dashboard.tsx
"use client";
import { useI18n, useLocale } from "i18n-at";
import { messages } from "./messages";

export default function Dashboard() {
  const locale = useLocale();
  const { t, m } = useI18n(messages); // IDE jumping works!

  return (
    <div>
      <h1>{t(m.dashboard.title)}</h1>
      <p>{t(m.dashboard.welcome, { name: "User" })}</p>
    </div>
  );
}

4. Provider Setup

// app/layout.tsx
import { I18nClientProvider } from "@i18n-at";

export default function RootLayout({
  children,
  params: { locale },
}: {
  children: React.ReactNode;
  params: { locale: string };
}) {
  return (
    <html lang={locale}>
      <body>
        <I18nClientProvider locale={locale}>{children}</I18nClientProvider>
      </body>
    </html>
  );
}

πŸ“š API Reference

Core Functions

defineMessages(messages)

Define internationalized messages with type safety.

const { messages } = defineMessages({
  en: { hello: "Hello" },
  ja: { hello: "こんにけは" },
});

at(locale, messages)

Get type-safe locale-specific messages.

const enMessages = at("en", messages); // Type: { hello: string }
const jaMessages = at("ja", messages); // Type: { hello: string }

getI18n(messages, locale)

Server-side translation function that returns both translator and messages.

const { t, m } = getI18n(messages, "en");
const text = t(m.hello); // "Hello" with type safety

useI18n(messages)

Client-side translation hook that returns both translator and messages.

const { t, m } = useI18n(messages);
const text = t(m.hello); // Translated text with type safety

🎯 Why This Library?

πŸ—οΈ Co-location First: Keep Messages Close to Usage

Unlike traditional i18n solutions that force you to manage translations in separate files, i18n-at lets you define and use messages in the same place:

// βœ… Messages defined right where they're used
export const { messages } = defineMessages({
  en: {
    dashboard: {
      title: "Dashboard",
      welcome: "Welcome, {name}!",
    },
  },
  ja: {
    dashboard: {
      title: "ダッシγƒ₯γƒœγƒΌγƒ‰",
      welcome: "{name} γ•γ‚“γ€γ‚ˆγ†γ“γοΌ",
    },
  },
});

// Used immediately in the same component
const m = at(locale, messages);
return <h1>{t(m.dashboard.title)}</h1>;

πŸ”Ί Traditional Approach Problems

// ❌ Separate files, hard to maintain
// locales/en.json: { "dashboard.title": "Dashboard" }
// locales/ja.json: { "dashboard.title": "ダッシγƒ₯γƒœγƒΌγƒ‰" }

// No type safety, no IDE jumping
t("dashboard.title"); // ← String literal, error-prone

βœ… Our Co-location Benefits

  • 🎯 Easy Maintenance: Messages live next to their usage
  • πŸ” IDE Code Jumping: F12 jumps directly to message definitions
  • πŸ›‘οΈ 100% Type-safe: Full TypeScript support
  • 🧹 Dead Code Detection: Unused messages are easily spotted
  • ⚑ Faster Refactoring: Change component? Messages move with it
  • πŸ“ 1-Line Declaration: const { t, m } = useI18n(messages) - Simple & powerful!

πŸ”§ Advanced Usage

Dynamic Locale Loading

// Conditional locale loading
const getMessages = (locale: string) => {
  switch (locale) {
    case "en":
      return at("en", messages);
    case "ja":
      return at("ja", messages);
    default:
      return at("en", messages);
  }
};

Nested Message Structures

const { messages } = defineMessages({
  en: {
    auth: {
      login: {
        title: "Sign In",
        form: {
          email: "Email Address",
          password: "Password",
        },
      },
    },
  },
});

// Usage with full autocomplete
t(m.auth.login.form.email); // ← Full IDE support!

🀝 Contributing

We welcome contributions! Please see our Contributing Guide.

πŸ“„ License

MIT Β© Jabelic

Made with ❀️ for type-safe internationalization

Keywords

i18n

FAQs

Package last updated on 21 Aug 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚑️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.