fix(i18n): add missing menu translations and fix admin language resolution

Two issues caused the admin sidebar to show a mix of French and English:

1. Only 3 of 14 modules had "menu" translations in their locale files.
   When a key was missing, _translate_label() fell back to English Title
   Case from the key name — mixing with French from modules that had
   translations. Added menu sections to all 4 languages (en, fr, de, lb)
   across 13 modules.

2. The language middleware hardcoded admin to "en" ignoring user preference,
   while the menu API fell back to DEFAULT_LANGUAGE ("fr") when
   preferred_language was NULL. Fixed middleware to respect user's
   preferred_language and menu API to use middleware-resolved language
   as fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 23:37:13 +01:00
parent faf7047979
commit dad02695f6
54 changed files with 3924 additions and 3549 deletions

View File

@@ -18,7 +18,7 @@ Menu rendering endpoints require authenticated admin/store access.
import logging
from typing import Any
from fastapi import APIRouter, Depends, Path, Query
from fastapi import APIRouter, Depends, Path, Query, Request
from pydantic import BaseModel, Field
from sqlalchemy.orm import Session
@@ -180,6 +180,7 @@ def _build_menu_config_response(
@router.get("/platforms/{platform_id}", response_model=MenuConfigResponse)
async def get_platform_menu_config(
request: Request,
platform_id: int = Path(..., description="Platform ID"),
frontend_type: FrontendType = Query(
FrontendType.ADMIN, description="Frontend type (admin or store)"
@@ -203,8 +204,8 @@ async def get_platform_menu_config(
f"for platform {platform.code} ({frontend_type.value})"
)
# Use user's preferred language, falling back to default
language = current_user.preferred_language or DEFAULT_LANGUAGE
# Use user's preferred language, falling back to middleware-resolved language
language = current_user.preferred_language or getattr(request.state, "language", "en")
return _build_menu_config_response(
items, frontend_type, language=language, platform_id=platform_id
@@ -317,6 +318,7 @@ async def reset_platform_menu_config(
@router.get("/user", response_model=MenuConfigResponse)
async def get_user_menu_config(
request: Request,
db: Session = Depends(get_db),
current_user: UserContext = Depends(get_current_super_admin),
):
@@ -331,8 +333,8 @@ async def get_user_menu_config(
f"[MENU_CONFIG] Super admin {current_user.email} fetched their personal menu config"
)
# Use user's preferred language, falling back to default
language = current_user.preferred_language or DEFAULT_LANGUAGE
# Use user's preferred language, falling back to middleware-resolved language
language = current_user.preferred_language or getattr(request.state, "language", "en")
return _build_menu_config_response(
items, FrontendType.ADMIN, language=language, user_id=current_user.id
@@ -442,6 +444,7 @@ async def show_all_platform_menu_config(
@router.get("/render/admin", response_model=RenderedMenuResponse)
async def get_rendered_admin_menu(
request: Request,
db: Session = Depends(get_db),
current_user: UserContext = Depends(get_current_admin_from_cookie_or_header),
):
@@ -482,8 +485,8 @@ async def get_rendered_admin_menu(
is_super_admin=False,
)
# Use user's preferred language, falling back to default
language = current_user.preferred_language or DEFAULT_LANGUAGE
# Use user's preferred language, falling back to middleware-resolved language
language = current_user.preferred_language or getattr(request.state, "language", "en")
# Translate section and item labels
sections = []