# WP6a — i18n completion, hardcoded-string sweep, RTL audit, known-defect cleanup

**Repo:** FE only — `/home/moonui4/public_html/moon-erp`, branch `hazemdev4`. **Everything you touch lives under `projects/storefront/`.**
**Review:** code-reviewer · **[FIN]:** no · **Migration:** no
**Depends on:** WP0–WP5 (all ✅ and merged). WP6b (distribution/build) runs AFTER you — do not touch `angular.json`, `index.html` fonts, or any build config.

## Goal

The storefront is functionally complete: catalog, cart, auth, COD checkout, order tracking — all verified against the live API, two real orders placed. What is left is the finishing pass: no user-visible string may be hardcoded, English must be complete, direction must be correct in both languages, and three known defects must be closed. After you, the app should be presentable in either language with no raw keys, no Arabic leaking into an English session, and no layout break.

## Verified starting facts (do NOT re-derive; DO report if reality differs)

| Fact | Value |
|---|---|
| i18n files | `projects/storefront/src/assets/i18n/{ar,en}.json` — **418 keys each, already balanced** (no `ar-only` / `en-only`) |
| Source files | 106 `.ts`/`.html` under `projects/storefront/src` |
| Files containing Arabic characters | **22** — *some are legitimately comments*; WP1 claimed only 2 comment-instances existed, so **that number has grown and the growth is the bug you are hunting** |
| Dynamic Tailwind classes (`class` with `${}`) | **0** — the codebase builds whole literal class strings and concatenates with `+` (see `shared/category-tile.component.ts`). Preserve that discipline. |
| Live preview | https://moonui4.elbaset.com/store/ (orchestrator-deployed; **you must not deploy**) |
| Catalog | 1024 products with real images — the storefront now has real data to render |

## The job

### 1. Hardcoded-string sweep (the core of this WP)
Go through all 22 files that contain Arabic characters. For each occurrence decide:
- **A comment** → leave it, but verify it is *actually* a comment and not a string that merely looks like one.
- **A user-visible string** → move it to `ar.json` + `en.json` under the existing `FEATURE_NAME.FIELD` convention and render it through `| translate`.
- **A non-visible literal** (an API value, a status enum, a sort key) → leave it, and add a one-line comment saying why, so the next sweep does not "fix" it.

Do the same sweep for **hardcoded English** user-visible strings — the same defect in the other direction, and it will not show up in an Arabic-character grep. `git grep` for quoted strings inside templates and toast/error calls.

⛔ **Do not invent copy.** If a string needs Arabic that does not exist yet, translate faithfully in Egyptian Arabic matching the tone of the surrounding keys. If you are unsure what a string should say, **flag it in your report** rather than guessing.

### 2. English completeness
`en.json` has the same 418 keys, but **key parity is not translation quality**. Read the English side end to end for: untranslated Arabic left in an English value, placeholder text, and machine-sounding phrasing. Fix what is clearly wrong.

🔴 **`BRAND.NAME` in English is currently `Saydaliyti` — a transliteration a previous agent invented and NOBODY approved.** The owner's decision (OPEN-2) is: use **`صيدليتي`** as the brand everywhere, as an i18n key so it is swappable per client. Make the Arabic side consistent — the auth pages currently say `الصيدلاني` / `صيدليات`, which contradicts the header. **All three must become `صيدليتي`.** Leave the English value as `Saydaliyti` but **flag in your report that it is still unapproved** — do not silently bless it.

### 3. RTL / LTR audit — the T2 trap
This app is Arabic-first and the source theme is **RTL-only**. That means the theme's physical `right` is the inline **start**. WP1 was bitten by this exact trap: it mirrored every mapping and flipped the search button, both badges, the notification dot, three dropdowns and the toast. WP2 was bitten again on the discount badge.

**Audit by measurement, not by eye.** Switch the app to English (LTR) and to Arabic (RTL) and compare rendered geometry. Every absolutely-positioned element, every badge, every dropdown anchor, every icon that implies direction (arrows, chevrons, "back") must be checked. Use the system Chromium at `/usr/bin/chromium-browser` headless against the live preview; **do not run `npx playwright install`** (bundled browsers are root-owned and unreadable).

