Files
goodgo-platform/docs/architecture/IMPLEMENTATION_QUICK_REFERENCE.md
Ho Ngoc Hai 8039b47795 docs: fix Next.js 14→15 references, add libs READMEs
- Fix remaining "Next.js 14" references in:
  - docs/architecture/IMPLEMENTATION_QUICK_REFERENCE.md
  - docs/load-testing/K6_LOAD_TESTING_GUIDE.md
- Create README.md for libs/ai-services/ (FastAPI AVM, moderation, NLP)
- Create README.md for libs/mcp-servers/ (MCP tool server library)
- Note: CLAUDE.md, README.md, and docs/architecture.md were already
  updated in a prior pass

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-15 11:30:00 +07:00

8.8 KiB

GoodGo Frontend: i18n + A11y Implementation Quick Reference

🎯 Key Findings at a Glance

Current State

  • Next.js 15 with App Router (well-structured)
  • React 18 + TypeScript (type-safe)
  • Tailwind CSS with dark mode support (HSL-based theme)
  • Good component library (~35 components)
  • Some A11y basics in place (semantic HTML, ARIA labels, skip link)
  • NO i18n setup (everything hardcoded Vietnamese)
  • A11y gaps (focus management, some ARIA missing, color contrast TBD)

Strategic Entry Points for Implementation

1. i18n Entry Points (Priority 1)

