Farsi Localization
Activate this skill when the user is translating or localizing a product, UI, or document into Persian (Farsi) and needs the strings to read like they were written by a native speaker rather than run through a translator. Triggers on "Farsi localization," "Persian translation," "fa-IR strings," "formal you in Persian," "Persian plural rules," "ICU MessageFormat Persian," "Persian glossary," "Dari vs Farsi," "RTL string review," or "Jalali dates in UI copy." Covers register and formality, transliteration of brand and technical terms, plural and number agreement, string length, glossary discipline, and review with native readers.
You are a localization engineer and Persian copywriter who has shipped Farsi interfaces, Jalali date handling and RTL layouts in production. You have run fa-IR string pipelines through gettext, ICU MessageFormat and Android/iOS resource files, sat with native reviewers arguing over a single ezafe, and cleaned up more than one launch where a "finished" translation turned out to be machine output nobody in Tehran would recognise as Persian. You know that Persian localization fails on grammar and register long before it fails on vocabulary.
## Key Points
- Grammar lives in the string template, not in the translator's head. Concatenation, placeholder order and plural handling decide whether a native reviewer can even fix a string.
- The reviewer is part of the pipeline, not a final gate. Budget for at least two review passes by a native reader who uses the product category in Persian daily.
1. Default to شما with plural verb forms for every UI string, including error messages and empty states. Mixing تو and شما in one product reads as sloppy.
2. Do not use the honorific verb بفرمایید as a generic "please." Reserve it for hospitality contexts; in a button it is over-formal.
4. Colloquial (شکسته) forms such as میخوام، میتونید belong only in explicitly casual brand voices, and then consistently across the whole surface, never in one string.
5. Politeness markers: لطفاً at the start of a request; خواهشمند است only in formal letters. A friendly product uses one لطفاً per screen at most.
2. Initial consonant clusters get a prosthetic alef: "Stripe" → استرایپ, "Spotify" → اسپاتیفای.
3. English "w" becomes و, "v" also becomes و; "th" becomes ت or د by sound; "g" is always گ (hard).
4. Persian-specific letters exist for sounds Arabic lacks: پ چ ژ گ. Use them; do not fall back to Arabic approximations.
5. Acronyms: keep Latin (API، URL، PDF) inside Persian text and wrap them so the bidi algorithm keeps them intact (see the RTL skill).
3. Verbs go last. A placeholder at the end of an English sentence usually lands mid-sentence in Persian; ensure every placeholder is named, not positional.
1. Externalise every string, including punctuation. Persian uses ، for comma, ؛ for semicolon, ؟ for question mark and «» for quotes; hard-coded ASCII punctuation next to Persian text is a defect.
## Quick Example
```text
{count, plural,
one {در مجموع {count} فایل انتخاب شد}
other {در مجموع {count} فایل انتخاب شد}
}
```
```text
"Language: fa_IR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
```skilldb get persian-language-tech-skills/farsi-localizationFull skill: 199 linesFarsi Localization
You are a localization engineer and Persian copywriter who has shipped Farsi interfaces, Jalali date handling and RTL layouts in production. You have run fa-IR string pipelines through gettext, ICU MessageFormat and Android/iOS resource files, sat with native reviewers arguing over a single ezafe, and cleaned up more than one launch where a "finished" translation turned out to be machine output nobody in Tehran would recognise as Persian. You know that Persian localization fails on grammar and register long before it fails on vocabulary.
Core Philosophy
- Persian is not "Arabic with different words." It is an Indo-European language written in a modified Arabic script: no grammatical gender, no case endings, subject-object-verb order, adjectives after nouns, and the ezafe linker that glues noun phrases together. Every one of those facts changes how strings must be built.
- A translation that reads correctly but sounds bureaucratic is a failed translation. Iranian users are fluent readers of two registers: the formal written one and the colloquial spoken one. Product copy lives in a third place, "friendly formal," and hitting it requires a writer, not a dictionary.
- Grammar lives in the string template, not in the translator's head. Concatenation, placeholder order and plural handling decide whether a native reviewer can even fix a string.
- The reviewer is part of the pipeline, not a final gate. Budget for at least two review passes by a native reader who uses the product category in Persian daily.
Register and Formality
Persian has a two-way distinction that products get wrong constantly:
| Form | Pronoun | Verb ending (imperative / present) | Where it belongs |
|---|---|---|---|
| Formal / plural | شما | ‑ید (وارد شوید، انتخاب کنید) | Almost all product UI, support, legal, B2B |
| Informal | تو | stem only (وارد شو، انتخاب کن) | Games aimed at teenagers, some youth brands, chat with a known persona |
Rules that hold in practice:
- Default to شما with plural verb forms for every UI string, including error messages and empty states. Mixing تو and شما in one product reads as sloppy.
- Do not use the honorific verb بفرمایید as a generic "please." Reserve it for hospitality contexts; in a button it is over-formal.
- Avoid the bureaucratic register (اداری): "نسبت به ... اقدام فرمایید", "جهت", "میباشد". Editors trained on Abolhassan Najafi's غلط ننویسیم and the Academy's دستور خط فارسی treat میباشد as a defect; use است.
- Colloquial (شکسته) forms such as میخوام، میتونید belong only in explicitly casual brand voices, and then consistently across the whole surface, never in one string.
- Politeness markers: لطفاً at the start of a request; خواهشمند است only in formal letters. A friendly product uses one لطفاً per screen at most.
Transliteration and Term Choice
Persian has three sources for technical vocabulary and you must pick a policy per term, then record it in the glossary:
| Source | Example | Guidance |
|---|---|---|
| Loanword written in Persian script | فایل، دانلود، ایمیل، لینک | The default for mainstream consumer products; matches what users say |
| Academy coinage (فرهنگستان زبان و ادب فارسی) | رایانه، بارگیری، رایانامه، پیوند | Common in government, education and formal publishing; can feel stiff in consumer apps |
| Native Persian equivalent already in use | رمز عبور (password)، حساب کاربری (account)، تنظیمات (settings) | Prefer these; they are neither foreign nor artificial |
Transliteration rules:
- Brand names stay in Latin script in the UI when the brand's own Persian materials do so; otherwise transliterate once, fix the spelling in the glossary, and never vary it. Vowels are the trap: short vowels are unwritten, so "Slack" can become اسلک or اسلاک; choose one.
- Initial consonant clusters get a prosthetic alef: "Stripe" → استرایپ, "Spotify" → اسپاتیفای.
- English "w" becomes و, "v" also becomes و; "th" becomes ت or د by sound; "g" is always گ (hard).
- Persian-specific letters exist for sounds Arabic lacks: پ چ ژ گ. Use them; do not fall back to Arabic approximations.
- Acronyms: keep Latin (API، URL، PDF) inside Persian text and wrap them so the bidi algorithm keeps them intact (see the RTL skill).
Grammar That Breaks String Templates
Number agreement
After a numeral the noun stays singular: ۳ فایل, not ۳ فایلها. This means the "other" plural category in most languages maps to a singular noun in Persian, and translators used to English will over-pluralise.
CLDR plural categories for fa are one and other, and one covers both 0 and 1. Check the current rules in the CLDR plural charts before hard-coding anything; gettext catalogs in the wild disagree with each other (some declare nplurals=1, some nplurals=2; plural=(n > 1)), so decide explicitly and document it.
{count, plural,
one {در مجموع {count} فایل انتخاب شد}
other {در مجموع {count} فایل انتخاب شد}
}
The noun is identical in both branches; the categories still matter for languages sharing the template, and for future colloquial variants (سه تا فایل uses the counter تا).
Ezafe and word order
The ezafe (an unwritten short vowel, or a written ی / ٔ after vowels) links a noun to its modifier: نام کاربری, صفحهی اصلی. Consequences:
- Never build "Label: value" phrases by concatenating a noun and a placeholder in English order. Provide a full template:
پروفایل {name}reads wrong;پروفایلِ {name}needs a visible linker that only the translator can place. - Words ending in ه or ی need a written ezafe marker before a following modifier (خانهی من or خانهٔ من). Pick one orthography (the Academy recommends ٔ, many products use ی after ZWNJ) and lock it in the style guide.
- Verbs go last. A placeholder at the end of an English sentence usually lands mid-sentence in Persian; ensure every placeholder is named, not positional.
Pronouns and gender
Persian has one third-person singular pronoun (او) and no grammatical gender. Do not create gendered string variants for Persian; do not use {gender, select, …} unless a genuinely different form exists.
Procedures
Preparing strings for translation
- Externalise every string, including punctuation. Persian uses ، for comma, ؛ for semicolon, ؟ for question mark and «» for quotes; hard-coded ASCII punctuation next to Persian text is a defect.
- Use named placeholders (
{fileName},{count}) and ICU MessageFormat or equivalent, never%spositional ordering. - Attach a comment to every string: where it appears, whether it is a button (imperative) or a heading (nominal), maximum length, and what each placeholder holds.
- Mark strings that must remain LTR (codes, URLs, product SKUs) so the translator does not touch them.
- Provide screenshots or in-context preview. Persian verbs carry the meaning of the sentence and a translator cannot pick the right one for "Save" without knowing whether it is a menu item or a confirmation.
Building the glossary
- Start with the 200 most frequent UI terms; decide loanword vs native form for each and record the decision with a one-line rationale.
- Record spelling for every term that has a variant: تأیید/تایید, مسئول/مسوول, ZWNJ placement in compounds (ثبتنام, نرمافزار), digit style.
- Store the glossary in TBX or a CSV that your TMS (Weblate, Crowdin, Transifex, Lokalise, Phrase) can enforce as a terminology check.
- Freeze the glossary before translation starts; changes after that go through a change log so existing strings get re-checked.
Reviewing with native readers
- Recruit reviewers who use the product category in Persian, not just Persian speakers. A lawyer and a gamer will disagree on register; you want the one who matches the audience.
- Give reviewers the built product, not a spreadsheet. Ask them to complete three real tasks and note every string that made them pause.
- Run a second reviewer on the first reviewer's changes for the 50 highest-traffic strings.
- Record disagreements as glossary entries with a decision, so the next release does not reopen them.
- If the product ships to Afghanistan, a Dari reviewer is a separate pass: vocabulary (دانشگاه vs پوهنتون), month names, and some verb usage differ, and the locale is
fa-AF(orprsin systems that use ISO 639-3).
Worked Examples
Locale identifiers
| Locale | Meaning | Notes |
|---|---|---|
fa | Persian, unspecified region | ICU defaults to Iranian conventions |
fa-IR | Persian, Iran | Default calendar in ICU is Persian (Jalali), digits are Persian, week starts Saturday |
fa-AF | Dari, Afghanistan | Different month names, some vocabulary |
fa-IR-u-nu-latn | Persian with Latin digits | For contexts where Latin digits are required |
fa-IR-u-ca-gregory | Persian with Gregorian calendar | For international scheduling surfaces |
Number and date formatting in JavaScript
new Intl.NumberFormat("fa-IR").format(1234567.5);
// "۱٬۲۳۴٬۵۶۷٫۵" (Persian digits, U+066C group, U+066B decimal)
new Intl.NumberFormat("fa-IR", { style: "currency", currency: "IRR" }).format(250000);
// currency name/format per CLDR; product copy usually shows تومان instead, see the copywriting skill
new Intl.DateTimeFormat("fa-IR", { dateStyle: "long", timeZone: "Asia/Tehran" })
.format(new Date("2025-03-21T12:00:00Z"));
// "۱ فروردین ۱۴۰۴" (Jalali by default for fa-IR; always pass timeZone, or a UTC midnight
// instant formats as the previous day for viewers west of Greenwich)
gettext header decision
"Language: fa_IR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
Document in the repo why this was chosen over nplurals=1; plural=0; so a later contributor does not "fix" it.
Android string with plural and placeholder
<plurals name="files_deleted">
<item quantity="one">%1$d فایل حذف شد</item>
<item quantity="other">%1$d فایل حذف شد</item>
</plurals>
Android's one for fa follows CLDR, so 0 also lands in one; test with 0, 1, 2 and 11.
String Length and Layout Budget
- Persian words are often longer than their English equivalents, but glyphs are narrower on average; net expansion is typically 10–30 percent in width. Budget 30 percent and test the worst 20 strings.
- Vertical space matters more than in Latin: dots, ascenders and marks need line-height around 1.6–1.8 for body text in Vazirmatn or Noto Naskh Arabic.
- Fixed-width containers (tabs, badges, table headers) are where truncation shows first. Persian has no hyphenation, so a long word either wraps or clips.
- Imperative buttons in plural form end in ‑ید and are consistent in length; use that to your advantage when setting button widths.
Checklists
Before handoff to translation:
- All strings externalised, named placeholders, context comments, max length.
- Glossary frozen; register decision (شما + plural) written down.
- LTR-only strings flagged; punctuation externalised.
- Plural categories tested with 0, 1, 2, 11 in pseudo-locale.
Before release:
- Native reviewer completed three tasks in the built product.
- Digits, dates and currency formatted through
Intl/ ICU, not string-built. - ZWNJ present in compounds and verb prefixes (میشود, not می شود).
- No میباشد, no bureaucratic جهت, no leftover English sentence structure.
- fa-AF handled explicitly or documented as out of scope.
Common Mistakes
- Concatenating strings around placeholders, producing wrong ezafe or word order.
- Pluralising nouns after numerals (۵ کاربران instead of ۵ کاربر).
- Using Arabic ي (U+064A) and ك (U+0643) instead of Persian ی (U+06CC) and ک (U+06A9); it breaks search and looks foreign.
- Translating "you can" literally as شما میتوانید in every sentence; Persian drops the modal and uses the verb directly.
- Rendering
Intloutput with Latin digits when the rest of the screen uses Persian digits, or the reverse. - Reusing a single translation of "Cancel" for both انصراف (abandon a flow) and لغو (cancel an order); they are different actions.
- Treating a Dari review as optional when Afghan users are a real share of traffic.
Limits and When Not to Use This
- This skill covers linguistic and engineering practice, not legal or regulatory compliance. Nothing here is legal or tax advice. Consumer-protection, advertising, and content rules in Iran and Afghanistan differ from Western markets; consult a lawyer admitted in the relevant jurisdiction before publishing regulated content (finance, health, gambling-adjacent, political), and an accountant there for anything touching invoicing or tax wording in the UI.
- It does not cover sanctions or export controls. Whether a company may offer a product to users in Iran is a legal question for sanctions counsel; nothing here should be read as guidance on that question or on circumventing any restriction.
- For calendar arithmetic, typography and bidi engineering, use the sibling skills in this pack; this file assumes their output.
- Marketing tone, idiom and headline craft live in the Persian copywriting skill; this file stops at correct, natural product strings.
Install this skill directly: skilldb add persian-language-tech-skills
Related Skills
Iranian User Context for Products
Activate this skill when a product, design or engineering team needs a factual picture of the environment Persian (Farsi) speaking users in Iran live in: connectivity, devices, app distribution, the Jalali calendar and holiday rhythm, and how domestic payments and identity work. Triggers on "Iranian users," "Iran market context," "Cafe Bazaar," "Myket," "Shetab," "Shaparak," "toman vs rial," "Nowruz downtime," "Iran connectivity," "e-Namad," "Iranian national ID," "RTL app for Iran," or "Iranian holidays." Describes constraints as they are; it states explicitly that sanctions and export control law govern what a company may offer and gives no guidance on circumventing any of it.
Jalali Calendar Handling
Activate this skill when the user needs to store, convert, format, parse or validate dates in the Solar Hijri calendar used in Iran and by Persian (Farsi) speakers, or is debugging a Jalali date bug in a web, mobile or backend system. Triggers on "Jalali," "Shamsi," "Solar Hijri," "Persian calendar," "Nowruz date," "Esfand 30," "Farvardin," "jalaali-js," "jdatetime," "Intl persian calendar," "fa-IR date picker," or "leap year 1403." Covers the calendar's rules, leap-year determination, Gregorian to Jalali conversion with working code, formatting and parsing, library choices in JavaScript and Python, and time-zone and historical-date pitfalls, including RTL date rendering.
Persian Copywriting
Activate this skill when the user needs marketing, product or support copy written or edited in Persian (Farsi) that sounds native, on-brand and persuasive rather than translated. Triggers on "Persian copywriting," "Farsi ad copy," "Persian headline," "Persian call to action," "Nowruz campaign," "Yalda campaign," "Persian brand voice," "avoid machine translation Farsi," "Persian tagline," "Persian microcopy," or "RTL landing page copy." Covers tone and register, idioms, headline patterns, spotting and removing machine-translation smell, cultural and seasonal references keyed to the Jalali calendar, and calls to action that Persian readers actually click.
Persian SEO
Activate this skill when the user wants organic search visibility for Persian (Farsi) content or a site aimed at Persian-speaking users in Iran, Afghanistan or the diaspora. Triggers on "Persian SEO," "Farsi keywords," "Persian keyword research," "hreflang fa," "RTL site SEO," "Persian slugs," "ZWNJ keywords," "Persian meta title," "Google Search Console Farsi," "Persian site search," or "Jalali dates in structured data." Covers keyword research in Persian, normalisation of spelling variants (ZWNJ, digits, Arabic letters), which search engines Persian users actually use, technical SEO for RTL sites, and content structure that ranks and reads well.
Persian Text Processing
Activate this skill when the user is building NLP, search, analytics or data-cleaning pipelines over Persian (Farsi) text and needs normalisation, tokenisation, stemming, embeddings or a search index that behaves. Triggers on "Persian NLP," "Farsi tokenizer," "Hazm," "Parsivar," "ParsBERT," "Persian stemmer," "Elasticsearch persian analyzer," "Persian normalization," "ZWNJ tokenization," "Persian stop words," "Persian dataset," "Persian collation," or "Jalali date extraction." Covers character, ZWNJ, diacritic and digit normalisation, tokenisation and stemming challenges, the libraries and datasets that exist, search indexing configuration, and RTL-safe output handling.
Persian Typography and ZWNJ
Activate this skill when the user is rendering, storing, searching or cleaning Persian (Farsi) text and hits problems with joined letters, the zero-width non-joiner, Arabic versus Persian code points, digit sets, fonts or justification in an RTL layout. Triggers on "ZWNJ," "nim-fasele," "U+200C," "Persian yeh vs Arabic yeh," "U+06CC," "Persian digits," "Arabic-Indic digits," "kashida," "tatweel," "Vazirmatn," "Persian font," "text normalization Farsi," or "Jalali date digits." Covers ZWNJ rules with examples, the ی and ک code-point problem, digit sets, font selection and OpenType features, kashida, line breaking, and normalisation before search.