### 4. Close three known defects (all recorded in LEDGER)

**a) 9px horizontal overflow on mobile — the one that matters.**
All four audited pages have `scrollWidth 399` vs `clientWidth 390` at mobile viewport. Isolated to WP1's language dropdown at `projects/storefront/src/app/layout/top-bar.component.html:37` — `invisible` sets `visibility:hidden`, which still occupies layout on an `absolute` element. Fix with `pointer-events-none` plus a `hidden`/`group-hover:block` swap, or by clipping the container. **Re-measure after the fix and paste the numbers** — a claimed fix without a measurement is not a fix.

**b) `features/smoke/` is unrouted dead code.** Confirmed absent from every bundle. Delete it.

**c) `COMMON.CURRENCY` is a hardcoded `"EGP"`.** Route it through the same i18n key everywhere it is used so a non-Egyptian install is a config change, not a code change. **Do not build a currency-conversion feature** — this is a labelling fix only.

## Constraints — absolute

1. ⛔ **Touch nothing outside `projects/storefront/`.** The admin app (`src/`) and `angular.json` are off-limits — a previous WP proved the admin app untouched with a diff, and that property must hold. WP6b owns build config.
2. ⛔ **Do not push, deploy, run `/fullpush`, or merge to `main`.** Commit on `hazemdev4` and stop.
3. **Bump `I18N_VERSION`** in the storefront's config after ANY edit to `ar.json`/`en.json` — the JSONs are not fingerprinted, so without a bump the browser serves the stale file and every new key renders as its raw path.
4. `src/assets/config.json` is **gitignored and per-instance** — never commit it, never edit it.
5. Preserve the whole-literal-Tailwind-class discipline. A class assembled from a variable does not exist in the compiled CSS.
6. `npx ng build --base-href /store/` must stay green. **The flag is mandatory on every storefront build** — `baseHref` is not pinned yet (WP6b's job); building without it produces `<base href="/">` and a silently blank page.

## Acceptance criteria — paste real output, do not assert

- [ ] Zero user-visible hardcoded strings. Paste the final grep and your per-file classification of all 22 Arabic-containing files (comment / visible-fixed / non-visible-justified).
- [ ] `ar.json` and `en.json` still key-balanced; paste the new count and the `ar-only: []` / `en-only: []` check.
- [ ] Rendered proof of **zero raw keys** (`rawKeys: []`) on every page **in both languages** — the app has 190+ routes' worth of screens; cover home, products, product detail, categories, cart, checkout, order success, order tracking, and all five auth pages.
- [ ] Brand reads `صيدليتي` in all three places; paste the diff.
- [ ] RTL/LTR audit: paste measured geometry for both directions, listing every element checked.
- [ ] Mobile overflow: paste `scrollWidth`/`clientWidth` **before and after** on all four pages.
- [ ] `features/smoke/` deleted; `git grep smoke` clean.
- [ ] `npx ng build --base-href /store/` green; paste bundle size.
- [ ] Admin app provably untouched: `git diff --stat` shows nothing outside `projects/storefront/`.

## Commit
Conventional commit on `hazemdev4`. This IS user-visible (branding, English completeness, a layout fix) → add ONE bilingual bullet to `docs/moonstack/CHANGELOG.md` under `## [Unreleased]` in the **backend** repo at `/home/moonui4/moon-erp-be` (`- **Title.** English {{ar}} **عنوان.** عربي`). That file currently has 14 bullets — **append, never rewrite**, and preserve every existing bullet and all released `## [x.y.z]` sections.

## Report back
Paste actual output for every check. **Flag anything in this brief that turns out to be wrong** — every single work package on this project has found a genuine error in its own brief, including a seeder claimed to seed cities that seeded none, and a "reachable database" that was not reachable by the app user. Be explicit about what you **VERIFIED** versus what you **INFERRED**. If a decision needs the owner (copy nobody approved, a design call the theme does not answer), **stop and flag it** rather than inventing an answer.
