fix: i18n system overhaul and sidebar UI bugs

- Fix LanguageProvider: add RTL support (ar/fa), translation caching,
  prevent blank flash during load, browser language detection
- Fix detect-user-language: extend whitelist from 5 to all 15 languages
- Remove hardcoded initialLanguage="fr" from auth layout
- Complete fr.json translation (all sections translated from English)
- Add missing admin.ai keys to all 13 non-English locales
- Translate ai.autoLabels, ai.batchOrganization, memoryEcho sections
  for all locales
- Remove duplicate top-level autoLabels/batchOrganization from en.json
- Fix notebook creation: replace window.location.reload() with
  createNotebookOptimistic + router.refresh()
- Fix notebook name truncation in sidebar with min-w-0
- Remove redundant router.refresh() after note creation in page.tsx

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Sepehr Ramezani
2026-03-29 22:14:05 +02:00
parent 8bf56cd8cd
commit 8daf50ac3f
27 changed files with 1210 additions and 936 deletions

View File

@@ -3,7 +3,7 @@
import { useState, useEffect, useCallback } from 'react'
import { useSearchParams, useRouter } from 'next/navigation'
import { Note } from '@/lib/types'
import { getAllNotes, getPinnedNotes, getRecentNotes, searchNotes } from '@/app/actions/notes'
import { getAllNotes, searchNotes } from '@/app/actions/notes'
import { getAISettings } from '@/app/actions/ai-settings'
import { NoteInput } from '@/components/note-input'
import { MasonryGrid } from '@/components/masonry-grid'
@@ -35,7 +35,7 @@ export default function HomePage() {
const [notes, setNotes] = useState<Note[]>([])
const [pinnedNotes, setPinnedNotes] = useState<Note[]>([])
const [recentNotes, setRecentNotes] = useState<Note[]>([])
const [showRecentNotes, setShowRecentNotes] = useState(false)
const [showRecentNotes, setShowRecentNotes] = useState(true)
const [editingNote, setEditingNote] = useState<{ note: Note; readOnly?: boolean } | null>(null)
const [isLoading, setIsLoading] = useState(true)
const [notebookSuggestion, setNotebookSuggestion] = useState<{ noteId: string; content: string } | null>(null)
@@ -137,8 +137,9 @@ export default function HomePage() {
}
// Refresh in background to ensure data consistency (non-blocking)
router.refresh()
// Note: revalidatePath('/') is already called in the server action,
// and the optimistic update above already adds the note to state.
// No additional router.refresh() needed — avoids visible re-render flash.
}, [searchParams, labels, router])
const handleOpenNote = (noteId: string) => {
@@ -156,9 +157,11 @@ export default function HomePage() {
const loadSettings = async () => {
try {
const settings = await getAISettings()
setShowRecentNotes(settings.showRecentNotes === true)
// Default to true if setting is undefined or null
setShowRecentNotes(settings?.showRecentNotes !== false)
} catch (error) {
setShowRecentNotes(false)
// Default to true on error
setShowRecentNotes(true)
}
}
loadSettings()
@@ -203,19 +206,31 @@ export default function HomePage() {
)
}
// Load pinned notes separately (shown in favorites section)
const pinned = await getPinnedNotes(notebookFilter || undefined)
// Derive pinned notes from already-fetched allNotes (no extra server call)
const pinnedFilter = notebookFilter
? allNotes.filter((note: any) => note.isPinned && note.notebookId === notebookFilter)
: allNotes.filter((note: any) => note.isPinned && !note.notebookId)
setPinnedNotes(pinned)
setPinnedNotes(pinnedFilter)
// Load recent notes only if enabled in settings
// Derive recent notes from already-fetched allNotes (no extra server call)
if (showRecentNotes) {
const recent = await getRecentNotes(3)
// Filter recent notes by current filters
const sevenDaysAgo = new Date()
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7)
sevenDaysAgo.setHours(0, 0, 0, 0)
const recentFiltered = allNotes
.filter((note: any) => {
return !note.isArchived && !note.dismissedFromRecent && note.contentUpdatedAt >= sevenDaysAgo
})
.sort((a: any, b: any) => new Date(b.contentUpdatedAt).getTime() - new Date(a.createdAt).getTime())
.slice(0, 3)
if (notebookFilter) {
setRecentNotes(recent.filter((note: any) => note.notebookId === notebookFilter))
setRecentNotes(recentFiltered.filter((note: any) => note.notebookId === notebookFilter))
} else {
setRecentNotes(recent.filter((note: any) => !note.notebookId))
// Show ALL recent notes when in inbox (not just notes without notebooks)
setRecentNotes(recentFiltered)
}
} else {
setRecentNotes([])
@@ -392,7 +407,7 @@ export default function HomePage() {
{/* Recent Notes Section - Only shown if enabled in settings */}
{showRecentNotes && (
<RecentNotesSection
recentNotes={recentNotes.filter(note => !note.isPinned)}
recentNotes={recentNotes}
onEdit={(note, readOnly) => setEditingNote({ note, readOnly })}
/>
)}