feat(i18n): add language-pack scaffold with English and Spanish

Introduces ``src/i18n`` with a tiny JSON-backed t() lookup, an in-session
language preference, and a sidebar selector wired through
``hide_streamlit_chrome`` so every page picks up the same picker. Covers
home, tool cards, findings panel, gate, shutdown, and pickup banner
strings. Tests pin pack parity and the farewell-overlay JS escape so
future packs can't silently regress.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-13 15:11:30 +00:00
parent 4706ed571e
commit c4ce86bd64
8 changed files with 649 additions and 75 deletions

View File

@@ -26,13 +26,16 @@ from src.gui.components import (
hide_streamlit_chrome,
upload_and_analyze_section,
)
from src.i18n import t
st.set_page_config(
page_title="DataTools — Data Cleaning Mastery",
page_title=t("home.page_title"),
page_icon="🧹",
layout="wide",
)
# ``hide_streamlit_chrome`` also renders the sidebar language selector,
# so every page that hides chrome picks up the same picker.
hide_streamlit_chrome()
@@ -40,8 +43,8 @@ hide_streamlit_chrome()
# Home page
# ---------------------------------------------------------------------------
st.title("🧹 DataTools — Data Cleaning Mastery")
st.caption("A 9-tool suite for cleaning, standardizing, and validating tabular data. Runs 100% locally.")
st.title(t("home.title"))
st.caption(t("home.caption"))
st.divider()
@@ -57,7 +60,7 @@ st.divider()
# Tool cards
# ---------------------------------------------------------------------------
from src.gui.tools_registry import TOOLS
from src.gui.tools_registry import TOOLS, tool_description, tool_name
# Render tool cards in a 3-column grid. Cards picked up by the analyzer get a
# coloured "N findings" badge so the user can see at a glance which tools
@@ -70,15 +73,17 @@ for row_start in range(0, len(TOOLS), 3):
break
tool = TOOLS[idx]
with col:
status_key = "status.ready" if tool.status == "Ready" else "status.coming_soon"
status_color = "green" if tool.status == "Ready" else "orange"
badge = ""
n = findings_count_for_tool(tool.tool_id)
if n:
badge = f" :red-background[**{n} finding{'s' if n != 1 else ''}**]"
badge_key = "home.findings_badge_one" if n == 1 else "home.findings_badge_other"
badge = f" :red-background[**{t(badge_key, n=n)}**]"
st.markdown(
f"### {tool.icon} {tool.name}{badge}\n\n"
f"{tool.description}\n\n"
f":{status_color}[**{tool.status}**]"
f"### {tool.icon} {tool_name(tool.tool_id)}{badge}\n\n"
f"{tool_description(tool.tool_id)}\n\n"
f":{status_color}[**{t(status_key)}**]"
)
@@ -87,7 +92,4 @@ for row_start in range(0, len(TOOLS), 3):
# ---------------------------------------------------------------------------
st.divider()
st.caption(
"Runs locally. Your data never leaves this computer. "
"| DataTools v3.0"
)
st.caption(t("chrome.footer"))