npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fluenti/next

v0.6.3

Published

Next.js plugin for Fluenti — withFluenti, I18nProvider, t`` transforms for App Router and Pages Router

Readme

@fluenti/next

npm bundle size license

Compile-time i18n for Next.js. App Router native. RSC + streaming + server actions out of the box.

// Server Component — zero client JS
import { t } from '@fluenti/react'

export default async function Page() {
  return <h1>{t`Welcome, ${user.name}!`}</h1>
}
// Client Component — same syntax
'use client'
import { t } from '@fluenti/react'

export default function Counter() {
  return <p>{t`You have ${count} items in your cart.`}</p>
}

No runtime parsing. Messages are compiled at build time, and the generated server/runtime helpers are tree-shaken with your app code.

Features

  • App Router native — first-class RSC, streaming SSR, and server actions support
  • Next.js 14 & 15 compatible (next >= 14.0.0)
  • t\`` tagged templates — write messages inline, extract them with the CLI
  • Binding-aware transforms — the webpack loader rewrites tagged templates only for proven Fluenti bindings
  • I18nProvider — async server component that sets up both server and client i18n in one place
  • withLocale() — per-component locale isolation in RSC
  • ICU MessageFormat — plurals, selects, nested arguments, custom formatters
  • Per-locale generated modules — server/runtime helpers are generated per project, while the client provider statically bundles configured locale catalogs for RSC hydration
  • Cookie-based locale detection — reads locale cookie in server components by default

Quick Start

1. Install

pnpm add @fluenti/next @fluenti/core @fluenti/react
pnpm add -D @fluenti/cli

2. Configure next.config.ts

import type { NextConfig } from 'next'
import { withFluenti } from '@fluenti/next'

const nextConfig: NextConfig = {
  reactStrictMode: true,
}

export default withFluenti()(nextConfig)

withFluenti() adds a webpack loader that rewrites direct-import authoring APIs in supported client/server scopes and generates a server module for RSC i18n. It reads your fluenti.config.ts automatically.

You can pass overrides directly:

export default withFluenti({
  locales: ['en', 'ja', 'zh-CN'],
  defaultLocale: 'en',
})(nextConfig)

3. Set up I18nProvider in your root layout

// app/layout.tsx
import { cookies } from 'next/headers'
import { I18nProvider } from '@fluenti/next'

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  const cookieStore = await cookies()
  const locale = cookieStore.get('locale')?.value ?? 'en'

  return (
    <html lang={locale}>
      <body>
        <I18nProvider locale={locale}>
          {children}
        </I18nProvider>
      </body>
    </html>
  )
}

I18nProvider is an async server component. It initializes the server-side i18n instance (via React.cache) and wraps children in a client-side I18nProvider for hydration.

4. Use t\`` in your pages

Server Component (default in app/):

// app/rsc/page.tsx
import { t } from '@fluenti/react'

export default async function RSCPage() {
  return (
    <div>
      <h1>{t`Server rendered`}</h1>
      <p>{t`This page is a React Server Component.`}</p>
    </div>
  )
}

Client Component:

// app/page.tsx
'use client'
import { t, useI18n } from '@fluenti/react'

export default function Home() {
  const { setLocale, preloadLocale } = useI18n()
  const name = 'World'
  return <h1>{t`Hello, ${name}!`}</h1>
}

import { t } is the primary compile-time API. It supports tagged templates and descriptor calls, but not t('message.id') lookup. In Next apps using withFluenti(), ordinary authoring imports come from @fluenti/react on both the client and the server. For runtime lookup or full imperative access, use await getI18n() on the server or useI18n() on the client.

5. Extract and compile messages

# Extract messages from source files
pnpm fluenti extract

# Translate your PO files, then compile
pnpm fluenti compile

Next.js-Specific Features

React Server Components

Server components use t\`with zero client-side JavaScript. The loader detects server context automatically (files inapp/without'use client'`).

