Languages
How the site runs in English and Arabic, where every text lives, and what to change to add a language.
The languages that ship
| Language | Address | Direction | Fonts |
|---|---|---|---|
| English, the default | /en | Left to right | DM Sans, with Clash Display for headings |
| Arabic | /ar | Right to left | Noto Sans Arabic, with Almarai for headings |
Every text, button label, image description, form message and page title exists in both languages.
How the language is chosen
- The language is the first part of every address:
/en/pricing,/ar/pricing. - A visitor who opens
/is sent to/arwhen the browser prefers Arabic, and to/enotherwise.src/proxy.tsdoes this. - The language menu in the header switches to the other language and keeps the visitor on the same page.
- Each language has its own title, description and canonical address, and each page tells search engines where the other language is.
Right to left
On /ar, src/app/[locale]/layout.tsx sets lang="ar" and dir="rtl" on the page, so the whole layout mirrors: the menu, the cards, the arrows and the tables read from right to left.
The components use logical Tailwind classes that follow the direction, such as ms-2, pe-4, start-0 and text-start. When you add markup, use these instead of ml-*, pr-*, left-* or text-left, or the Arabic page comes out wrong.
The dashboard preview in the hero keeps a left-to-right layout in both languages, as a real product screenshot would. Its labels are translated.
Where the texts live
The texts are split by page into seven folders under messages/, each with an en.json and an ar.json:
| Folder | What it holds |
|---|---|
messages/home/ | The home page's sections and the dashboard preview |
messages/layout/ | The header, the footer, the error pages and the site's name, title and description |
messages/pricing/ | The pricing page |
messages/blog/ | The blog pages and the posts themselves |
messages/contact/ | The contact page |
messages/auth/ | The sign-in, sign-up and forgot-password pages |
messages/legal/ | The terms, privacy, cookies and GDPR pages |
Change a text
- Change the value in the English file and the matching one in the Arabic file. Keep the keys the same in both.
- A key missing from one file shows its name in place of the text on that language's page.
- Words in curly braces, such as
{year},{count}and{planName}, are filled in by the site. Keep them as they are.
The site's own Arabic labels
When you write about the site in Arabic, use the labels it shows:
| English | Arabic |
|---|---|
Pricing | الأسعار |
Blog | المدونة |
Contact | اتصل بنا |
Sign Up Now | سجّل الآن |
Get Started Free | ابدأ مجانًا |
Most Popular | الأكثر شعبية |
Frequently Asked Questions | الأسئلة الشائعة |
Send Message | إرسال الرسالة |
Sign In | تسجيل الدخول |
Subscribe | اشترك |
Add a language
Add its code to the routing
Add the language code to
localesinsrc/i18n/routing.ts, and toLocale,localesandlocaleNamesinsrc/config/i18n.ts. For example French:src/i18n/routing.tslocales: ["en", "ar", "fr"],Add its message files
In each of the seven folders under
messages/, copyen.jsonunder the new code and translate the values. Keep every key and every word in curly braces. For the home folder:TerminalinNextjs-landing-page-template-2cp messages/home/en.json messages/home/fr.jsonAdd it to the language menu
Add it to the
languageslist insrc/components/LanguageSwitcher.tsx, with the country of the flag it shows, such as{ code: "fr", country: "FR" }.Set its direction and font, if it needs them
Only Arabic is treated as right to left. For another right-to-left language, extend the
locale === "ar"checks insrc/app/[locale]/layout.tsx,src/hooks/locale/useDirection.ts,src/features/home/TestimonialsSection/hooks/useTestimonialsCarousel.tsandsrc/features/auth/forgot-password/components/ForgotPasswordForm/components/BackToSignInLink.tsx. For a script DM Sans does not cover, add a font withnext/fontinlayout.tsx.
Restart yarn dev, or build again, and the new language answers at its own address, here /fr. The canonical links, the language links and the sitemap pick it up by themselves.