From 81a77d7a44f861a47b6083dd257a6c2f1241c3f4 Mon Sep 17 00:00:00 2001 From: Muhammad Fadhil Date: Thu, 28 May 2026 20:33:34 +0700 Subject: [PATCH 1/3] refactor(web): centralize i18n translations --- apps/web/src/hooks/use-language.ts | 2 +- apps/web/src/lib/{i18n.ts => i18n/index.ts} | 9 ++------- apps/web/src/lib/i18n/react-i18next.d.ts | 7 +++++++ apps/web/src/lib/i18n/resources.ts | 11 +++++++++++ apps/web/src/tests/setup.ts | 6 +++--- .../{locales/en/common.json => translations/en.json} | 0 .../{locales/id/common.json => translations/id.json} | 0 7 files changed, 24 insertions(+), 11 deletions(-) rename apps/web/src/lib/{i18n.ts => i18n/index.ts} (67%) create mode 100644 apps/web/src/lib/i18n/react-i18next.d.ts create mode 100644 apps/web/src/lib/i18n/resources.ts rename apps/web/src/{locales/en/common.json => translations/en.json} (100%) rename apps/web/src/{locales/id/common.json => translations/id.json} (100%) diff --git a/apps/web/src/hooks/use-language.ts b/apps/web/src/hooks/use-language.ts index 7d830fc..2705f82 100644 --- a/apps/web/src/hooks/use-language.ts +++ b/apps/web/src/hooks/use-language.ts @@ -5,7 +5,7 @@ const LANGUAGES = ['en', 'id'] as const; export type Language = (typeof LANGUAGES)[number]; export function useLanguage() { - const { i18n } = useTranslation('common'); + const { i18n } = useTranslation(); const current = LANGUAGES.find((l) => i18n.language.startsWith(l)) ?? 'en'; const next = current === 'en' ? 'id' : 'en'; diff --git a/apps/web/src/lib/i18n.ts b/apps/web/src/lib/i18n/index.ts similarity index 67% rename from apps/web/src/lib/i18n.ts rename to apps/web/src/lib/i18n/index.ts index 447af16..cb81ee7 100644 --- a/apps/web/src/lib/i18n.ts +++ b/apps/web/src/lib/i18n/index.ts @@ -2,20 +2,15 @@ import i18n from 'i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; import { initReactI18next } from 'react-i18next'; -import enCommon from '@/locales/en/common.json'; -import idCommon from '@/locales/id/common.json'; +import { resources } from './resources'; i18n .use(initReactI18next) .use(LanguageDetector) .init({ - resources: { - en: { common: enCommon }, - id: { common: idCommon } - }, + resources, fallbackLng: 'en', supportedLngs: ['en', 'id'], - defaultNS: 'common', interpolation: { escapeValue: false }, diff --git a/apps/web/src/lib/i18n/react-i18next.d.ts b/apps/web/src/lib/i18n/react-i18next.d.ts new file mode 100644 index 0000000..e220b83 --- /dev/null +++ b/apps/web/src/lib/i18n/react-i18next.d.ts @@ -0,0 +1,7 @@ +import type { resources } from './resources'; + +declare module 'react-i18next' { + type CustomTypeOptions = { + resources: (typeof resources)['en']; + }; +} diff --git a/apps/web/src/lib/i18n/resources.ts b/apps/web/src/lib/i18n/resources.ts new file mode 100644 index 0000000..2a35a18 --- /dev/null +++ b/apps/web/src/lib/i18n/resources.ts @@ -0,0 +1,11 @@ +import en from '@/translations/en.json'; +import id from '@/translations/id.json'; + +export const resources = { + en: { + translation: en + }, + id: { + translation: id + } +}; diff --git a/apps/web/src/tests/setup.ts b/apps/web/src/tests/setup.ts index 5340d52..94967be 100644 --- a/apps/web/src/tests/setup.ts +++ b/apps/web/src/tests/setup.ts @@ -14,20 +14,20 @@ Object.defineProperty(window, 'matchMedia', { dispatchEvent: () => false }) }); + import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import { afterAll, afterEach, beforeAll } from 'vitest'; -import enCommon from '@/locales/en/common.json'; +import en from '@/translations/en.json'; import { server } from './mocks/server'; // init i18n for tests with English only i18n.use(initReactI18next).init({ - resources: { en: { common: enCommon } }, + resources: { en: { translation: en } }, lng: 'en', fallbackLng: 'en', - defaultNS: 'common', interpolation: { escapeValue: false } }); diff --git a/apps/web/src/locales/en/common.json b/apps/web/src/translations/en.json similarity index 100% rename from apps/web/src/locales/en/common.json rename to apps/web/src/translations/en.json diff --git a/apps/web/src/locales/id/common.json b/apps/web/src/translations/id.json similarity index 100% rename from apps/web/src/locales/id/common.json rename to apps/web/src/translations/id.json From 99586adb5c57b9fc687f8ec5872e8f0de52f613d Mon Sep 17 00:00:00 2001 From: Muhammad Fadhil Date: Thu, 28 May 2026 20:37:07 +0700 Subject: [PATCH 2/3] refactor(web): remove i18n namespace --- apps/web/src/components/common/error.tsx | 2 +- apps/web/src/components/common/not-found.tsx | 2 +- apps/web/src/components/common/user-menu.tsx | 2 +- apps/web/src/components/layouts/demo-banner.tsx | 2 +- apps/web/src/components/layouts/header.tsx | 2 +- apps/web/src/components/layouts/reader.tsx | 2 +- apps/web/src/components/navigation/mobile-header-nav.tsx | 2 +- apps/web/src/components/navigation/reader-nav.tsx | 2 +- apps/web/src/components/ui/spinner.tsx | 2 +- apps/web/src/components/ui/tag-input.tsx | 2 +- .../features/articles/components/add-article-dialog.tsx | 2 +- .../web/src/features/articles/components/article-card.tsx | 8 ++++---- .../src/features/articles/components/articles-toolbar.tsx | 2 +- .../src/features/articles/components/edit-tags-dialog.tsx | 2 +- apps/web/src/features/articles/components/empty-state.tsx | 2 +- .../src/features/articles/components/filter-sidebar.tsx | 2 +- apps/web/src/features/auth/components/brand-panel.tsx | 2 +- apps/web/src/features/auth/components/login-form.tsx | 2 +- apps/web/src/features/auth/components/register-form.tsx | 2 +- .../features/home/components/continue-reading-section.tsx | 2 +- .../features/home/components/onboarding-progress-card.tsx | 2 +- apps/web/src/features/home/components/quick-add-bar.tsx | 2 +- .../features/home/components/recently-saved-section.tsx | 2 +- .../src/features/home/components/suggestions-section.tsx | 2 +- .../import-articles/api/get-links-from-session.ts | 2 +- .../import-articles/components/extraction-progress.tsx | 2 +- .../import-articles/components/extraction-status-card.tsx | 2 +- .../import-articles/components/import-progress.tsx | 2 +- .../features/import-articles/components/map-fields.tsx | 2 +- .../features/import-articles/components/review-import.tsx | 2 +- .../import-articles/components/upload-from-csv.tsx | 2 +- .../import-articles/components/wizard-step-indicator.tsx | 2 +- .../reader/components/floating-progress-indicator.tsx | 2 +- .../reader/components/highlighter/manage-highlight.tsx | 2 +- .../reader/components/highlighter/use-highlighter.tsx | 2 +- apps/web/src/features/reader/components/note-card.tsx | 2 +- .../features/reader/components/resume-position-banner.tsx | 2 +- .../src/features/settings/components/account-section.tsx | 2 +- .../web/src/features/settings/components/data-section.tsx | 2 +- .../src/features/settings/components/language-section.tsx | 2 +- .../settings/components/reader-preferences-section.tsx | 2 +- .../src/features/settings/components/security-section.tsx | 2 +- .../tags/components/delete-confirmation-dialog.tsx | 2 +- .../web/src/features/tags/components/group-tags-sheet.tsx | 2 +- .../web/src/features/tags/components/move-tags-dialog.tsx | 2 +- apps/web/src/features/tags/components/tag-form-dialog.tsx | 2 +- apps/web/src/features/tags/components/tag-group-card.tsx | 2 +- .../features/tags/components/tag-group-form-dialog.tsx | 2 +- apps/web/src/features/tags/hooks/use-tags-actions.ts | 2 +- apps/web/src/pages/article-reader.tsx | 2 +- apps/web/src/pages/articles.tsx | 2 +- apps/web/src/pages/home.tsx | 2 +- apps/web/src/pages/import-articles.tsx | 2 +- apps/web/src/pages/import-progress.tsx | 2 +- apps/web/src/pages/manage-tags.tsx | 2 +- apps/web/src/pages/register.tsx | 2 +- apps/web/src/pages/settings.tsx | 2 +- 57 files changed, 60 insertions(+), 60 deletions(-) diff --git a/apps/web/src/components/common/error.tsx b/apps/web/src/components/common/error.tsx index 898eb2e..588353d 100644 --- a/apps/web/src/components/common/error.tsx +++ b/apps/web/src/components/common/error.tsx @@ -2,7 +2,7 @@ import { useRouter } from '@tanstack/react-router'; import { useTranslation } from 'react-i18next'; export function ErrorFallback({ error }: { error: Error }) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const router = useRouter(); return ( diff --git a/apps/web/src/components/common/not-found.tsx b/apps/web/src/components/common/not-found.tsx index 1d4c5c8..aca928a 100644 --- a/apps/web/src/components/common/not-found.tsx +++ b/apps/web/src/components/common/not-found.tsx @@ -2,7 +2,7 @@ import { useRouter } from '@tanstack/react-router'; import { useTranslation } from 'react-i18next'; export function NotFound() { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const router = useRouter(); return ( diff --git a/apps/web/src/components/common/user-menu.tsx b/apps/web/src/components/common/user-menu.tsx index a0f6ab1..38ed81a 100644 --- a/apps/web/src/components/common/user-menu.tsx +++ b/apps/web/src/components/common/user-menu.tsx @@ -56,7 +56,7 @@ function getInitials(name: string): string { } export function UserMenu({ align = 'end', contentClassName, trigger }: UserMenuProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const { data: user } = useGetUser(); const { setTheme, theme } = useTheme(); const navigate = useNavigate(); diff --git a/apps/web/src/components/layouts/demo-banner.tsx b/apps/web/src/components/layouts/demo-banner.tsx index 0f5bd1c..92e45e3 100644 --- a/apps/web/src/components/layouts/demo-banner.tsx +++ b/apps/web/src/components/layouts/demo-banner.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'; import { env } from '@/lib/env'; export function DemoModeBanner() { - const { t } = useTranslation('common'); + const { t } = useTranslation(); if (!env.isDemo) return null; diff --git a/apps/web/src/components/layouts/header.tsx b/apps/web/src/components/layouts/header.tsx index 5f67602..b74d40a 100644 --- a/apps/web/src/components/layouts/header.tsx +++ b/apps/web/src/components/layouts/header.tsx @@ -8,7 +8,7 @@ import { UserMenu } from '../common/user-menu'; export function Header() { const { pathname } = useLocation(); - const { t } = useTranslation('common'); + const { t } = useTranslation(); return (
diff --git a/apps/web/src/components/layouts/reader.tsx b/apps/web/src/components/layouts/reader.tsx index 1a46c87..ea9a9e6 100644 --- a/apps/web/src/components/layouts/reader.tsx +++ b/apps/web/src/components/layouts/reader.tsx @@ -23,7 +23,7 @@ function ReaderLayout({ onUpdateHighlight, onRemoveHighlight }: ReaderLayoutProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const id = useParams({ from: '/_protected/articles/$id' }).id; const { selectedHighlightId, setSelectedHighlightId, showHighlights, toggleShowHighlights } = useHighlights(); diff --git a/apps/web/src/components/navigation/mobile-header-nav.tsx b/apps/web/src/components/navigation/mobile-header-nav.tsx index 489cd42..e71fe65 100644 --- a/apps/web/src/components/navigation/mobile-header-nav.tsx +++ b/apps/web/src/components/navigation/mobile-header-nav.tsx @@ -5,7 +5,7 @@ import { UserMenu } from '../common/user-menu'; import { Button } from '../ui/button'; export function MobileHeaderNav() { - const { t } = useTranslation('common'); + const { t } = useTranslation(); return (
diff --git a/apps/web/src/components/navigation/reader-nav.tsx b/apps/web/src/components/navigation/reader-nav.tsx index 9816b94..5d858b2 100644 --- a/apps/web/src/components/navigation/reader-nav.tsx +++ b/apps/web/src/components/navigation/reader-nav.tsx @@ -86,7 +86,7 @@ function getFontFamilyLocaleKey(value: string) { function ReaderNav({ linkId, onOpenHighlights }: ReaderNavProps) { const navigate = useNavigate(); - const { t } = useTranslation('common'); + const { t } = useTranslation(); const linkQuery = useGetLink({ linkId }); diff --git a/apps/web/src/components/ui/spinner.tsx b/apps/web/src/components/ui/spinner.tsx index 6ac98ff..e5d04e8 100644 --- a/apps/web/src/components/ui/spinner.tsx +++ b/apps/web/src/components/ui/spinner.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'; import { cn } from '@/lib/utils'; function Spinner({ className, ...props }: React.ComponentProps<'svg'>) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); return ( ( }, [groupedTags, inputValue]); const isMaxReached = maxTags ? value.length >= maxTags : false; - const { t } = useTranslation('common'); + const { t } = useTranslation(); const addTag = useCallback( (tag: Tag) => { diff --git a/apps/web/src/features/articles/components/add-article-dialog.tsx b/apps/web/src/features/articles/components/add-article-dialog.tsx index c3c4d77..c42a080 100644 --- a/apps/web/src/features/articles/components/add-article-dialog.tsx +++ b/apps/web/src/features/articles/components/add-article-dialog.tsx @@ -49,7 +49,7 @@ export function AddArticleDialog({ tags }: Props) { const position = isMobile ? 'top-center' : 'top-right'; - const { t } = useTranslation('common'); + const { t } = useTranslation(); const createLinkMutation = useCreateLink({ mutationConfig: { diff --git a/apps/web/src/features/articles/components/article-card.tsx b/apps/web/src/features/articles/components/article-card.tsx index ac2a17c..cb4e37b 100644 --- a/apps/web/src/features/articles/components/article-card.tsx +++ b/apps/web/src/features/articles/components/article-card.tsx @@ -138,7 +138,7 @@ function ArticleDropdownMenu({ link, onEditTagsOpen }: ArticleDropdownMenuProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const { id, isArchived, priority } = link; return ( @@ -228,7 +228,7 @@ function GridCard({ link, tagGroups }: ArticleCardProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const { coverImage, excerpt, @@ -478,7 +478,7 @@ function ListCardCompact({ link, tagGroups }: ArticleCardProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const { coverImage, excerpt, @@ -696,7 +696,7 @@ function ListCardDesktop({ link, tagGroups }: ArticleCardProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const { coverImage, excerpt, diff --git a/apps/web/src/features/articles/components/articles-toolbar.tsx b/apps/web/src/features/articles/components/articles-toolbar.tsx index 353d51a..85fab70 100644 --- a/apps/web/src/features/articles/components/articles-toolbar.tsx +++ b/apps/web/src/features/articles/components/articles-toolbar.tsx @@ -59,7 +59,7 @@ export function ArticlesToolbar({ searchQuery, setOpenFilterModal }: Props) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Escape') onSearchClear(); }; diff --git a/apps/web/src/features/articles/components/edit-tags-dialog.tsx b/apps/web/src/features/articles/components/edit-tags-dialog.tsx index 7b7cdb2..cda89bd 100644 --- a/apps/web/src/features/articles/components/edit-tags-dialog.tsx +++ b/apps/web/src/features/articles/components/edit-tags-dialog.tsx @@ -40,7 +40,7 @@ interface EditTagsDialogProps { function EditTagsDialog({ initialTags, linkId, onOpenChange, open }: EditTagsDialogProps) { const [pendingTags, setPendingTags] = useState(initialTags); const pendingCreatedTagRef = useRef(null); - const { t } = useTranslation('common'); + const { t } = useTranslation(); const { isMobile } = useMediaQuery(); const tagsQuery = useGetTags(); diff --git a/apps/web/src/features/articles/components/empty-state.tsx b/apps/web/src/features/articles/components/empty-state.tsx index deb478f..7c314ff 100644 --- a/apps/web/src/features/articles/components/empty-state.tsx +++ b/apps/web/src/features/articles/components/empty-state.tsx @@ -20,7 +20,7 @@ interface EmptyStateProps { export function EmptyState({ filter, hasSearch, isDemo = false, onAddArticle }: EmptyStateProps) { const shouldReduceMotion = useReducedMotion(); - const { t } = useTranslation('common'); + const { t } = useTranslation(); const getEmptyStateContent = () => { if (hasSearch) { diff --git a/apps/web/src/features/articles/components/filter-sidebar.tsx b/apps/web/src/features/articles/components/filter-sidebar.tsx index 93f211b..a38b42c 100644 --- a/apps/web/src/features/articles/components/filter-sidebar.tsx +++ b/apps/web/src/features/articles/components/filter-sidebar.tsx @@ -41,7 +41,7 @@ const Filter = memo(function Filter({ onFilterClick, onNavigateToTagManagement }: FilterProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); return (
diff --git a/apps/web/src/features/auth/components/brand-panel.tsx b/apps/web/src/features/auth/components/brand-panel.tsx index 8d31fe8..faec3a2 100644 --- a/apps/web/src/features/auth/components/brand-panel.tsx +++ b/apps/web/src/features/auth/components/brand-panel.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { cn } from '@/lib/utils'; export function AuthBrandPanel() { - const { t } = useTranslation('common'); + const { t } = useTranslation(); return (
diff --git a/apps/web/src/features/auth/components/login-form.tsx b/apps/web/src/features/auth/components/login-form.tsx index 05d807e..5eb3d10 100644 --- a/apps/web/src/features/auth/components/login-form.tsx +++ b/apps/web/src/features/auth/components/login-form.tsx @@ -17,7 +17,7 @@ import { type LoginInput, useLogin } from '../api/login'; import { authKeys } from '../api/query-keys'; export function LoginForm({ className, ...props }: React.ComponentProps<'form'>) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); const notifyError = useNotificationsStore.useError(); diff --git a/apps/web/src/features/auth/components/register-form.tsx b/apps/web/src/features/auth/components/register-form.tsx index dfa1a0e..c93a2db 100644 --- a/apps/web/src/features/auth/components/register-form.tsx +++ b/apps/web/src/features/auth/components/register-form.tsx @@ -16,7 +16,7 @@ import { authKeys } from '../api/query-keys'; import { type RegisterInput, useRegister } from '../api/register'; export function RegisterForm({ className, ...props }: React.ComponentProps<'form'>) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); const notifyError = useNotificationsStore.useError(); diff --git a/apps/web/src/features/home/components/continue-reading-section.tsx b/apps/web/src/features/home/components/continue-reading-section.tsx index 91f9d72..f91abe1 100644 --- a/apps/web/src/features/home/components/continue-reading-section.tsx +++ b/apps/web/src/features/home/components/continue-reading-section.tsx @@ -14,7 +14,7 @@ type Props = { export function ContinueReadingSection({ data, isLoading }: Props) { const navigate = useNavigate(); - const { t } = useTranslation('common'); + const { t } = useTranslation(); if (isLoading) { return ; diff --git a/apps/web/src/features/home/components/onboarding-progress-card.tsx b/apps/web/src/features/home/components/onboarding-progress-card.tsx index 9eab53a..c2e8a54 100644 --- a/apps/web/src/features/home/components/onboarding-progress-card.tsx +++ b/apps/web/src/features/home/components/onboarding-progress-card.tsx @@ -11,7 +11,7 @@ type Props = { }; export function OnboardingProgressCard({ hasStartedReading, totalArticles }: Props) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const steps = [ { diff --git a/apps/web/src/features/home/components/quick-add-bar.tsx b/apps/web/src/features/home/components/quick-add-bar.tsx index e43cab2..2bb3b4e 100644 --- a/apps/web/src/features/home/components/quick-add-bar.tsx +++ b/apps/web/src/features/home/components/quick-add-bar.tsx @@ -14,7 +14,7 @@ type QuickAddBarProps = { }; export function QuickAddBar({ isDemo = false }: QuickAddBarProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const notifySuccess = useNotificationsStore.useSuccess(); const [url, setUrl] = useState(''); diff --git a/apps/web/src/features/home/components/recently-saved-section.tsx b/apps/web/src/features/home/components/recently-saved-section.tsx index e17048f..7df59b2 100644 --- a/apps/web/src/features/home/components/recently-saved-section.tsx +++ b/apps/web/src/features/home/components/recently-saved-section.tsx @@ -14,7 +14,7 @@ type Props = { }; export function RecentlySavedSection({ articles, isFirstTimeUser, isLoading }: Props) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); return (
diff --git a/apps/web/src/features/home/components/suggestions-section.tsx b/apps/web/src/features/home/components/suggestions-section.tsx index 28988e3..4be4878 100644 --- a/apps/web/src/features/home/components/suggestions-section.tsx +++ b/apps/web/src/features/home/components/suggestions-section.tsx @@ -19,7 +19,7 @@ type Props = { }; export function SuggestionsSection({ isLoading, suggestions }: Props) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const navigate = useNavigate(); const shortReadCount = suggestions?.shortReads?.totalArticles ?? 0; diff --git a/apps/web/src/features/import-articles/api/get-links-from-session.ts b/apps/web/src/features/import-articles/api/get-links-from-session.ts index e7f3161..ecc1d06 100644 --- a/apps/web/src/features/import-articles/api/get-links-from-session.ts +++ b/apps/web/src/features/import-articles/api/get-links-from-session.ts @@ -77,7 +77,7 @@ export const useGetLinksFromImportSession = ({ queryConfig }: UseGetLinksFromImportSessionOptions) => { const queryClient = useQueryClient(); - const { t } = useTranslation('common'); + const { t } = useTranslation(); const infiniteQuery = useInfiniteQuery({ ...getLinksFromImportSessionQueryOptions(importSessionId, extractionStatus), diff --git a/apps/web/src/features/import-articles/components/extraction-progress.tsx b/apps/web/src/features/import-articles/components/extraction-progress.tsx index 03092ac..41cc210 100644 --- a/apps/web/src/features/import-articles/components/extraction-progress.tsx +++ b/apps/web/src/features/import-articles/components/extraction-progress.tsx @@ -43,7 +43,7 @@ const statusFilterKeys = [ ] as const; export function ExtractionProgress(props: ExtractionProgressProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const { extractionCompleted, extractionFailed, diff --git a/apps/web/src/features/import-articles/components/extraction-status-card.tsx b/apps/web/src/features/import-articles/components/extraction-status-card.tsx index bd24a59..5b33b70 100644 --- a/apps/web/src/features/import-articles/components/extraction-status-card.tsx +++ b/apps/web/src/features/import-articles/components/extraction-status-card.tsx @@ -39,7 +39,7 @@ const renderStatusBadge = (status: string, t: (key: string) => string) => { }; export function ExtractionStatusCard({ link, onViewArticle }: ExtractionStatusCardProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const getStatusIconStyle = () => { switch (link.status) { diff --git a/apps/web/src/features/import-articles/components/import-progress.tsx b/apps/web/src/features/import-articles/components/import-progress.tsx index 543e0c7..afbda35 100644 --- a/apps/web/src/features/import-articles/components/import-progress.tsx +++ b/apps/web/src/features/import-articles/components/import-progress.tsx @@ -8,7 +8,7 @@ import { Progress } from '@/components/ui/progress'; import { ExtractionProgress } from './extraction-progress'; export function ImportProgress() { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const [progress, setProgress] = useState({ extraction: 0, import: 0 diff --git a/apps/web/src/features/import-articles/components/map-fields.tsx b/apps/web/src/features/import-articles/components/map-fields.tsx index 6278569..c31cabd 100644 --- a/apps/web/src/features/import-articles/components/map-fields.tsx +++ b/apps/web/src/features/import-articles/components/map-fields.tsx @@ -79,7 +79,7 @@ function ColumnSelect({ } export function MapFields({ onMappingComplete }: MapFieldsProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const { mapping, onMappingChange, uploadedFile } = useImportArticles(); const populateFields = (columns: string[]) => { diff --git a/apps/web/src/features/import-articles/components/review-import.tsx b/apps/web/src/features/import-articles/components/review-import.tsx index cf7e725..4b4fcbd 100644 --- a/apps/web/src/features/import-articles/components/review-import.tsx +++ b/apps/web/src/features/import-articles/components/review-import.tsx @@ -21,7 +21,7 @@ interface ReviewImportProps { } export function ReviewImport({ onReviewComplete }: ReviewImportProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const { preview, uploadedFile } = useImportArticles(); useEffect(() => { diff --git a/apps/web/src/features/import-articles/components/upload-from-csv.tsx b/apps/web/src/features/import-articles/components/upload-from-csv.tsx index 739d29f..d8df5d9 100644 --- a/apps/web/src/features/import-articles/components/upload-from-csv.tsx +++ b/apps/web/src/features/import-articles/components/upload-from-csv.tsx @@ -20,7 +20,7 @@ interface UploadFromCsvProps { } export function UploadFromCsv({ disabled = false, onUploadComplete }: UploadFromCsvProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); const fileInputRef = useRef(null); const notifyError = useNotificationsStore.useError(); diff --git a/apps/web/src/features/import-articles/components/wizard-step-indicator.tsx b/apps/web/src/features/import-articles/components/wizard-step-indicator.tsx index 8fbe406..4658660 100644 --- a/apps/web/src/features/import-articles/components/wizard-step-indicator.tsx +++ b/apps/web/src/features/import-articles/components/wizard-step-indicator.tsx @@ -8,7 +8,7 @@ type Props = { }; export function WizardStepIndicator({ currentStep, steps }: Props) { - const { t } = useTranslation('common'); + const { t } = useTranslation(); return (