Generated by Spark: When I set Language to french, it doesnt work. I think Redux can help with this.

This commit is contained in:
2026-01-24 00:37:02 +00:00
committed by GitHub
parent f06dd26667
commit 89ffa229c7
5 changed files with 52 additions and 10 deletions

View File

@@ -3,6 +3,7 @@ import { useNotifications } from '@/hooks/use-notifications'
import { useAppData } from '@/hooks/use-app-data'
import { useAppActions } from '@/hooks/use-app-actions'
import { useViewPreload } from '@/hooks/use-view-preload'
import { useLocaleInit } from '@/hooks/use-locale-init'
import { Sidebar } from '@/components/navigation'
import { NotificationCenter } from '@/components/NotificationCenter'
import { ViewRouter } from '@/components/ViewRouter'
@@ -26,6 +27,7 @@ function App() {
useSampleData()
useViewPreload()
useLocaleInit()
const { notifications, addNotification, markAsRead, markAllAsRead, deleteNotification, unreadCount } = useNotifications()

View File

@@ -70,6 +70,7 @@ export { useSortableData } from './use-sortable-data'
export { useFilterableData } from './use-filterable-data'
export { useFormatter } from './use-formatter'
export { useTemplateManager } from './use-template-manager'
export { useLocaleInit } from './use-locale-init'
export { useFetch } from './use-fetch'
export { useLocalStorageState } from './use-local-storage-state'
@@ -145,4 +146,3 @@ export type { UseAsyncActionResult } from './use-async-action'
export type { UseMutationOptions, UseMutationResult } from './use-mutation'
export type { UseFavoritesOptions, UseFavoritesResult } from './use-favorites'
export type { UseClipboardResult } from './use-clipboard-copy'

View File

@@ -0,0 +1,18 @@
import { useEffect } from 'react'
import { useKV } from '@github/spark/hooks'
import { useAppDispatch, useAppSelector } from '@/store/hooks'
import { setLocale } from '@/store/slices/uiSlice'
type Locale = 'en' | 'es' | 'fr'
export function useLocaleInit() {
const dispatch = useAppDispatch()
const reduxLocale = useAppSelector(state => state.ui.locale)
const [kvLocale] = useKV<Locale>('app-locale', 'en')
useEffect(() => {
if (kvLocale && kvLocale !== reduxLocale) {
dispatch(setLocale(kvLocale))
}
}, [kvLocale, reduxLocale, dispatch])
}

View File

@@ -1,5 +1,7 @@
import { useKV } from '@github/spark/hooks'
import { useState, useEffect, useCallback } from 'react'
import { useAppSelector, useAppDispatch } from '@/store/hooks'
import { setLocale as setReduxLocale } from '@/store/slices/uiSlice'
type Translations = Record<string, any>
type Locale = 'en' | 'es' | 'fr'
@@ -8,11 +10,21 @@ const AVAILABLE_LOCALES: Locale[] = ['en', 'es', 'fr']
const DEFAULT_LOCALE: Locale = 'en'
export function useTranslation() {
const [locale, setLocale] = useKV<Locale>('app-locale', DEFAULT_LOCALE)
const dispatch = useAppDispatch()
const reduxLocale = useAppSelector(state => state.ui.locale)
const [kvLocale, setKVLocale] = useKV<Locale>('app-locale', DEFAULT_LOCALE)
const [translations, setTranslations] = useState<Translations>({})
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState<Error | null>(null)
useEffect(() => {
if (kvLocale && kvLocale !== reduxLocale) {
dispatch(setReduxLocale(kvLocale))
}
}, [kvLocale, reduxLocale, dispatch])
const locale = reduxLocale
useEffect(() => {
const loadTranslations = async () => {
try {
@@ -68,9 +80,10 @@ export function useTranslation() {
const changeLocale = useCallback((newLocale: Locale) => {
if (AVAILABLE_LOCALES.includes(newLocale)) {
setLocale(newLocale)
dispatch(setReduxLocale(newLocale))
setKVLocale(newLocale)
}
}, [setLocale])
}, [dispatch, setKVLocale])
return {
t,
@@ -83,16 +96,18 @@ export function useTranslation() {
}
export function useLocale() {
const [locale] = useKV<Locale>('app-locale', DEFAULT_LOCALE)
const locale = useAppSelector(state => state.ui.locale)
return locale
}
export function useChangeLocale() {
const [, setLocale] = useKV<Locale>('app-locale', DEFAULT_LOCALE)
const dispatch = useAppDispatch()
const [, setKVLocale] = useKV<Locale>('app-locale', DEFAULT_LOCALE)
return useCallback((newLocale: Locale) => {
if (AVAILABLE_LOCALES.includes(newLocale)) {
setLocale(newLocale)
dispatch(setReduxLocale(newLocale))
setKVLocale(newLocale)
}
}, [setLocale])
}, [dispatch, setKVLocale])
}

View File

@@ -1,17 +1,21 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
type View = 'dashboard' | 'timesheets' | 'billing' | 'payroll' | 'compliance' | 'expenses' | 'roadmap' | 'reports' | 'currency' | 'email-templates' | 'invoice-templates' | 'qr-scanner' | 'missing-timesheets' | 'purchase-orders' | 'onboarding' | 'audit-trail' | 'notification-rules' | 'batch-import' | 'rate-templates' | 'custom-reports' | 'holiday-pay' | 'contract-validation' | 'shift-patterns' | 'query-guide' | 'component-showcase' | 'business-logic-demo' | 'data-admin' | 'translation-demo' | 'profile'
type View = 'dashboard' | 'timesheets' | 'billing' | 'payroll' | 'compliance' | 'expenses' | 'roadmap' | 'reports' | 'currency' | 'email-templates' | 'invoice-templates' | 'qr-scanner' | 'missing-timesheets' | 'purchase-orders' | 'onboarding' | 'audit-trail' | 'notification-rules' | 'batch-import' | 'rate-templates' | 'custom-reports' | 'holiday-pay' | 'contract-validation' | 'shift-patterns' | 'query-guide' | 'component-showcase' | 'business-logic-demo' | 'data-admin' | 'translation-demo' | 'profile' | 'roles-permissions'
type Locale = 'en' | 'es' | 'fr'
interface UIState {
currentView: View
searchQuery: string
sidebarCollapsed: boolean
locale: Locale
}
const initialState: UIState = {
currentView: 'dashboard',
searchQuery: '',
sidebarCollapsed: false,
locale: 'en',
}
const uiSlice = createSlice({
@@ -27,8 +31,11 @@ const uiSlice = createSlice({
toggleSidebar: (state) => {
state.sidebarCollapsed = !state.sidebarCollapsed
},
setLocale: (state, action: PayloadAction<Locale>) => {
state.locale = action.payload
},
},
})
export const { setCurrentView, setSearchQuery, toggleSidebar } = uiSlice.actions
export const { setCurrentView, setSearchQuery, toggleSidebar, setLocale } = uiSlice.actions
export default uiSlice.reducer