Add catalog EN/AR translations with AI translate-all by locale.

Store product/category translations in entity_translations, expose CMS APIs, and gate the MultiLanguage Data module for businesses.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-09-04 09:51:11 +03:30
co-authored by Cursor
parent 42cf29bc4e
commit d14f91a606
13 changed files with 950 additions and 10 deletions
+13
View File
@@ -167,6 +167,7 @@ Example super admin: `+989121111111` / `password`
| `054_seed_iran_provinces_cities.sql` | Seed Iran provinces + cities when missing (004 seed may never have run) |
| `055_user_products_listing_fields.sql` | User product listing fields: `price_currency`, `delivery_note`, `condition` (`user_product_condition`), `technical_notes` |
| `058_invoice_user_id.sql` | `invoices.user_id` billed user (backfill from business owner) |
| `080_entity_translations.sql` | `entity_translations` for product/category EN+AR (AI or manual) |
Docker mounts `./database/migrations` into Postgres init — migrations run automatically only on **first** volume creation. Use `migrate.sh` for subsequent migrations.
@@ -179,6 +180,9 @@ Docker mounts `./database/migrations` into Postgres init — migrations run auto
| Enum | Values |
|------|--------|
| `MediaEntityType` | `product`, `blog`, `portfolio`, `customer`, `user_product` |
| `TranslationEntityType` | `product`, `category` |
| `TranslationLocale` | `en`, `ar` |
| `TranslationStatus` | `pending`, `ready`, `stale`, `failed` |
| `ContentStatus` | `draft`, `published`, `archived` |
| `VariationType` | `color`, `size`, `custom` |
| `CityLevel` | `country`, `province`, `city`, `district` |
@@ -325,6 +329,10 @@ Pattern: `/businesses/:businessId/<resource>`
| GET | `/categories/color-presets` | Predefined color palette |
| GET/PUT | `/categories/:id/variations` | Category variation options |
| GET/PUT | `/categories/:id/technical-form` | Technical form definition |
| POST | `/categories/translations/ai-all` | Generate missing EN+AR for all product categories (skips existing) |
| GET | `/categories/:id/translations` | EN/AR translations (AI or edited) |
| POST | `/categories/:id/translations/:locale/ai` | Generate EN or AR with AI |
| PUT | `/categories/:id/translations/:locale` | Save edited EN or AR text |
#### Products — notable sub-routes
@@ -333,6 +341,10 @@ Pattern: `/businesses/:businessId/<resource>`
| GET/PUT | `/products/:id/variations` | Which category variation options apply to this product |
| GET/POST/PATCH/DELETE | `/products/:id/variants` | Removed — use `/store-items` |
| GET/PUT | `/products/:id/technical-info` | Product technical data |
| POST | `/products/translations/ai-all` | Generate missing EN+AR for all products (skips existing) |
| GET | `/products/:id/translations` | EN/AR translations (AI or edited) |
| POST | `/products/:id/translations/:locale/ai` | Generate EN or AR with AI |
| PUT | `/products/:id/translations/:locale` | Save edited EN or AR text |
#### My user products (customer — JWT, must be business customer)
@@ -453,6 +465,7 @@ Each resource typically has: `read`, `create`, `update`, `delete` (+ `publish` f
- One category per product (via `CategoryAssignment`)
- Content JSON: `{ nameFa, html }`; metadata JSON: `{ tags }`
- i18n: Persian name in `content.nameFa`, summary in `description`
- Extra locales (EN, AR) in `entity_translations` (globe button in business dashboard; AI first, then optional edit)
### Category variations (product categories)