I18n
Internationalization (i18n) and RTL
The app resolves a UI locale for every navigation, wires i18next to that locale, and sets lang / dir on the document root for correct typography and right-to-left layout when needed.
Supported locales
Locales are defined in packages/shared/src/lib/i18n/locale-types.ts. Arabic uses dir="rtl" on <html> (see AppI18nProvider in packages/shared/src/components/app/app-i18n.tsx).
How locale is chosen
Order of resolution (getRequestLocale in packages/server/src/i18n/get-request-locale.ts):
- Cookie
yns_locale(enorar) — set when the user picks a language in the landing header (globe control next to the theme switcher). Accept-Language— if it mentionsar, locale becomes Arabic.- Fallback —
en.
The root route (apps/marketing/src/routes/__root.tsx or apps/web/src/routes/__root.tsx depending on surface) uses createRootRouteWithContext and beforeLoad to call getRequestLocale() and put { locale } on router context. createRouter supplies a default { locale: "en" } for typing and initial state.
After changing the cookie, the UI calls router.invalidate() so beforeLoad runs again and context updates.
Where strings live
- Landing page (namespace
landing):packages/shared/src/lib/i18n/messages/landing.en.tsandlanding.ar.ts, loaded bycreateAppI18n()inpackages/shared/src/lib/i18n/create-app-i18n.ts. - Feature marquee chips (arrays):
packages/shared/src/lib/i18n/landing-chips.ts— typed lists per locale. - FAQ (visible + JSON-LD):
getLandingFaqItems(locale)inpackages/shared/src/lib/landing-faq.ts— keep in sync with the home routehead()(see SEO). - Home meta title/description / og:locale:
getHomeHeadSeoCopy()inpackages/shared/src/lib/i18n/home-seo.ts, used from marketing homehead().
Adding a locale or namespace
- Extend
SUPPORTED_LOCALESandisRtlLocale()if the script direction differs from LTR. - Add message files (mirror
landing.en.ts) and register them inpackages/shared/src/lib/i18n/create-app-i18n.tsresources. - Add labels in
LOCALE_LABELinsidepackages/shared/src/components/app/locale-switcher.tsx. - For any new indexable route, pass
localefromctx.match.contextinhead()the same way as/if you need localized titles,og:locale, or JSON-LD.
Styling notes (RTL)
- Prefer logical utilities where layout mirrors:
ms-*/me-*,ps-*/pe-*,start-*/end-*,text-start/text-end. - Use the
rtl:variant for asymmetric motion (e.g. arrow nudges) and for the landing marquee ([dir="rtl"] .landing-marquee-trackinpackages/shared/src/styles.cssusesanimation-direction: reverse).
Cookie helper
packages/core/src/lib/i18n/cookie.ts — YNS_LOCALE_COOKIE, parseLocaleFromCookieHeader(), setLocaleCookieOnClient().