Remix
ShipEasyI18n integration for Remix — server-side label loading in loader(), useShipEasyI18n() hook in components, and inline data via root loader.
Package: @i18n/remix
Install
npm install @i18n/remix
Root loader — inline label data
Load labels once in the root loader and pass them to the client as inline data. This avoids a separate client fetch on every page:
// app/root.tsx
import { json, type LoaderFunctionArgs } from '@remix-run/node';
import { fetchLabels } from '@i18n/remix/server';
export async function loader({ request }: LoaderFunctionArgs) {
const labels = await fetchLabels({
i18nKey: process.env.ShipEasyI18n_KEY!,
profile: 'en:prod',
chunk: 'index',
});
return json({ i18nData: labels });
}
Then pass the data to the provider in App:
// app/root.tsx (continued)
import { useLoaderData } from '@remix-run/react';
import { ShipEasyI18nProvider } from '@i18n/remix';
export default function App() {
const { i18nData } = useLoaderData<typeof loader>();
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<ShipEasyI18nProvider initialData={i18nData}>
<Outlet />
</ShipEasyI18nProvider>
<Scripts />
</body>
</html>
);
}
Per-route loader() with fetchLabels()
For routes that need a different label chunk:
// app/routes/checkout.tsx
import { json, type LoaderFunctionArgs } from '@remix-run/node';
import { fetchLabels } from '@i18n/remix/server';
export async function loader({ request }: LoaderFunctionArgs) {
const labels = await fetchLabels({
i18nKey: process.env.ShipEasyI18n_KEY!,
profile: 'en:prod',
chunk: 'checkout',
});
return json({ i18nData: labels });
}
useShipEasyI18n() hook in components
// app/components/NavBar.tsx
import { useShipEasyI18n } from '@i18n/remix';
export function NavBar() {
const { t, ready } = useShipEasyI18n();
return (
<nav>
<a href="/" data-label="nav.home">{t('nav.home')}</a>
<a href="/account" data-label="nav.account">{t('nav.account')}</a>
</nav>
);
}
Because Remix runs loaders on every navigation, label data stays fresh without a separate CDN fetch on each route transition.
For the full implementation spec including package source code and edge cases, see plans/frameworks/remix.md in the repository.
React
ShipEasyI18n integration for React 18+ SPAs. ShipEasyI18nProvider, useShipEasyI18n hook, ShipEasyI18nString component. Works with Vite, CRA, and any React setup.
SolidJS
ShipEasyI18n integration for SolidJS — useShipEasyI18n() signal, ShipEasyI18nProvider context, and createStore integration for reactive label state.