For direct access to the i18n instance in RSC:

import { setLocale, getI18n } from '@fluenti/next'

export default async function Page({ searchParams }) {
  const params = await searchParams
  if (params.lang) setLocale(params.lang)

  const { t, locale } = await getI18n()
  return <p>{t`Current server locale: ${locale}`}</p>
}

Streaming SSR

Works with Suspense boundaries — streamed content is translated on the server:

import { Suspense } from 'react'

async function SlowContent() {
  const { getI18n } = await import('@fluenti/next')
  const { t } = await getI18n()
  await fetchData()
  return <p>{t`Streamed content loaded!`}</p>
}

export default async function StreamingPage() {
  return (
    <Suspense fallback={<p>Loading...</p>}>
      <SlowContent />
    </Suspense>
  )
}

Server Actions

Direct-import t works in 'use server' functions:

'use server'

import { t } from '@fluenti/react'

export async function greetAction(): Promise<string> {
  return t`Hello from server action`
}

Metadata i18n

Translate Next.js metadata using the server i18n instance:

import { getI18n } from '@fluenti/next'

export async function generateMetadata() {
  const i18n = await getI18n()
  return {
    title: i18n.t('My App — Internationalized'),
    description: i18n.t('A fully localized Next.js application'),
  }
}

Middleware Locale Detection

Detect locale from headers, cookies, or URL and set it via cookie:

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const SUPPORTED_LOCALES = ['en', 'ja', 'zh-CN']
const DEFAULT_LOCALE = 'en'

export function middleware(request: NextRequest) {
  const response = NextResponse.next()

  // Already has a locale cookie
  if (request.cookies.get('locale')?.value) {
    return response
  }

  // Detect from Accept-Language header
  const acceptLang = request.headers.get('accept-language') ?? ''
  const detected = acceptLang
    .split(',')
    .map((s) => s.split(';')[0]!.trim())
    .find((lang) => SUPPORTED_LOCALES.includes(lang))

  response.cookies.set('locale', detected ?? DEFAULT_LOCALE)
  return response
}

Per-Component Locale Isolation

Render a subtree in a different locale using withLocale():

import { withLocale } from '@fluenti/next/server'

export default async function Page() {
  return (
    <div>
      <h1>{t`Main content`}</h1>
      {await withLocale('ja', async () => (
        <JapaneseWidget />
      ))}
    </div>
  )
}

API Reference

withFluenti(config?)

Wraps your Next.js config with Fluenti support. Accepts an optional WithFluentConfig:

| Option | Type | Description | |--------|------|-------------| | locales | string[] | Override locales from fluenti.config.ts | | defaultLocale | string | Override source locale | | compiledDir | string | Override compiled messages directory | | serverModule | string | Custom server module path (skip auto-generation) | | resolveLocale | () => string \| Promise<string> | Custom locale resolver for server actions | | dateFormats | DateFormatOptions | Custom date format styles | | numberFormats | NumberFormatOptions | Custom number format styles | | fallbackChain | Record<string, Locale[]> | Fallback chain per locale |

I18nProvider

Async server component (imported from @fluenti/next). Place in your root layout.

| Prop | Type | Description | |------|------|-------------| | locale | string? | Active locale. Defaults to defaultLocale from config. | | children | ReactNode | Application tree |

withLocale(locale, fn)

Server utility (imported from @fluenti/next/server). Executes fn with a temporarily switched locale.

Generated Server Module

@fluenti/next exports:

| Export | Description | |--------|-------------| | I18nProvider | Async server component for layouts | | setLocale(locale) | Set the request-scoped locale | | getI18n() | Get the i18n instance (async) | | t | Compile-time translation API, preserved for advanced/server-specific imports | | Trans | Server component for rich text | | Plural | Server component for plurals | | Select | Server component for categorical selection | | DateTime | Server component for date formatting | | NumberFormat | Server component for number formatting |

Documentation

Full docs at fluenti.dev.

License

MIT