Body:
Summary
Open-Audit is a public transparency tool — its value proposition is making blockchain data readable to everyone. Ironically, the dashboard itself is not accessible to users who rely on screen readers, keyboard navigation, or high-contrast display modes. Additionally, the UI is English-only with no internationalisation infrastructure, which limits its reach in the non-English-speaking communities most likely to benefit from blockchain transparency tooling.
Part 1 — Accessibility audit and remediation
Run axe-core against every page and remediate all WCAG 2.1 AA violations. Confirmed areas of concern based on the current codebase:
Dashboard event list (components/dashboard/):
Event rows must have role="listitem" inside a role="list" container
Each translated event string must be wrapped in an aria-label that includes the contract ID and ledger number for screen reader context, not just the translated text
Live event updates via WebSocket must be announced via an aria-live="polite" region — currently new events appear silently
The raw XDR toggle must be a proper with aria-expanded and aria-controls, not a
Search input:
Must have a visible (not just placeholder)
Search results count must be announced to screen readers when it changes (e.g. "14 events found")
Theme toggle (components/theme/):
Must communicate current state: aria-pressed="true" when dark mode is active
Must have a visible focus indicator that meets 3:1 contrast ratio
Colour contrast:
Verify all text/background combinations meet 4.5:1 (normal text) and 3:1 (large text/UI components) — especially in dark mode, where shadcn/ui defaults sometimes fall short
Part 2 — i18n scaffolding
Set up next-intl (already compatible with Next.js 14 App Router) and extract all user-facing strings from components/ and app/ into locale message files.
Structure:
messages/
├── en.json # English (source of truth)
└── CONTRIBUTING_TRANSLATIONS.md # Guide for adding a new locale
Scope for this issue — extract and externalise strings from:
components/dashboard/ — column headers, status labels, empty states, error messages
app/dashboard/page.tsx — page title, description
Navigation and layout strings in app/layout.tsx
Do not translate anything beyond English in this issue — the goal is to establish the infrastructure so community members can open PRs adding messages/es.json, messages/fr.json, etc.
Acceptance criteria
axe-core audit of the dashboard returns zero WCAG 2.1 AA violations
All interactive elements are reachable and operable by keyboard alone
New events announced via aria-live region when received via WebSocket
next-intl is installed and configured; messages/en.json contains all user-facing strings from the scoped components
A CONTRIBUTING_TRANSLATIONS.md guide explains how to add a new locale in under 10 steps
Existing Vitest tests pass; add at least 5 new accessibility-specific tests using @testing-library/jest-dom aria matchers
npm run lint passes
Body:
Summary
Open-Audit is a public transparency tool — its value proposition is making blockchain data readable to everyone. Ironically, the dashboard itself is not accessible to users who rely on screen readers, keyboard navigation, or high-contrast display modes. Additionally, the UI is English-only with no internationalisation infrastructure, which limits its reach in the non-English-speaking communities most likely to benefit from blockchain transparency tooling.
Part 1 — Accessibility audit and remediation
Run axe-core against every page and remediate all WCAG 2.1 AA violations. Confirmed areas of concern based on the current codebase:
Dashboard event list (components/dashboard/):
Event rows must have role="listitem" inside a role="list" container
Each translated event string must be wrapped in an aria-label that includes the contract ID and ledger number for screen reader context, not just the translated text
Live event updates via WebSocket must be announced via an aria-live="polite" region — currently new events appear silently
The raw XDR toggle must be a proper with aria-expanded and aria-controls, not a
Search input:
Must have a visible (not just placeholder)
Search results count must be announced to screen readers when it changes (e.g. "14 events found")
Theme toggle (components/theme/):
Must communicate current state: aria-pressed="true" when dark mode is active
Must have a visible focus indicator that meets 3:1 contrast ratio
Colour contrast:
Verify all text/background combinations meet 4.5:1 (normal text) and 3:1 (large text/UI components) — especially in dark mode, where shadcn/ui defaults sometimes fall short
Part 2 — i18n scaffolding
Set up next-intl (already compatible with Next.js 14 App Router) and extract all user-facing strings from components/ and app/ into locale message files.
Structure:
messages/
├── en.json # English (source of truth)
└── CONTRIBUTING_TRANSLATIONS.md # Guide for adding a new locale
Scope for this issue — extract and externalise strings from:
components/dashboard/ — column headers, status labels, empty states, error messages
app/dashboard/page.tsx — page title, description
Navigation and layout strings in app/layout.tsx
Do not translate anything beyond English in this issue — the goal is to establish the infrastructure so community members can open PRs adding messages/es.json, messages/fr.json, etc.
Acceptance criteria
axe-core audit of the dashboard returns zero WCAG 2.1 AA violations
All interactive elements are reachable and operable by keyboard alone
New events announced via aria-live region when received via WebSocket
next-intl is installed and configured; messages/en.json contains all user-facing strings from the scoped components
A CONTRIBUTING_TRANSLATIONS.md guide explains how to add a new locale in under 10 steps
Existing Vitest tests pass; add at least 5 new accessibility-specific tests using @testing-library/jest-dom aria matchers
npm run lint passes