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

tyndale-next

v1.1.1

Published

Next.js adapter for Tyndale i18n

Readme

tyndale-next

npm version Build Status TypeScript License

Next.js adapter for Tyndale — locale routing, server-side rendering, and static generation support for the App Router.

Overview

tyndale-next bridges Tyndale's translation runtime with Next.js App Router conventions. It handles:

  • Locale routing — middleware that detects locale from URL, cookie, or Accept-Language, redirects to the correct locale prefix, and normalizes aliases
  • Server-side rendering — a server component that reads locale files from disk before the page renders, eliminating any client-side loading flash
  • Static generation — a helper that reads tyndale.config.json and returns all locale params for generateStaticParams()
  • Text direction — utilities to get ltr/rtl for the current locale, usable in both server and client components

[!NOTE] This package requires tyndale-react for the translation runtime and the tyndale CLI to extract and translate strings.

Installation

npm install tyndale-next
# or
bun add tyndale-next

Peer dependencies: Next.js ≥ 14 and React ≥ 18.

Setup

1. Wrap your Next.js config

// next.config.mjs
import { withTyndaleConfig } from 'tyndale-next/config';

export default withTyndaleConfig({
  // your existing Next.js config
});

withTyndaleConfig reads tyndale.config.json and injects the build-time environment variables the middleware and providers need at runtime. It also aliases tyndale-react so the server and client bundles share a single React context.

2. Add the middleware

// middleware.ts (project root)
import { createTyndaleMiddleware } from 'tyndale-next/middleware';

export default createTyndaleMiddleware();

export const config = {
  matcher: ['/((?!api|_next|_tyndale|.*\\..*).*)'],
};

The middleware handles locale detection (URL → cookie → Accept-Language → default), redirects to locale-prefixed routes, resolves locale aliases, and persists the active locale in a cookie.

3. Add the server provider to your layout

Create an app/[locale]/ directory if you don't have one, and add a layout that wraps children in TyndaleServerProvider:

// app/[locale]/layout.tsx
import { getDirection, TyndaleServerProvider } from 'tyndale-next/server';

export default async function LocaleLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: Promise<{ locale: string }>;
}) {
  const { locale } = await params;

  return (
    <html lang={locale} dir={getDirection(locale)}>
      <body>
        <TyndaleServerProvider locale={locale}>
          {children}
        </TyndaleServerProvider>
      </body>
    </html>
  );
}

TyndaleServerProvider reads the locale JSON file from disk on the server and forwards it to the client provider as initialTranslations, so no fetch is needed on the client.

[!IMPORTANT] TyndaleServerProvider does not set <html dir>. Call getDirection(locale) (server) or useDirection() (client) to get the correct value and set it yourself.

4. Enable static generation (optional)

If you use output: 'export' or want to pre-render all locale pages:

// app/[locale]/page.tsx
import { generateStaticLocaleParams } from 'tyndale-next';

export function generateStaticParams() {
  return generateStaticLocaleParams();
}

This reads tyndale.config.json at build time and returns [{ locale: 'en' }, { locale: 'es' }, ...].

How it works

The three pieces fit together in this order:

  1. Build timewithTyndaleConfig reads tyndale.config.json and bakes defaultLocale, locales, localeAliases, and output into process.env so the middleware and providers can read them without touching the filesystem at runtime on the edge.
  2. Request time — the middleware inspects the incoming URL, cookie, and Accept-Language header, picks the best locale, and either redirects (when no locale prefix is in the URL) or rewrites with an x-tyndale-locale header.
  3. Render timeTyndaleServerProvider runs in a React Server Component, reads the locale JSON directly from the filesystem, and passes translations as props to the client boundary. Components from tyndale-react (<T>, useTranslation(), etc.) receive translations via context and render without a loading state.

API reference

withTyndaleConfig(nextConfig)tyndale-next/config

Wraps a Next.js config object. Reads tyndale.config.json from the project root and sets the environment variables used by the middleware and providers.

createTyndaleMiddleware()tyndale-next/middleware

Returns a Next.js middleware function. Locale detection priority: URL path prefix → cookie → Accept-Language header → default locale.

| Condition | Behavior | |---|---| | No locale prefix in URL | Redirects to /{detectedLocale}/current-path | | URL has alias locale | Redirects to /{canonicalLocale}/rest-of-path | | URL has unsupported locale | Redirects to /{defaultLocale}/rest-of-path | | URL has valid locale | Rewrites, sets x-tyndale-locale header, updates cookie |

TyndaleServerProvidertyndale-next or tyndale-next/server

Server component. Loads locale data from disk and passes it to the client provider.

| Prop | Type | Description | |---|---|---| | locale | string | The active locale code, typically from route params | | children | ReactNode | Page content |

generateStaticLocaleParams()tyndale-next or tyndale-next/server

Returns { locale: string }[] containing the default locale followed by all target locales from tyndale.config.json. Use it as the body of generateStaticParams().

useDirection()tyndale-next

Client hook. Returns 'ltr' or 'rtl' for the locale currently in context.

getDirection(locale)tyndale-next or tyndale-next/server

Server utility. Returns 'ltr' or 'rtl' for any locale string. Use this in server components where hooks are not available.

TyndaleCachetyndale-next

Client component. Memoizes translated content keyed on id and the current locale. Useful in shared layouts to avoid re-rendering expensive translation trees on every navigation.

import { TyndaleCache } from 'tyndale-next';

<TyndaleCache id="footer">
  <T><footer>Large footer content...</footer></T>
</TyndaleCache>

| Prop | Type | Description | |---|---|---| | id | string | Unique key for this cache boundary | | children | ReactNode | Content to memoize |

isRtlLocale(locale) / resolveAlias(locale, aliases) — advanced

Lower-level locale utilities re-exported for custom use cases. isRtlLocale checks a BCP 47 locale string against the internal RTL set. resolveAlias maps a locale code through a Record<string, string> alias map.

Entrypoints

| Import path | What it exports | Notes | |---|---|---| | tyndale-next | TyndaleServerProvider, TyndaleNextClientProvider, generateStaticLocaleParams, useDirection, TyndaleCache, getDirection, isRtlLocale, resolveAlias | Full exports | | tyndale-next/server | TyndaleServerProvider, generateStaticLocaleParams, getDirection, isRtlLocale, resolveAlias | Server-only; safe in RSC without importing React.createContext | | tyndale-next/config | withTyndaleConfig | Used in next.config.* only | | tyndale-next/middleware | createTyndaleMiddleware | Used in middleware.ts only |

Related packages

| Package | Purpose | |---|---| | tyndale | CLI — init, extract, translate, validate, and more | | tyndale-react | React runtime — <T>, useTranslation(), Plural, Num, and more |