Commit Graph

3 Commits

Author SHA1 Message Date
David Montero Crespo 3b7abfc4f7 feat(editor): account block fuses into the explorer footer
The floating corner box sat ON TOP of the file tree — create enough files
and the last rows scrolled underneath it. The account + language block is
now the explorer panel's footer (VS Code style): the tree scrolls above
it, always. When the explorer is collapsed the block falls back to the
small fixed corner box, so account and language stay reachable.

The standalone language globe becomes a logged-out affordance: once the
pro auth slot renders its signed-in marker (data-auth-user), a :has()
rule hides the globe — signed-in users change language inside the
account menu, where the pro overlay now hosts it.
2026-07-30 20:54:24 +02:00
David Montero Crespo 57d7c93c90 fix(editor): corner-box dropdowns open upward
The language menu and the account menu were written for the top bar and
open downward; from the bottom-left corner box that means straight off
the bottom of the viewport. The language menu flips via a scoped CSS
rule; the account menu (pro) now anchors bottom-up whenever its trigger
sits in the lower half of the screen.
2026-07-30 20:25:52 +02:00
David Montero Crespo cc077c09d1 feat(i18n): react-i18next foundation + 9-locale support for header / footer
This is Phase 1 of multi-language support: the visible chrome (header,
footer, language switcher) and routing are wired up for all 9 locales
(en, es, pt-br, it, fr, zh-cn, de, ja, ru) — same set the blog at
velxio.dev/blog/ already supports. The Editor and the long-form
landing-page copy are still English-only and will be translated in a
follow-up.

Infrastructure
- frontend/src/i18n/config.ts: locale registry + LOCALE_META (htmlLang,
  native name, og locale, dir). Mirrors pro/blog/src/i18n/config.ts so
  cookie sync stays consistent.
- frontend/src/i18n/cookie.ts: read/write the velxio_locale cookie at
  Path=/; Max-Age=1y; SameSite=Lax (Secure on HTTPS). The blog reads
  the same cookie via an inline script in its Layout.astro.
- frontend/src/i18n/path.ts: getLocaleFromPath / stripLocaleFromPath /
  localizedPath / switchLocale / blogUrlFor — match the blog's helpers
  one-to-one.
- frontend/src/i18n/index.ts: i18next bootstrap. English bundle is
  inlined synchronously for first paint; non-default locales are
  lazy-loaded via dynamic import on demand. Initial locale is decided
  in priority order URL > cookie > navigator > en.
- frontend/src/i18n/LocaleSync.tsx: top-level wrapper inside <Router>.
  On every URL change loads the matching locale bundle, calls
  i18n.changeLanguage, writes the cookie, and mirrors the locale onto
  <html lang> and dir.
- frontend/src/i18n/useLocalizedNavigate.ts: useCurrentLocale,
  useLocalizedHref, useLocalizedNavigate hooks for components that
  build internal links.

Routing
- App.tsx: route table extracted to a single ROUTES array, then
  registered twice — once at the root (default English) and once
  nested under each non-default locale (`/<locale>/...`). Explicit
  per-locale parent routes (rather than a generic `:lang` param) so
  React Router never accidentally swallows a real top-level path
  like `/circuit-simulator` as a locale segment.

Header / Footer
- LanguageSwitcher.tsx + .css: dropdown matching the blog's
  LanguageSwitcher.astro. Globe icon + locale code on the trigger,
  native names + ISO codes in the menu. Click → `switchLocale()`
  rewrites the URL under the new locale; LocaleSync handles the
  rest (load bundle, change language, write cookie).
- AppHeader.tsx: every nav label and the auth dropdown copy now
  goes through `t('header.nav.*')`, `t('header.auth.*')`. All
  internal Links wrapped with localize() so navigation stays
  inside the active locale. Added a "Blog" link computed via
  `blogUrlFor(currentLocale)` so /es/ → /blog/es/, etc.
- LandingPage.tsx: footer About-Velxio paragraph reads from
  t('footer.about').

Translations (Phase 1 strings)
- frontend/src/i18n/locales/<locale>/common.json: nav labels, auth
  buttons, footer About copy. Hand-translated for all 9 locales,
  AGPLv3 / brand names preserved as-is.

Tooling
- frontend/scripts/translate-i18n.mjs: standalone Node script that
  takes the en.json bundles and auto-translates them to the 8 other
  locales via DeepSeek (primary) + Gemini (fallback). One LLM call
  per (locale, namespace) pair. Run after extracting new strings
  with `npm run translate:i18n`.

Phase 2 (deferred)
- Editor (toolbar, file explorer, simulator canvas, component picker,
  library manager, error toasts) — hundreds of strings.
- Examples / Docs / About / Profile pages.
- The translate-i18n.mjs script is ready to handle these once the
  strings have been extracted into JSON keys.
2026-05-09 00:40:37 -03:00