templates — Bilingual (EN/AR) Prompt Scaffolding
On this page
Rather than writing English prompts and bolting on a "respond in Arabic" instruction, every strategy's persona, section headers, and scaffolding text is natively authored in both English and Modern Standard Arabic (الفصحى). The module docstring states the rationale directly: this keeps reasoning quality consistent across languages, since the model is working from a prompt written for Arabic rather than a translated English one.
Table of contents
Langresolve_lang()/is_supported()persona_line()StrategyTemplateSTRATEGY_TEMPLATES/get_strategy_template()guardrail_text()format_instruction_text()guardrail_header()/output_format_header()
Lang
class Lang(str, Enum):
EN = "en"
AR = "ar"
)
Only two supported native languages exist in this module. Every other requested language falls back to the EN templates plus a plain "Respond in <language>." note appended separately by BaseStrategy._language_line (see strategies).
resolve_lang()
def resolve_lang(language: Optional[str]) -> Lang
None/empty → Lang.EN. Otherwise: Lang.AR if language.strip().lower() is in _ARABIC_ALIASES, else Lang.EN.
_ARABIC_ALIASES = {"ar", "arabic", "arab", "ar-eg", "ar-sa", "ar-ae", "ar_eg", "ar_sa", "msa", "فصحى", "عربي", "العربية", "مصري", "اللغة العربية"} — a fixed set of English and Arabic-script aliases. Regional dialect names beyond Egyptian/Saudi/UAE (e.g. "ar-ma" for Moroccan) are not in this set and will resolve to Lang.EN.
is_supported()
def is_supported(language: Optional[str]) -> bool
True for empty/None, "en"/"english", or anything in _ARABIC_ALIASES; False otherwise. Not called anywhere else in the provided source — appears to be a public utility for callers who want to check support before calling build(), rather than something the library uses internally.
persona_line()
def persona_line(lang: Lang, profile: UserProfile) -> str
Looks up PERSONA_LINES[lang][profile]. Falls back to the Lang.EN sub-dict if lang isn't a key (defensive; in practice lang is always EN or AR). Returns "" if profile isn't found in the sub-dict (defensive; all four UserProfile members are populated for both languages).
StrategyTemplate
@dataclass
class StrategyTemplate:
strategy: PromptStrategy
intro: Dict[Lang, str]
extra: Dict[Lang, List[str]] = field(default_factory=lambda: {Lang.EN: [], Lang.AR: []})
labels: Dict[Lang, Dict[str, str]] = field(default_factory=dict)
blocks: Dict[Lang, Dict[str, str]] = field(default_factory=dict)
The bilingual scaffold for one PromptStrategy. Four accessor methods, all with English fallback:
Seven built-in instances (module-private, _SIMPLE, _COT, _MULTI_HOP, _SELF_CONSISTENT, _STEP_BACK, _REACT, _LEAST_TO_MOST) — one per PromptStrategy member — are defined as module-level constants and collected into STRATEGY_TEMPLATES.
Section labels by strategy (English; Arabic equivalents exist for every one)
Each strategy's _build_user in strategies.md uses exactly these labels via tpl.label(lang, key).
STRATEGY_TEMPLATES / get_strategy_template()
STRATEGY_TEMPLATES: Dict[PromptStrategy, StrategyTemplate] = { ... } # all 7 members
def get_strategy_template(strategy: PromptStrategy) -> StrategyTemplate:
return STRATEGY_TEMPLATES.get(strategy, _SIMPLE)
Never raises; unregistered strategies (not reachable in practice, since all 7 enum members are registered) silently fall back to the Simple template.
guardrail_text()
def guardrail_text(name: str, lang: Lang, fallback: str = "") -> str
Looks up GUARDRAIL_TEXT[name][lang], falling back to GUARDRAIL_TEXT[name][Lang.EN], falling back to fallback if name isn't in the dict at all. GUARDRAIL_TEXT has a natively-authored English and Arabic entry for all 12 GuardrailLibrary names: grounding, uncertainty, no_fabrication, cite_sources, stay_on_topic, no_personal_opinions, safe_output, pii_protection, concise, no_markdown_leakage, show_reasoning, self_check. In practice, fallback (the guardrail's own .instruction from guardrails.py) is only ever used if a custom guardrail added via extra_guardrails has a name that isn't one of these 12 built-ins.
format_instruction_text()
def format_instruction_text(fmt: OutputFormat, lang: Lang) -> Optional[str]
Looks up FORMAT_INSTRUCTIONS_TEXT[fmt][lang], English fallback, or None if fmt has no entry at all. Entries exist (bilingually) for JSON, BULLET_LIST, MARKDOWN, CITATION, STRUCTURED — not for TEXT, matching the same gap noted in guardrails.md.
guardrail_header() / output_format_header()
GUARDRAIL_HEADER = {Lang.EN: "## Instructions & Constraints", Lang.AR: "## التعليمات والقيود"}
OUTPUT_FORMAT_HEADER = {Lang.EN: "\n## Output Format", Lang.AR: "\n## تنسيق الإخراج"}
Simple dict-lookup functions with Lang.EN fallback, used by GuardrailEngine._render.
Examples
1. Basic — resolve a language code
from zerda.prompt.templates import resolve_lang, Lang
assert resolve_lang("AR") == Lang.AR
assert resolve_lang("Arabic") == Lang.AR
assert resolve_lang("fr") == Lang.EN # no native French template
2. Intermediate — get a strategy template
from zerda.prompt.templates import get_strategy_template
from zerda.prompt.types import PromptStrategy
tpl = get_strategy_template(PromptStrategy.CHAIN_OF_THOUGHT)
print(tpl.get_intro(Lang.AR))
3. Advanced — localized guardrail text with fallback
from zerda.prompt.templates import guardrail_text, Lang
text = guardrail_text("grounding", Lang.AR)
text_unknown = guardrail_text("my_custom_guardrail", Lang.EN, fallback="Custom instruction text.")
4. Error handling — there's little to fail; everything degrades to English
tpl = get_strategy_template(None) # falls back to _SIMPLE, no exception
5. Production — building a fully bilingual system prompt manually
from zerda.prompt.templates import resolve_lang, get_strategy_template, persona_line
from zerda.prompt.types import PromptStrategy, UserProfile
lang = resolve_lang("ar")
tpl = get_strategy_template(PromptStrategy.SIMPLE)
system = "\n\n".join(filter(None, [tpl.get_intro(lang), persona_line(lang, UserProfile.ACADEMIC)]))
Related APIs
- strategies — the primary consumer of
StrategyTemplate - guardrails — consumer of
guardrail_text,format_instruction_text, the two header functions - types —
PromptStrategy,OutputFormat,UserProfile