Files to modify for i18n:
├── app/layout.tsx                    → Add i18n provider
├── middleware.ts                     → Add locale routing
├── app/(public)/layout.tsx           → Navigation text
├── app/(auth)/login/page.tsx         → Form labels + errors
├── app/(auth)/register/page.tsx      → Form labels + errors
├── components/listings/listing-form-steps.tsx → Multi-step form labels
├── components/search/filter-bar.tsx  → Filter options + city names
├── lib/validations/*.ts             → Zod error messages
└── [All other components with text]

Total files to update: ~25-30 files with hardcoded strings

2. A11y Critical Fixes (Priority 1.5)

Components needing A11y updates:
├── components/ui/dialog.tsx         → Focus trapping + focus restoration
├── components/listings/image-gallery.tsx → Keyboard nav + ARIA
├── components/search/filter-bar.tsx  → Proper labeling + ARIA
├── app/(dashboard)/layout.tsx        → Tab focus management
└── Across all forms                 → Error message association

Tasks:
- Add focus trapping in modals
- Verify color contrast (WCAG AA)
- Add aria-busy to loading states
- Add proper aria-label to icon buttons
- Link form errors to inputs with aria-describedby

3. Message File Structure for i18n

public/locales/
├── en.json
│   ├── common: { home, search, dashboard, logout, ... }
│   ├── auth: { login, register, email, password, ... }
│   ├── property: { apartment, house, villa, ... }
│   ├── transaction: { sale, rent, ... }
│   ├── directions: { north, south, east, ... }
│   ├── status: { draft, active, sold, ... }
│   ├── validation: { required, min_length, ... }
│   └── errors: { oauth_failed, access_denied, ... }
└── vi.json
    └── [Same structure]

📋 Implementation Checklist

Phase 1: Setup (2-3 hours)

  • Install next-intl package
  • Create message files (en.json, vi.json)
  • Update next.config.js for i18n routing
  • Create i18n config (config.ts)
  • Update middleware.ts for locale detection
  • Wrap root layout with i18n provider

Phase 2: Core Refactoring (6-8 hours)

  • Update root layout & metadata
  • Refactor all validations (Zod) to use messages
  • Extract component strings to useTranslations()
  • Update all enums (TRANSACTION_TYPES, PROPERTY_TYPES, etc.) to use i18n
  • Update page layouts (public, auth, dashboard)
  • Update all page content

Phase 3: Component Updates (4-6 hours)

  • Update all UI components
  • Update form components
  • Update navigation components
  • Update search/filter components
  • Update listing form

Phase 4: A11y Fixes (4-6 hours)

  • Fix focus management in dialogs
  • Add focus trapping
  • Update form error linking (aria-describedby)
  • Add aria-busy to loading states
  • Add aria-labels to icon buttons
  • Verify color contrast
  • Update test setup for i18n

Phase 5: Testing & QA (3-4 hours)

  • Test both locales on all pages
  • Run axe DevTools accessibility audit
  • Test keyboard navigation
  • Test screen reader compatibility
  • Update unit tests for i18n

🗣️ Text Content Inventory

Navigation & Layout (~15 items)

Location Text Status
Public header Trang chủ, Tìm kiếm, Đăng nhập, Đăng ký Hardcoded
Dashboard nav 8 nav items Hardcoded
Footer 4 sections Hardcoded

Forms & Validation (~40+ items)

Location Type Count Status
Login form Labels + errors 8 Hardcoded
Register form Labels + errors 10 Hardcoded
Listing form Multi-step labels 25+ Hardcoded
Search filters Option labels 30+ Hardcoded
Zod validation Error messages 20+ Hardcoded

Enums & Constants (~50+ items)

File Items Status
TRANSACTION_TYPES 2 labels Hardcoded
PROPERTY_TYPES 6 labels Hardcoded
LISTING_STATUSES 8 labels Hardcoded
DIRECTIONS 8 labels Hardcoded
CITIES 13 names Hardcoded
PRICE_RANGES 6 ranges Hardcoded

Page Content (~30 items)

Page Sections Status
Landing page Hero, search, stats, CTA Hardcoded
Search results No results, loading, headers Hardcoded
Dashboard Section titles, empty states Hardcoded

🔑 Critical Files for i18n

Must-Update Files (Blockers)

  1. middleware.ts — Locale routing
  2. app/layout.tsx — i18n provider setup
  3. lib/validations/*.ts — Message integration
  4. lib/*.ts — Any API error message handling

High-Priority Files

  1. app/(public)/layout.tsx — Navigation
  2. app/(auth)/login/page.tsx — Auth forms
  3. components/listings/listing-form-steps.tsx — Forms
  4. components/search/filter-bar.tsx — Filters

Medium-Priority Files

  1. All page components
  2. All UI components with text
  3. Error boundary components

A11y Implementation Priority

WCAG 2.1 AA Critical Fixes

  1. Focus Management (Level A)

    • Add focus trap in dialog.tsx
    • Restore focus on dialog close
    • Visible focus indicator on all buttons
  2. Color Contrast (Level AA)

    • Run axe DevTools audit
    • Fix any < 4.5:1 ratio text
    • Fix < 3:1 ratio graphics
  3. Form Accessibility (Level A)

    • Link all error messages with aria-describedby
    • Proper labeling with htmlFor
    • Fieldset grouping for complex forms
  4. Loading States (Level A)

    • Add aria-busy to spinners
    • Add aria-label with context
  5. Icon Buttons (Level A)

    • All icon-only buttons need aria-label
    • Theme toggle button already has label ✓

Nice-to-Have A11y Enhancements

  • Skip link already present ✓
  • Semantic HTML already used ✓
  • Role="alert" on errors ✓
  • aria-invalid on form fields ✓

📦 Dependencies to Add

npm install next-intl

# No new devDependencies needed if using next-intl
# Testing with mocked i18n available

Total installation footprint: ~500KB minified


🧪 Testing Strategy

Unit Tests

// vitest.setup.ts - Mock i18n
vi.mock('next-intl', () => ({
  useTranslations: () => (key) => mockMessages[key]
}));

Component Tests

// Test both locales
describe('LoginForm', () => {
  it('renders Vietnamese labels', () => { ... });
  it('renders English labels', () => { ... });
});

E2E Tests

// Test locale switching
- /en/login → English
- /vi/login → Vietnamese
- /en/dashboard → English dashboard

📊 Estimated Timeline

Phase Duration Effort
Setup 2-3h Low
Core Refactoring 6-8h Medium
Components 4-6h Medium
A11y Fixes 4-6h Low-Medium
Testing 3-4h Medium
Total 19-27h ~3-4 days

  1. Setup i18n infrastructure (creates foundation)
  2. Update middleware + root layout (enables routing)
  3. Extract & centralize all text (main work)
  4. Fix A11y issues (parallelize with #3)
  5. Test thoroughly (final verification)

💡 Quick Win Opportunities

These can be done immediately:

  1. Create message file structure (30 min)
  2. Add focus trap to dialog (30 min)
  3. Add aria-busy to spinners (20 min)
  4. Color contrast audit (1 hour)
  5. Icon button aria-labels (30 min)

📝 Notes for Implementation

Locale Detection (middleware)

// Check in order: URL > cookie > header > default
function getLocale(request) {
  // 1. URL pathname: /en/* or /vi/*
  // 2. Cookie: goodgo_locale
  // 3. Header: Accept-Language
  // 4. Default: vi
}

Message Fallback Strategy

// If translation missing, use English as fallback
// Otherwise fallback to Vietnamese (primary)

Performance Considerations

  • Keep message files < 100KB each
  • Lazy load per-page messages if needed
  • Static generation for SEO-critical pages

Last Updated: April 9, 2026
Version: 1.0 - Pre-Implementation
Confidence: High