I18n rtl
A portable Claude Code skills library (plugin) for a Django 5.2 + Next.js 16 house stack: 30 model-agnostic, tenant-isolation-and-security-first skills.
npx -y skills add Deadlymind/nanolama --skill i18n-rtlAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 21 days oldThe repository was created 21 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Internationalizes a Next.js 16 App Router app with next-intl for fr/en/ar — every user string via t() and present in all three message files, locale routing, and Arabic RTL that mirrors via dir="rtl" plus logical Tailwind classes (ms-/me-, ps-/pe-, text-start) instead of physical left/right. Use when adding a translated string, wiring next-intl routing/middleware, fixing hardcoded text, making a layout mirror for Arabic, or converting ml-/mr-/text-left to logical properties. Not for Zod form schemas and field messages (see zod-forms) or the Tailwind theme and shadcn setup itself (see tailwind-shadcn).
SKILL.md
4.0 KB, as published. Nobody here has run it
i18n and Arabic RTL (next-intl, logical CSS)
When to use
Adding or reviewing any user-facing string, wiring locale routing, or making a
layout mirror correctly for Arabic. On this stack every visible string is
translated in all three locales (fr, en, ar) and every direction-sensitive
style is written in logical properties so dir="rtl" flips it for free.
Pattern
Two invariants, held everywhere:
- No hardcoded user text. Every visible string comes from
t()and exists as a key inmessages/fr.json,messages/en.json, andmessages/ar.json. A key present in one file but missing in another is a bug (blank UI or a raw key leak). - Direction is data, not layout. Set
dirfrom the locale on<html>; write spacing/alignment with logical classes (ms-,me-,ps-,pe-,text-start,text-end) so the same markup mirrors forarwithout RTL-specific CSS.
Route by locale, set dir once in the root layout, and read every string via t():
// app/[locale]/layout.tsx — route by locale, set dir once, provide messages
import { NextIntlClientProvider, hasLocale } from 'next-intl';
import { getMessages } from 'next-intl/server';
import { notFound } from 'next/navigation';
import { routing } from '@/i18n/routing';
export default async function LocaleLayout(
{ children, params }: { children: React.ReactNode; params: Promise<{ locale: string }> },
) {
const { locale } = await params; // Next 16 params are async
if (!hasLocale(routing.locales, locale)) notFound();
const dir = locale === 'ar' ? 'rtl' : 'ltr'; // direction is data, not layout
const messages = await getMessages();
return (
<html lang={locale} dir={dir}>
<body>
<NextIntlClientProvider messages={messages}>{children}</NextIntlClientProvider>
</body>
</html>
);
}
// In components: strings via t(), spacing via LOGICAL classes so ar mirrors for free.
// const t = useTranslations('invoices'); // key must exist in fr.json, en.json, ar.json
// <span className="ms-2 me-4 text-start ps-3">{t('label')}</span> // not ml-/mr-/text-left
Adapt to your repo
Rename the invoices namespace and message keys to your domain. Confirm your locale
set (routing.locales in i18n/routing.ts) and defaultLocale, and that the
[locale] segment plus the next-intl middleware.ts matcher are wired. Add a
CI/lint step that diffs the key sets of fr/en/ar.json so a missing translation
fails the build rather than shipping a blank string.
Gotchas
- A key in
fr.jsonbut missing inar.jsonrenders the raw key or empty text — keep the three files in lockstep; don't let one drift. ml-/mr-/left-/right-/text-leftdo not flip underdir="rtl"; use the logicalms-/me-/ps-/pe-/text-start/text-end(Tailwind v4 maps these to CSS logical properties). Seetailwind-shadcn.- Set
diron<html>from the locale, not per-component; icons/chevrons that must point a fixed way get an explicitrtl:rotate-180or a physical override. - Translate the tenant label too — "Entreprise" is the portable example; rename it and its message keys to your own tenant noun.
useTranslationsruns in client components; usegetTranslationsin server components/route handlers — don't mix them up.
See also
tailwind-shadcnzod-formsnextjs-module