feat(nav,i18n): sticky footer with Back-to-Home + localized tool headers

Two unrelated UX issues addressed in one sweep across all nine tool
pages because they share the same edit surface.

(1) Sticky footer replaces the top + bottom back-link buttons.

Reported: a big white empty footer space at the bottom of every page;
the Back to Home button at the top scrolled out of view on long pages.

New ``render_sticky_footer()`` helper in ``components/_legacy.py``
injects a fixed-position bar at ``bottom: 0`` of the viewport with:

- A border-top so it visually reads as a non-movable bar.
- A semi-transparent background (rgba 0.96 + ``backdrop-filter: blur``)
  so content underneath shows through faintly when the user scrolls.
- A styled ``<a href="home">`` anchor (not an ``st.button``) because
  Streamlit widgets can't be CSS-positioned reliably — Streamlit owns
  the widget's DOM container and re-mounts it on every rerun. A real
  anchor sits exactly where the CSS puts it and triggers Streamlit's
  URL routing to the home page.
- ``padding-bottom: 3.5rem`` on the main container so the last widget
  isn't hidden behind the bar.

Called once per tool page, immediately after ``hide_streamlit_chrome()``
so it renders even on pages that ``st.stop()`` early before any other
content runs. The old top-and-bottom ``back_to_home_link()`` calls are
removed from every tool page; their entry/exit points were dropping
the button when the script short-circuited.

(2) Tool-page headers now localize.

Reported: switching the sidebar language picker to Spanish left the
tool page's title + caption in English. Root cause: every page had
hard-coded ``st.title("✂️ Clean Text")`` / ``st.caption("Trim
whitespace...")`` strings.

Added per-tool ``tools.<id>.page_title`` and
``tools.<id>.page_caption`` keys to ``en.json`` and ``es.json`` for
all nine tools. Routed each page's title/caption call through ``t()``.
Verified: with ``ui_lang=es`` set, the Clean Text page now renders
"✂️ Limpiar texto" + the Spanish caption.

Updated ``tests/gui/test_smoke.py::EXPECTED_SUBSTRINGS`` so the
``es`` column for each tool page asserts the actual Spanish string
(was a duplicate of the English string back when the page bodies
were English-only).

2220 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-17 00:42:45 +00:00
parent 84e4665ab0
commit 7ad19ac7f4
14 changed files with 194 additions and 88 deletions

View File

@@ -106,39 +106,57 @@
"tools": {
"01_deduplicator": {
"name": "Find Duplicates",
"description": "Fuzzy matching, normalization, survivor selection, and interactive review."
"description": "Fuzzy matching, normalization, survivor selection, and interactive review.",
"page_title": "🔍 Find Duplicates",
"page_caption": "Find and remove duplicate rows in CSV, delimited text, and Excel files."
},
"02_text_cleaner": {
"name": "Clean Text",
"description": "Whitespace trim, multi-space collapse, Unicode normalization, BOM and line-ending handling."
"description": "Whitespace trim, multi-space collapse, Unicode normalization, BOM and line-ending handling.",
"page_title": "✂️ Clean Text",
"page_caption": "Trim whitespace, fold smart quotes, strip invisible characters, and normalize line endings. Runs locally — your data never leaves this computer."
},
"03_format_standardizer": {
"name": "Standardize Formats",
"description": "Standardize dates, currencies, names, phone numbers, and addresses."
"description": "Standardize dates, currencies, names, phone numbers, and addresses.",
"page_title": "📐 Standardize Formats",
"page_caption": "Canonicalize dates, phone numbers, currency, names, addresses, and booleans on a per-column basis. Runs locally — your data never leaves this computer."
},
"04_missing_handler": {
"name": "Fix Missing Values",
"description": "Detect disguised nulls, missingness analysis, and imputation strategies."
"description": "Detect disguised nulls, missingness analysis, and imputation strategies.",
"page_title": "🕳️ Fix Missing Values",
"page_caption": "Detect disguised nulls, profile missingness, and apply imputation or drop strategies. Runs locally — your data never leaves this computer."
},
"05_column_mapper": {
"name": "Map Columns",
"description": "Rename columns, enforce a target schema, and coerce types."
"description": "Rename columns, enforce a target schema, and coerce types.",
"page_title": "🗂️ Map Columns",
"page_caption": "Rename columns, enforce a target schema, and coerce types. Runs locally — your data never leaves this computer."
},
"06_outlier_detector": {
"name": "Find Unusual Values",
"description": "Z-score, IQR, and MAD detection with domain-rule violations and winsorization."
"description": "Z-score, IQR, and MAD detection with domain-rule violations and winsorization.",
"page_title": "📊 Find Unusual Values",
"page_caption": "Detect and handle outliers in numeric columns."
},
"07_multi_file_merger": {
"name": "Combine Files",
"description": "Combine multiple CSV/Excel files with schema alignment."
"description": "Combine multiple CSV/Excel files with schema alignment.",
"page_title": "📎 Combine Files",
"page_caption": "Combine multiple CSV and Excel files into one dataset."
},
"08_validator_reporter": {
"name": "Quality Check",
"description": "Validate against rules and generate PDF/Excel quality reports."
"description": "Validate against rules and generate PDF/Excel quality reports.",
"page_title": "✅ Quality Check",
"page_caption": "Validate data against rules and generate quality reports."
},
"09_pipeline_runner": {
"name": "Automated Workflows",
"description": "Chain tools in recommended order and pass output between steps."
"description": "Chain tools in recommended order and pass output between steps.",
"page_title": "⚙️ Automated Workflows",
"page_caption": "Chain DataTools cleaning steps into one repeatable workflow. The pipeline recommends an order; you stay in control."
}
},
"nav": {