cleanup phase 1
This commit is contained in:
+1
-1
@@ -23,6 +23,6 @@ NEXT_PUBLIC_API_URL = https://localhost:5002
|
||||
|
||||
# Neshan **web** key (client-embeddable maps/search/reverse-geocode) — get one from
|
||||
# https://platform.neshan.org (a separate key from the server's NeshanGeocoder key, which lives in
|
||||
# server appsettings/user-secrets, never here). Leave unset to keep the address map-pin picker's
|
||||
# server appsettings, never here). Leave unset to keep the address map-pin picker's
|
||||
# bounded-canvas grid fallback (dev/CI/jsdom all work without a key).
|
||||
# NEXT_PUBLIC_NESHAN_KEY = your-neshan-web-key
|
||||
+5
-3
@@ -1,10 +1,12 @@
|
||||
# AGENTS.md — Balinyaar Web Client
|
||||
|
||||
The canonical agent guide for the frontend is **[CLAUDE.md](CLAUDE.md)** (same folder). It is the
|
||||
engineering contract: stack, commands, lint/type gates, routing, providers, data fetching, theming,
|
||||
i18n, cookies, and the rules every change must follow.
|
||||
The canonical agent guide for the frontend is **[CLAUDE.md](CLAUDE.md)** (same folder): stack,
|
||||
commands, the quality gates, the project structure, and the hard rules every change must follow.
|
||||
|
||||
- Reference rules, read on demand per area → [../docs/rules/client/](../docs/rules/client/)
|
||||
(structure · theme · components · forms · i18n · services · auth · testing)
|
||||
- Repo-wide context → [../CLAUDE.md](../CLAUDE.md)
|
||||
- Business rules (what to build) → [../product/](../product/index.md)
|
||||
- Human setup/run instructions → [README.md](README.md)
|
||||
- UI/design work → the **frontend-designer** skill
|
||||
|
||||
|
||||
+141
-1062
File diff suppressed because it is too large
Load Diff
@@ -1,116 +0,0 @@
|
||||
# Persian (fa) copy style guide
|
||||
|
||||
One page, binding for `messages/fa.json`. `scripts/check-copy.mjs` (`npm run lint:copy`, part of
|
||||
`npm run check`) enforces the banned-variant rules below so these decisions cannot silently regress.
|
||||
This file does not repeat `en.json` conventions beyond what's noted in §7 — the English catalog is
|
||||
hand-written and reviewed for idiom, not linted.
|
||||
|
||||
## 1. Brand name
|
||||
|
||||
**«بالینیار» — ZWNJ (``) between بالین and یار, always.** Never a plain space («بالین یار»).
|
||||
The brand name appears in money/trust copy (login, escrow, refunds) as often as anywhere else — an
|
||||
unstable brand mark there is the worst place to be inconsistent.
|
||||
|
||||
## 2. تأیید — hamza, always
|
||||
|
||||
Write **تأیید** (with hamza) and its derived forms — **تأییدشده**, **تأییدیه**, **تأیید کردن** — every
|
||||
time, never تایید/تاییدشده/تاییدیه (hamza-less). This is the single most frequent word in a
|
||||
verification product; one spelling, no exceptions, in every namespace (booking, payment, auth,
|
||||
verification, admin, payouts, bnpl, refunds, legal — all of them).
|
||||
|
||||
## 3. جستجو — one form
|
||||
|
||||
Standard form: **جستجو** (no ZWNJ, one word). Not «جستوجو» / «جست و جو». Applies to the noun and any
|
||||
compound (`در جستجو`, `نتایج جستجو`).
|
||||
|
||||
## 4. ZWNJ (نیمفاصله) rules
|
||||
|
||||
Use ZWNJ (``) — never a plain space or no separator — in:
|
||||
- **می + verb stem**: میشود، میکند، میپردازید، میماند (never میشود/می شود).
|
||||
- **Plural ها**: مراقبها-style compounds keep the ZWNJ before ها when the base ends in a consonant that
|
||||
would otherwise misread (`شبها` not `شبها`); a plain plural on a word already ending in a vowel/silent-h
|
||||
takes the ZWNJ too (`بچهها`).
|
||||
- **Compound past-participle adjectives**: تأییدشده، لغوشده، ردشده، منتشرشده، پرداختشده — the doer/state
|
||||
compound is one ZWNJ-joined word, not two spaced words («تایید شده») and not fused with no separator.
|
||||
- Brand name itself (§1) is the other load-bearing ZWNJ case.
|
||||
|
||||
## 5. Punctuation & quotes
|
||||
|
||||
- Persian text uses «...» guillemets for quoted terms/labels in prose (as this document does), and
|
||||
Persian «،» / «؛» for commas/semicolons *inside translated sentences* where the surrounding punctuation
|
||||
is itself Persian prose (most UI strings use plain Latin `,`/`;` today for simplicity in short labels —
|
||||
don't retrofit existing short strings, but prefer «،»/«؛» in new multi-clause sentences).
|
||||
- English (`en.json`) uses **straight** apostrophes (`don't`, `couldn't`) throughout — never curly
|
||||
(`’`, `‘`). One admin-namespace holdout (curly `don't`/`couldn't`) is fixed by this phase; don't
|
||||
reintroduce curly quotes when editing English copy.
|
||||
|
||||
## 6. Domain glossary
|
||||
|
||||
- **بیمار** — the care recipient, used consistently everywhere except one parenthetical. Do not adopt
|
||||
«مددجو» — it appeared exactly once (`booking.patient_label`) and has been dropped in favor of the
|
||||
99%-majority «بیمار».
|
||||
- **پرستار** — the caregiver, always (never «مراقب» as a noun for the person — «مراقب» only survives as
|
||||
an adjective/role qualifier, e.g. `booking.gender_label` "جنسیت مراقب" meaning "the caregiver's gender").
|
||||
- **رزرو** — a confirmed, paid booking. **درخواست رزرو** — a pre-payment request. Never conflate the two;
|
||||
a `booking_request` is never called «رزرو» before it converts.
|
||||
- **ویزیت** — one scheduled visit/session within a booking.
|
||||
- **شبا** — IBAN, always («شماره شبا» for the field label, «شبا» alone elsewhere).
|
||||
|
||||
## 7. Shell naming system
|
||||
|
||||
One metaphor per audience class, not four:
|
||||
- **End-user shells** (family, nurse — the apps people book/work through day to day) → **«اپلیکیشن»**:
|
||||
«اپلیکیشن خانواده», «اپلیکیشن پرستار».
|
||||
- **Back-office shells** (staff consoles — admin, partner-center) → **«کنسول»**: «کنسول مدیریت»,
|
||||
«کنسول همکار».
|
||||
- Never «نما» (view) or «پرتال» (portal) for a whole shell name — those read as one-off inconsistent
|
||||
metaphors. (`booking.evv_nurse_view` "نمای پرستار" is a different thing — a chip labeling *whose
|
||||
perspective* a shared booking-detail screen is rendered from, not a shell name; it correctly keeps
|
||||
«نما» in that narrower sense.)
|
||||
|
||||
## 8. Verification pipeline vs. the identity step
|
||||
|
||||
**«تأیید صلاحیت»** names the whole 7-step nurse trust pipeline (nav entry, the verification hub's title,
|
||||
its start/progress/approved states, the admin queue). **«احراز هویت»** stays the name of the one KYC
|
||||
step inside it (national-ID + civil-registry + liveness selfie) — both on the nurse side
|
||||
(`verification.step_identity_kyc`) and the admin side (`admin.step_identity_kyc`). A nurse who passed the
|
||||
KYC step but still sees a pipeline titled «احراز هویت» incomplete in the nav used to read as a
|
||||
contradiction; they no longer share a name.
|
||||
|
||||
## 9. Status vocabulary — one nurse-facing form, one admin-facing form
|
||||
|
||||
For "this step/item was rejected/failed" style states that appear on both a nurse-facing screen and an
|
||||
admin-facing screen for the *same underlying concept* (a verification step's outcome):
|
||||
- **Nurse-facing**: «رد شد» (`verification.status_failed`) — a short declarative sentence-style status,
|
||||
matching the register of its sibling `status_passed` ("تأییدشده")/`status_in_review` ("در حال بررسی").
|
||||
- **Admin-facing**: «ردشده» (`admin.step_failed`, `admin.agg_rejected`, `admin.rstatus_rejected`,
|
||||
`admin.mstatus_rejected`) — the compound-adjective state form, matching the admin namespace's own
|
||||
`step_passed`/`agg_approved`/`center_state_verified` ("تأییدشده") pattern.
|
||||
|
||||
This does **not** extend to unrelated money-failure vocabulary (`payouts.pstatus_failed`,
|
||||
`refunds.rstatus_failed`, `admin.batch_status_failed` all legitimately use «ناموفق» — a transfer/payment
|
||||
*failing* is a different concept from a document being *rejected*, and conflating them would blur a real
|
||||
distinction).
|
||||
|
||||
## 10. Digits policy
|
||||
|
||||
Persian digits (۰۱۲۳۴۵۶۷۸۹) everywhere on `/fa` — both hard-coded literals (`"۲۴ ساعت"`) and
|
||||
interpolated numbers. For an interpolated `{count}`/`{hours}`/… inside an ICU message, use the ICU
|
||||
`number` sub-format (`{count, number}`) or a plain `#` inside a `plural` block — next-intl formats both
|
||||
through the active locale (`fa` → Persian digits) automatically. When a raw number is interpolated at a
|
||||
call site instead of through ICU (e.g. built into a larger string in code, not a message placeholder),
|
||||
route it through `formatNumber` (`@/utils`) — never template a raw JS number directly into Persian text.
|
||||
|
||||
## 11. Register
|
||||
|
||||
Formal شما throughout, with polite imperatives (کنید) for actions and instructions. Already consistent
|
||||
across the whole catalog — this codifies it so a future addition can't drift into informal تو/imperative
|
||||
stems (نکن, برو).
|
||||
|
||||
## 12. Policy numbers
|
||||
|
||||
Legally/financially sensitive numbers that the admin config panel can change (the dispute-window hours,
|
||||
cancellation lead-time hours, refund ETA days) are **never hard-coded into a message string**. The
|
||||
message key takes a parameter (`{hours}`, `{minDays}`/`{maxDays}`) and the call site interpolates from
|
||||
`client/src/constants/policy.ts` (single-sourced, REQ-065 tracks the eventual public config-read that
|
||||
replaces the constants file). A config edit must never again silently make the UI copy lie.
|
||||
@@ -1,8 +1,11 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Lints client/messages/fa.json against the banned-orthography-variant rules in
|
||||
* client/messages/STYLE.md — enforces the phase-12 sweep so it cannot silently regress.
|
||||
* docs/rules/client/i18n.md §4 — enforces the phase-12 copy sweep so it cannot silently regress.
|
||||
* Exits non-zero (and prints every offending key) on any match.
|
||||
*
|
||||
* The rules below are the machine-checkable subset. The full Persian style guide (glossary, register,
|
||||
* shell naming, the ZWNJ cases a grep can't express) lives in that doc; keep the two in step.
|
||||
*/
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
Reference in New Issue
Block a user