fix: comprehensive i18n — replace hardcoded French/English strings with t() calls
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 1m7s
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 1m7s
Replaced ~100+ hardcoded French and English text strings across 30+ components with proper i18n t() calls. Added 57 new translation keys to all 15 locale files (ar, de, en, es, fa, fr, hi, it, ja, ko, nl, pl, pt, ru, zh). Key changes: - contextual-ai-chat.tsx: 30 French strings → t() (actions, toasts, labels, placeholders) - ai-chat.tsx: 15 French/English strings → t() (header, tabs, welcome, insights, history) - note-inline-editor.tsx: 20 French fallbacks removed (toolbar, save status, checklist) - lab-skeleton.tsx: French loading text → t() - admin-header.tsx, header.tsx, editor-connections-section.tsx: French fallbacks removed - New AI chat component, agent cards, sidebar, settings panel i18n cleanup Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { auth } from '@/auth'
|
||||
import { autoLabelCreationService } from '@/lib/ai/services'
|
||||
import { getAISettings } from '@/app/actions/ai-settings'
|
||||
|
||||
/**
|
||||
* POST /api/ai/auto-labels - Suggest new labels for a notebook
|
||||
@@ -16,6 +17,12 @@ export async function POST(request: NextRequest) {
|
||||
)
|
||||
}
|
||||
|
||||
// Respect user's autoLabeling toggle
|
||||
const userSettings = await getAISettings(session.user.id)
|
||||
if (userSettings.autoLabeling === false) {
|
||||
return NextResponse.json({ success: true, data: null, message: 'Auto-labeling disabled by user' })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { notebookId, language = 'en' } = body
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ export async function GET(request: NextRequest) {
|
||||
AI_MODEL_TAGS: config.AI_MODEL_TAGS || 'not set',
|
||||
AI_PROVIDER_EMBEDDING: config.AI_PROVIDER_EMBEDDING || 'not set',
|
||||
AI_MODEL_EMBEDDING: config.AI_MODEL_EMBEDDING || 'not set',
|
||||
AI_PROVIDER_CHAT: config.AI_PROVIDER_CHAT || 'not set',
|
||||
AI_MODEL_CHAT: config.AI_MODEL_CHAT || 'not set',
|
||||
OPENAI_API_KEY: config.OPENAI_API_KEY ? '***configured***' : '',
|
||||
CUSTOM_OPENAI_API_KEY: config.CUSTOM_OPENAI_API_KEY ? '***configured***' : '',
|
||||
CUSTOM_OPENAI_BASE_URL: config.CUSTOM_OPENAI_BASE_URL || '',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { auth } from '@/auth'
|
||||
import { paragraphRefactorService } from '@/lib/ai/services/paragraph-refactor.service'
|
||||
import { getAISettings } from '@/app/actions/ai-settings'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
@@ -10,6 +11,12 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
// Respect user's paragraphRefactor toggle (Assistant IA)
|
||||
const userSettings = await getAISettings(session.user.id)
|
||||
if (userSettings.paragraphRefactor === false) {
|
||||
return NextResponse.json({ error: 'Feature disabled' }, { status: 403 })
|
||||
}
|
||||
|
||||
const { text, option } = await request.json()
|
||||
|
||||
// Validation
|
||||
|
||||
@@ -5,6 +5,8 @@ import { getTagsProvider } from '@/lib/ai/factory';
|
||||
import { getSystemConfig } from '@/lib/config';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { getAISettings } from '@/app/actions/ai-settings';
|
||||
|
||||
const requestSchema = z.object({
|
||||
content: z.string().min(1, "Le contenu ne peut pas être vide"),
|
||||
notebookId: z.string().optional(),
|
||||
@@ -18,6 +20,11 @@ export async function POST(req: NextRequest) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const userSettings = await getAISettings(session.user.id);
|
||||
if (userSettings.autoLabeling === false) {
|
||||
return NextResponse.json({ tags: [] });
|
||||
}
|
||||
|
||||
const body = await req.json();
|
||||
const { content, notebookId, language } = requestSchema.parse(body);
|
||||
|
||||
|
||||
46
memento-note/app/api/ai/test-chat/route.ts
Normal file
46
memento-note/app/api/ai/test-chat/route.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getChatProvider } from '@/lib/ai/factory'
|
||||
import { getSystemConfig } from '@/lib/config'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const config = await getSystemConfig()
|
||||
const provider = getChatProvider(config)
|
||||
|
||||
const testMessage = 'Réponds en exactement 3 mots : quel est ton nom ?'
|
||||
|
||||
const startTime = Date.now()
|
||||
const response = await provider.generateText(testMessage)
|
||||
const endTime = Date.now()
|
||||
|
||||
if (!response || response.trim().length === 0) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: 'No response from chat provider',
|
||||
model: config.AI_MODEL_CHAT || 'granite4:latest',
|
||||
},
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
model: config.AI_MODEL_CHAT || 'granite4:latest',
|
||||
chatResponse: response.trim(),
|
||||
responseTime: endTime - startTime,
|
||||
})
|
||||
} catch (error: any) {
|
||||
const config = await getSystemConfig()
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: error.message || 'Unknown error',
|
||||
model: config.AI_MODEL_CHAT || 'granite4:latest',
|
||||
stack: process.env.NODE_ENV === 'development' ? error.stack : undefined,
|
||||
},
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getTagsProvider } from '@/lib/ai/factory'
|
||||
import { getSystemConfig } from '@/lib/config'
|
||||
import { auth } from '@/auth'
|
||||
import { getAISettings } from '@/app/actions/ai-settings'
|
||||
import { z } from 'zod'
|
||||
|
||||
const requestSchema = z.object({
|
||||
@@ -9,6 +11,16 @@ const requestSchema = z.object({
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
// Check authentication and user setting
|
||||
const session = await auth()
|
||||
if (session?.user?.id) {
|
||||
const settings = await getAISettings(session.user.id)
|
||||
if (settings.titleSuggestions === false) {
|
||||
return NextResponse.json({ suggestions: [] })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const body = await req.json()
|
||||
const { content } = requestSchema.parse(body)
|
||||
|
||||
|
||||
17
memento-note/app/api/ai/web-search-available/route.ts
Normal file
17
memento-note/app/api/ai/web-search-available/route.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { getSystemConfig } from '@/lib/config'
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const config = await getSystemConfig()
|
||||
const available = !!(
|
||||
config.WEB_SEARCH_PROVIDER ||
|
||||
config.BRAVE_SEARCH_API_KEY ||
|
||||
config.SEARXNG_URL ||
|
||||
config.JINA_API_KEY
|
||||
)
|
||||
return NextResponse.json({ available })
|
||||
} catch {
|
||||
return NextResponse.json({ available: false })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user