## Translation Files - Add 11 new language files (es, de, pt, ru, zh, ja, ko, ar, hi, nl, pl) - Add 100+ missing translation keys across all 15 languages - New sections: notebook, pagination, ai.batchOrganization, ai.autoLabels - Update nav section with workspace, quickAccess, myLibrary keys ## Component Updates - Update 15+ components to use translation keys instead of hardcoded text - Components: notebook dialogs, sidebar, header, note-input, ghost-tags, etc. - Replace 80+ hardcoded English/French strings with t() calls - Ensure consistent UI across all supported languages ## Code Quality - Remove 77+ console.log statements from codebase - Clean up API routes, components, hooks, and services - Keep only essential error handling (no debugging logs) ## UI/UX Improvements - Update Keep logo to yellow post-it style (from-yellow-400 to-amber-500) - Change selection colors to #FEF3C6 (notebooks) and #EFB162 (nav items) - Make "+" button permanently visible in notebooks section - Fix grammar and syntax errors in multiple components ## Bug Fixes - Fix JSON syntax errors in it.json, nl.json, pl.json, zh.json - Fix syntax errors in notebook-suggestion-toast.tsx - Fix syntax errors in use-auto-tagging.ts - Fix syntax errors in paragraph-refactor.service.ts - Fix duplicate "fusion" section in nl.json 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Ou une version plus courte si vous préférez : feat(i18n): Add 15 languages, remove logs, update UI components - Create 11 new translation files (es, de, pt, ru, zh, ja, ko, ar, hi, nl, pl) - Add 100+ translation keys: notebook, pagination, AI features - Update 15+ components to use translations (80+ strings) - Remove 77+ console.log statements from codebase - Fix JSON syntax errors in 4 translation files - Fix component syntax errors (toast, hooks, services) - Update logo to yellow post-it style - Change selection colors (#FEF3C6, #EFB162) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
321 lines
7.0 KiB
TypeScript
321 lines
7.0 KiB
TypeScript
/**
|
|
* Load translations from JSON files
|
|
*/
|
|
|
|
export type SupportedLanguage = 'en' | 'fr' | 'es' | 'de' | 'fa' | 'it' | 'pt' | 'ru' | 'zh' | 'ja' | 'ko' | 'ar' | 'hi' | 'nl' | 'pl'
|
|
|
|
export interface Translations {
|
|
auth: {
|
|
signIn: string
|
|
signUp: string
|
|
email: string
|
|
password: string
|
|
name: string
|
|
emailPlaceholder: string
|
|
passwordPlaceholder: string
|
|
namePlaceholder: string
|
|
passwordMinChars: string
|
|
resetPassword: string
|
|
resetPasswordInstructions: string
|
|
forgotPassword: string
|
|
noAccount: string
|
|
hasAccount: string
|
|
signInToAccount: string
|
|
createAccount: string
|
|
rememberMe: string
|
|
orContinueWith: string
|
|
}
|
|
notes: {
|
|
title: string
|
|
newNote: string
|
|
untitled: string
|
|
placeholder: string
|
|
markdownPlaceholder: string
|
|
titlePlaceholder: string
|
|
listItem: string
|
|
addListItem: string
|
|
newChecklist: string
|
|
add: string
|
|
adding: string
|
|
close: string
|
|
confirmDelete: string
|
|
confirmLeaveShare: string
|
|
sharedBy: string
|
|
leaveShare: string
|
|
delete: string
|
|
archive: string
|
|
unarchive: string
|
|
pin: string
|
|
unpin: string
|
|
color: string
|
|
changeColor: string
|
|
setReminder: string
|
|
setReminderButton: string
|
|
date: string
|
|
time: string
|
|
reminderDateTimeRequired: string
|
|
invalidDateTime: string
|
|
reminderMustBeFuture: string
|
|
reminderSet: string
|
|
addImage: string
|
|
addLink: string
|
|
linkAdded: string
|
|
linkMetadataFailed: string
|
|
linkAddFailed: string
|
|
invalidFileType: string
|
|
fileTooLarge: string
|
|
uploadFailed: string
|
|
contentOrMediaRequired: string
|
|
itemOrMediaRequired: string
|
|
noteCreated: string
|
|
noteCreateFailed: string
|
|
aiAssistant: string
|
|
changeSize: string
|
|
backgroundOptions: string
|
|
moreOptions: string
|
|
remindMe: string
|
|
markdownMode: string
|
|
addCollaborators: string
|
|
duplicate: string
|
|
share: string
|
|
showCollaborators: string
|
|
pinned: string
|
|
others: string
|
|
noNotes: string
|
|
noNotesFound: string
|
|
createFirstNote: string
|
|
}
|
|
labels: {
|
|
title: string
|
|
filter: string
|
|
manage: string
|
|
manageTooltip: string
|
|
changeColor: string
|
|
changeColorTooltip: string
|
|
delete: string
|
|
deleteTooltip: string
|
|
confirmDelete: string
|
|
newLabelPlaceholder: string
|
|
namePlaceholder: string
|
|
addLabel: string
|
|
createLabel: string
|
|
labelName: string
|
|
labelColor: string
|
|
manageLabels: string
|
|
clearAll: string
|
|
filterByLabel: string
|
|
tagAdded: string
|
|
}
|
|
search: {
|
|
placeholder: string
|
|
searchPlaceholder: string
|
|
semanticInProgress: string
|
|
semanticTooltip: string
|
|
searching: string
|
|
noResults: string
|
|
resultsFound: string
|
|
exactMatch: string
|
|
related: string
|
|
}
|
|
collaboration: {
|
|
emailPlaceholder: string
|
|
addCollaborator: string
|
|
removeCollaborator: string
|
|
owner: string
|
|
canEdit: string
|
|
canView: string
|
|
shareNote: string
|
|
}
|
|
ai: {
|
|
analyzing: string
|
|
clickToAddTag: string
|
|
ignoreSuggestion: string
|
|
generatingTitles: string
|
|
generateTitlesTooltip: string
|
|
poweredByAI: string
|
|
languageDetected: string
|
|
processing: string
|
|
}
|
|
titleSuggestions: {
|
|
available: string
|
|
title: string
|
|
generating: string
|
|
selectTitle: string
|
|
dismiss: string
|
|
}
|
|
semanticSearch: {
|
|
exactMatch: string
|
|
related: string
|
|
searching: string
|
|
}
|
|
paragraphRefactor: {
|
|
title: string
|
|
shorten: string
|
|
expand: string
|
|
improve: string
|
|
formal: string
|
|
casual: string
|
|
}
|
|
memoryEcho: {
|
|
title: string
|
|
description: string
|
|
dailyInsight: string
|
|
insightReady: string
|
|
}
|
|
nav: {
|
|
home: string
|
|
notes: string
|
|
notebooks: string
|
|
generalNotes: string
|
|
archive: string
|
|
settings: string
|
|
profile: string
|
|
aiSettings: string
|
|
logout: string
|
|
login: string
|
|
}
|
|
settings: {
|
|
title: string
|
|
description: string
|
|
account: string
|
|
appearance: string
|
|
theme: string
|
|
themeLight: string
|
|
themeDark: string
|
|
themeSystem: string
|
|
notifications: string
|
|
language: string
|
|
selectLanguage: string
|
|
privacy: string
|
|
security: string
|
|
about: string
|
|
version: string
|
|
settingsSaved: string
|
|
settingsError: string
|
|
}
|
|
profile: {
|
|
title: string
|
|
description: string
|
|
displayName: string
|
|
email: string
|
|
changePassword: string
|
|
changePasswordDescription: string
|
|
currentPassword: string
|
|
newPassword: string
|
|
confirmPassword: string
|
|
updatePassword: string
|
|
passwordChangeSuccess: string
|
|
passwordChangeFailed: string
|
|
passwordUpdated: string
|
|
passwordError: string
|
|
languagePreferences: string
|
|
languagePreferencesDescription: string
|
|
preferredLanguage: string
|
|
selectLanguage: string
|
|
languageDescription: string
|
|
autoDetect: string
|
|
updateSuccess: string
|
|
updateFailed: string
|
|
languageUpdateSuccess: string
|
|
languageUpdateFailed: string
|
|
profileUpdated: string
|
|
profileError: string
|
|
accountSettings: string
|
|
manageAISettings: string
|
|
}
|
|
aiSettings: {
|
|
title: string
|
|
description: string
|
|
features: string
|
|
provider: string
|
|
providerAuto: string
|
|
providerOllama: string
|
|
providerOpenAI: string
|
|
frequency: string
|
|
frequencyDaily: string
|
|
frequencyWeekly: string
|
|
saving: string
|
|
saved: string
|
|
error: string
|
|
}
|
|
general: {
|
|
loading: string
|
|
save: string
|
|
cancel: string
|
|
add: string
|
|
edit: string
|
|
confirm: string
|
|
close: string
|
|
back: string
|
|
next: string
|
|
previous: string
|
|
submit: string
|
|
reset: string
|
|
apply: string
|
|
clear: string
|
|
select: string
|
|
tryAgain: string
|
|
error: string
|
|
operationSuccess: string
|
|
operationFailed: string
|
|
}
|
|
colors: {
|
|
default: string
|
|
red: string
|
|
blue: string
|
|
green: string
|
|
yellow: string
|
|
purple: string
|
|
pink: string
|
|
orange: string
|
|
gray: string
|
|
}
|
|
reminder: {
|
|
title: string
|
|
setReminder: string
|
|
removeReminder: string
|
|
reminderDate: string
|
|
reminderTime: string
|
|
save: string
|
|
cancel: string
|
|
}
|
|
notebookSuggestion: {
|
|
title: string
|
|
description: string
|
|
move: string
|
|
dismiss: string
|
|
dismissIn: string
|
|
moveToNotebook: string
|
|
generalNotes: string
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load translations from JSON files
|
|
*/
|
|
export async function loadTranslations(language: SupportedLanguage): Promise<Translations> {
|
|
try {
|
|
const translations = await import(`@/locales/${language}.json`)
|
|
return translations.default as Translations
|
|
} catch (error) {
|
|
console.error(`Failed to load translations for ${language}:`, error)
|
|
// Fallback to English
|
|
const enTranslations = await import(`@/locales/en.json`)
|
|
return enTranslations.default as Translations
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get nested translation value from object using dot notation
|
|
*/
|
|
export function getTranslationValue(translations: Translations, key: string): string {
|
|
const keys = key.split('.')
|
|
let value: any = translations
|
|
|
|
for (const k of keys) {
|
|
value = value?.[k]
|
|
}
|
|
|
|
return typeof value === 'string' ? value : key
|
|
}
|