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 |
|---|---|---|
| English, the default | No prefix: /, /pricing, /contact | Left to right |
| Arabic | /ar, /ar/pricing, /ar/contact | Right to left |
Every text, button label, image description, form message and page title exists in both languages.
How the language is chosen
- English pages have no language in the address; Arabic pages start with
/ar. - A visitor who opens
/with a browser that prefers Arabic is sent to/ar.src/proxy.tsdoes this. - The language menu in the header, and in the menu on phones, switches language and keeps the visitor on the same page. The site remembers the choice for the next visit.
- 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 Arabic pages, src/app/[locale]/layout.tsx sets lang="ar" and dir="rtl" on the page, so the whole layout mirrors: the header, the cards, the dashboard mockup and its 3D tilt, and the forms 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.
A few pieces stay left to right in both languages on purpose: the terminal and the file tree in the feature cards, the charts, and phone numbers on the contact page.
Where the texts live
The texts are split into four folders under messages/, each with an en.json and an ar.json:
| Folder | What it holds |
|---|---|
messages/common/ | The site's name, title and description, the header, the language menu, the copyright line and the buy strip |
messages/home/ | Every section of the home page, the dashboard mockup and the feature cards |
messages/pricing/ | The pricing page |
messages/contact/ | The contact page |
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{name}, 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 |
|---|---|
Features | المميزات |
Pricing | الأسعار |
Contact | تواصل معنا |
Login | تسجيل الدخول |
Book a call | احجز مكالمة |
Get Started | ابدأ الآن |
Learn More | اعرف المزيد |
Monthly | شهري |
Annual | سنوي |
Send Message | إرسال الرسالة |
Add a language
Add its code to the routing
Add the language code to
localesinsrc/i18n/routing.ts. For example French:src/i18n/routing.tslocales: ["en", "ar", "fr"],Add its message files
In each of the four folders under
messages/, copyen.jsonunder the new code and translate the values. Keep every key and every word in curly braces, and setmetadata.ogLocaleinmessages/common/fr.json, such asfr_FR. For the home folder:TerminalinPublino-templatecp messages/home/en.json messages/home/fr.jsonAdd it to the language menus
Give it a flag and a code in
src/components/LanguageSwitcher/index.tsx(flagComponentsandlocaleIsoCodes), and a flag and a name insrc/layouts/Navbar/components/MobileLanguageSwitcher.tsx(flagComponentsandlocaleNames). The flags come fromcountry-flag-icons, such asFR.Set its direction, if it needs it
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/features/home/DashboardMockup/components/index.tsxandsrc/features/home/WhyChooseUs/index.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.