fix(storefront): i18n sweep + locale-aware reset-password and welcome email
Some checks failed
Some checks failed
Test 5 (storefront password reset + customer dashboard) surfaced five
issues that all traced back to missing i18n plumbing:
- Forgot-password email arrived in EN regardless of storefront locale —
handler now prefers request.state.language over customer.preferred_language,
and loyalty self-enrollment backfills preferred_language for new + returning
customers so future locale-sensitive flows hit the right language without
being told twice.
- reset-password.html rendered "undefined" icon boxes because $icon magic
wasn't loaded in the standalone page — replaced with inline SVGs matching
the forgot-password.html convention.
- reset-password.html was hardcoded English: added lang attr, full _()
sweep (22 new auth.* keys × 4 locales), language selector, and JS
validation strings exposed via tojson.
- "Continue shopping" CTA renamed to "Back to Home" (auth.back_to_home,
4 locales) on login + forgot + reset — loyalty storefronts have no
catalog to continue to, mirroring the earlier enroll-success rename.
- /account dashboard, profile, addresses were hardcoded English in the
body (menu was FR because base layout uses _()). New customers.storefront
.pages.{dashboard,profile,addresses}.* namespace (~80 keys × 4 locales),
templates updated, Alpine JS strings injected via window.__*I18n.
18 files, 18 changed; arch validation: 126 warnings before = 126 after,
mkdocs --strict clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -94,6 +94,7 @@ def self_enroll(
|
||||
customer_name=data.customer_name,
|
||||
customer_phone=data.customer_phone,
|
||||
customer_birthday=data.customer_birthday,
|
||||
customer_language=getattr(request.state, "language", None),
|
||||
)
|
||||
|
||||
logger.info(f"Self-enrollment for customer {customer_id} at store {store.subdomain}")
|
||||
|
||||
@@ -188,6 +188,7 @@ class CardService:
|
||||
customer_name: str | None = None,
|
||||
customer_phone: str | None = None,
|
||||
customer_birthday: date | None = None,
|
||||
customer_language: str | None = None,
|
||||
) -> int:
|
||||
"""
|
||||
Resolve a customer ID from either a direct ID or email lookup.
|
||||
@@ -224,11 +225,18 @@ class CardService:
|
||||
|
||||
customer = customer_service.get_customer_by_email(db, store_id, email)
|
||||
if customer:
|
||||
# Backfill birthday on existing customer if they didn't have
|
||||
# one before — keeps the enrollment form useful for returning
|
||||
# customers who never previously provided a birthday.
|
||||
# Backfill birthday + preferred_language on existing customer
|
||||
# if they were missing — keeps the enrollment form useful for
|
||||
# returning customers and lets transactional emails (welcome,
|
||||
# password reset) hit the right locale.
|
||||
dirty = False
|
||||
if customer_birthday and not customer.birth_date:
|
||||
customer.birth_date = customer_birthday
|
||||
dirty = True
|
||||
if customer_language and not customer.preferred_language:
|
||||
customer.preferred_language = customer_language
|
||||
dirty = True
|
||||
if dirty:
|
||||
db.flush()
|
||||
return customer.id
|
||||
|
||||
@@ -250,8 +258,17 @@ class CardService:
|
||||
.first()
|
||||
)
|
||||
if existing_cardholder:
|
||||
dirty = False
|
||||
if customer_birthday and not existing_cardholder.birth_date:
|
||||
existing_cardholder.birth_date = customer_birthday
|
||||
dirty = True
|
||||
if (
|
||||
customer_language
|
||||
and not existing_cardholder.preferred_language
|
||||
):
|
||||
existing_cardholder.preferred_language = customer_language
|
||||
dirty = True
|
||||
if dirty:
|
||||
db.flush()
|
||||
return existing_cardholder.id
|
||||
|
||||
@@ -272,6 +289,7 @@ class CardService:
|
||||
last_name=last_name,
|
||||
phone=customer_phone,
|
||||
birth_date=customer_birthday,
|
||||
preferred_language=customer_language,
|
||||
)
|
||||
logger.info(
|
||||
f"Created customer {customer.id} ({email}) "
|
||||
|
||||
Reference in New Issue
Block a user