From 77934201ef3fdc2939c4303d55b6ff468948375c Mon Sep 17 00:00:00 2001 From: Subramaniyajothi6 Date: Wed, 5 Aug 2026 17:22:04 +0530 Subject: [PATCH] Remove the unused i18n layer I18nContext exported useTranslation and t(), but nothing ever called them. The only reference anywhere in the frontend was App.tsx importing I18nProvider to wrap the tree. Every UI string is hardcoded English, only an 'en' locale exists, translations carries just 'common' and 'nav', and setLocale is exposed through context with no UI able to reach it. So the layer is scaffolding for a feature that was never built. Removing it rather than wiring it in: reintroducing i18n properly when localisation is actually planned is easier than maintaining a half-present abstraction that looks supported but is not, and whose presence implies strings are already translatable when they are not. Deletes the context and its test, and unwraps the provider from App.tsx. No other module referenced it, so nothing else changes. Verified: no i18n reference remains anywhere in src, tests, docs or configs; tsc clean; quality gate 13 passed / 0 failed; full vitest 64 files / 566 tests pass -- 9 fewer than main's 575, which is exactly the deleted file. --- frontend/src/App.tsx | 21 ++- frontend/src/components/I18nContext.tsx | 68 ---------- .../unit/components/I18nContext.test.tsx | 126 ------------------ 3 files changed, 9 insertions(+), 206 deletions(-) delete mode 100644 frontend/src/components/I18nContext.tsx delete mode 100644 frontend/testing/unit/components/I18nContext.test.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index fcc003240..b1e2e7306 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -18,7 +18,6 @@ import ProtectedRoute from './components/ProtectedRoute' import { ThemeProvider } from './components/ThemeContext' import { ToastProvider } from './components/ToastContext' -import { I18nProvider } from './components/I18nContext' import { AuthProvider } from './components/AuthContext' import { routes } from './routes' @@ -61,17 +60,15 @@ export function AppRoutes() { export default function App() { return ( - - - - - - - - - - - + + + + + + + + + ) } diff --git a/frontend/src/components/I18nContext.tsx b/frontend/src/components/I18nContext.tsx deleted file mode 100644 index d879669f0..000000000 --- a/frontend/src/components/I18nContext.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React, { createContext, useContext, useState, ReactNode } from 'react'; - -type Translations = { - [key: string]: string | Translations; -}; - -const translations: Translations = { - en: { - common: { - dashboard: 'Dashboard', - scanners: 'Scanners', - history: 'History', - findings: 'Findings', - reports: 'Reports', - settings: 'Settings', - search: 'Search...', - loading: 'Loading system...', - error: 'System Error', - success: 'Operation Successful', - }, - nav: { - monitor: 'Monitor', - analyze: 'Analyze', - execute: 'Execute', - } - } -}; - -interface I18nContextType { - t: (path: string) => string; - locale: string; - setLocale: (locale: string) => void; -} - -const I18nContext = createContext(undefined); - -export function I18nProvider({ children }: { children: ReactNode }) { - const [locale, setLocale] = useState('en'); - - const t = (path: string): string => { - const keys = path.split('.'); - let result: any = translations[locale]; - - for (const key of keys) { - if (result && typeof result === 'object' && key in result) { - result = result[key]; - } else { - return path; - } - } - - return typeof result === 'string' ? result : path; - }; - - return ( - - {children} - - ); -} - -export function useTranslation() { - const context = useContext(I18nContext); - if (!context) { - throw new Error('useTranslation must be used within an I18nProvider'); - } - return context; -} diff --git a/frontend/testing/unit/components/I18nContext.test.tsx b/frontend/testing/unit/components/I18nContext.test.tsx deleted file mode 100644 index 7560d5788..000000000 --- a/frontend/testing/unit/components/I18nContext.test.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import React from 'react'; -import { describe, it, expect, vi } from 'vitest'; -import { render, screen, act } from '@testing-library/react'; -import { I18nProvider, useTranslation } from '../../../src/components/I18nContext'; - -const LocaleDisplay: React.FC = () => { - const { locale } = useTranslation(); - return
{locale}
; -}; - -const TranslationDisplay: React.FC<{ path: string }> = ({ path }) => { - const { t } = useTranslation(); - return
{t(path)}
; -}; - -const LocaleSwitcher: React.FC<{ targetLocale: string }> = ({ targetLocale }) => { - const { locale, setLocale } = useTranslation(); - return ( - <> -
{locale}
- - - ); -}; - -describe('I18nContext', () => { - - it('should default locale to "en"', () => { - render( - - - - ); - expect(screen.getByTestId('locale').textContent).toBe('en'); - }); - - it('should return correct translation for a valid nested key', () => { - render( - - - - ); - expect(screen.getByTestId('translation').textContent).toBe('Dashboard'); - }); - - it('should return the key itself when translation path is not found', () => { - render( - - - - ); - expect(screen.getByTestId('translation').textContent).toBe('common.nonexistent'); - }); - - it('should expose setLocale function in context', () => { - render( - - - - ); - expect(screen.getByRole('button', { name: 'Switch' })).toBeDefined(); - }); - - it('should update locale when setLocale is called', async () => { - render( - - - - ); - expect(screen.getByTestId('locale').textContent).toBe('en'); - await act(async () => { - screen.getByRole('button', { name: 'Switch' }).click(); - }); - expect(screen.getByTestId('locale').textContent).toBe('fr'); - }); - - it('should update locale correctly when switching to Hindi', async () => { - render( - - - - ); - await act(async () => { - screen.getByRole('button', { name: 'Switch' }).click(); - }); - expect(screen.getByTestId('locale').textContent).toBe('hi'); - }); - - it('should fail if provider stops exposing locale as a string', () => { - render( - - - - ); - const localeEl = screen.getByTestId('locale'); - expect(typeof localeEl.textContent).toBe('string'); - expect(localeEl.textContent).toBeTruthy(); - }); - - it('should fail if provider stops exposing t as a function', () => { - let capturedT: ((path: string) => string) | undefined; - const Inspector: React.FC = () => { - const { t } = useTranslation(); - capturedT = t; - return null; - }; - render( - - - - ); - expect(typeof capturedT).toBe('function'); - }); - - it('should throw error when useTranslation is used outside I18nProvider', () => { - const BadComponent: React.FC = () => { - useTranslation(); - return null; - }; - const spy = vi.spyOn(console, 'error').mockImplementation(() => {}); - expect(() => render()).toThrow( - 'useTranslation must be used within an I18nProvider' - ); - spy.mockRestore(); - }); -});