feat: translate all UI strings to English for international release

Complete French→English translation across all frontend pages and backend
services — every label, button, header, empty state, toast, and nav item
is now in English. Build verified clean (tsc + vite). No i18n library
added; direct string replacement throughout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-22 09:06:37 +02:00
parent f8a0a6d023
commit dcbc9f19fc
24 changed files with 1443 additions and 1444 deletions

View File

@@ -99,13 +99,13 @@ def get_portfolio_concentration(open_trades: List[Dict]) -> Dict[str, int]:
def build_portfolio_context_block(open_trades: List[Dict], concentration: Dict[str, int]) -> str:
"""Build a prompt section describing current portfolio for injection into AI prompts."""
if not open_trades:
return "\n## PORTEFEUILLE ACTUEL\nAucun trade en cours — portefeuille vide.\n"
return "\n## CURRENT PORTFOLIO\nNo open trades — empty portfolio.\n"
total = len(open_trades)
conc_sorted = sorted(concentration.items(), key=lambda x: -x[1])
conc_str = " | ".join(f"{cls.upper()}: {n}" for cls, n in conc_sorted)
lines: List[str] = [f"Total: {total} trade(s) ouvert(s) | Concentration: {conc_str}", ""]
lines: List[str] = [f"Total: {total} open trade(s) | Concentration: {conc_str}", ""]
for t in open_trades:
sym = t["underlying"]
@@ -118,27 +118,27 @@ def build_portfolio_context_block(open_trades: List[Dict], concentration: Dict[s
pat = t.get("pattern_name", "")
entry = t.get("entry_price")
cur = t.get("current_price")
ep_str = f"entrée {entry:.2f}actuel {cur:.2f}" if entry and cur else ""
ep_str = f"entry {entry:.2f}current {cur:.2f}" if entry and cur else ""
line = f"{sym} | {strat} [{cls}] | {held}j tenu / {rem}j restants | J-1: {m1d_str} | J-5: {m5d_str}"
line = f"{sym} | {strat} [{cls}] | {held}d held / {rem}d remaining | D-1: {m1d_str} | D-5: {m5d_str}"
if ep_str:
line += f" | {ep_str}"
if pat:
line += f" | thèse: «{pat}»"
line += f" | thesis: «{pat}»"
lines.append(line)
# Identify overweight classes
overweight = [cls for cls, n in conc_sorted if n >= 3]
ow_str = ", ".join(overweight) if overweight else "aucune"
ow_str = ", ".join(overweight) if overweight else "none"
block = (
"\n## PORTEFEUILLE ACTUEL — POSITIONS OUVERTES\n"
"\n## CURRENT PORTFOLIO — OPEN POSITIONS\n"
+ "\n".join(lines)
+ f"\n\nClasses surpondérées (≥3 trades): {ow_str}\n"
+ "\n⚠️ CONSIGNES IMPÉRATIVES (nongociables):\n"
+ "1. NE PAS suggérer un nouveau trade sur un sous-jacent déjà en portefeuille — doublement interdit.\n"
+ "2. Signaler explicitement dans 'rationale' si une suggestion CONTREDIT une position ouverte (signal de clôture potentiel).\n"
+ "3. Éviter d'alourdir une classe surpondérée (≥3 trades) sauf catalyseur exceptionnel justifié.\n"
+ "4. Un signal opposé à une position ouverte = opportunité de SORTIE à documenter, pas d'entrée inversée.\n"
+ f"\n\nOverweight classes (≥3 trades): {ow_str}\n"
+ "\n⚠️ MANDATORY RULES (non-negotiable):\n"
+ "1. DO NOT suggest a new trade on an underlying already in the portfolio — strictly forbidden.\n"
+ "2. Explicitly flag in 'rationale' if a suggestion CONTRADICTS an open position (potential exit signal).\n"
+ "3. Avoid adding to an overweight class (≥3 trades) unless an exceptional justified catalyst exists.\n"
+ "4. A signal opposing an open position = EXIT opportunity to document, not a reverse entry.\n"
)
return block