agentsclimarketplace

I18n rtl

Skill Deadlymind/nanolama/skills/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.

Install
npx -y skills add Deadlymind/nanolama --skill i18n-rtl

Assembled 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:

  1. No hardcoded user text. Every visible string comes from t() and exists as a key in messages/fr.json, messages/en.json, and messages/ar.json. A key present in one file but missing in another is a bug (blank UI or a raw key leak).
  2. Direction is data, not layout. Set dir from the locale on <html>; write spacing/alignment with logical classes (ms-, me-, ps-, pe-, text-start, text-end) so the same markup mirrors for ar without 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.json but missing in ar.json renders the raw key or empty text — keep the three files in lockstep; don't let one drift.
  • ml-/mr-/left-/right-/text-left do not flip under dir="rtl"; use the logical ms-/me-/ps-/pe-/text-start/text-end (Tailwind v4 maps these to CSS logical properties). See tailwind-shadcn.
  • Set dir on <html> from the locale, not per-component; icons/chevrons that must point a fixed way get an explicit rtl:rotate-180 or a physical override.
  • Translate the tenant label too — "Entreprise" is the portable example; rename it and its message keys to your own tenant noun.
  • useTranslations runs in client components; use getTranslations in server components/route handlers — don't mix them up.

See also

  • tailwind-shadcn
  • zod-forms
  • nextjs-module

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.