Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f8788ee42d | ||
![]() |
b0ec84b8ca | ||
![]() |
198222c3ff | ||
![]() |
7ef225daec | ||
![]() |
6e56e164df |
File diff suppressed because it is too large
Load Diff
@ -73,7 +73,10 @@
|
|||||||
"groupNameRequired": "Group name is required",
|
"groupNameRequired": "Group name is required",
|
||||||
"createFailed": "Failed to create group. Please try again.",
|
"createFailed": "Failed to create group. Please try again.",
|
||||||
"inviteCodeRequired": "Invite code is required",
|
"inviteCodeRequired": "Invite code is required",
|
||||||
"joinFailed": "Failed to join group. Please check the invite code and try again."
|
"joinFailed": "Failed to join group. Please check the invite code and try again.",
|
||||||
|
"invalidDataFromServer": "Invalid data received from server.",
|
||||||
|
"createFailedConsole": "Error creating group:",
|
||||||
|
"joinFailedConsole": "Error joining group:"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"groupCreatedSuccess": "Group '{groupName}' created successfully.",
|
"groupCreatedSuccess": "Group '{groupName}' created successfully.",
|
||||||
@ -85,7 +88,8 @@
|
|||||||
"authCallbackPage": {
|
"authCallbackPage": {
|
||||||
"redirecting": "Redirecting...",
|
"redirecting": "Redirecting...",
|
||||||
"errors": {
|
"errors": {
|
||||||
"authenticationFailed": "Authentication failed"
|
"authenticationFailed": "Authentication failed",
|
||||||
|
"noTokenProvided": "No token provided"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"choresPage": {
|
"choresPage": {
|
||||||
@ -125,7 +129,17 @@
|
|||||||
"save": "Save Changes",
|
"save": "Save Changes",
|
||||||
"create": "Create",
|
"create": "Create",
|
||||||
"editChore": "Edit Chore",
|
"editChore": "Edit Chore",
|
||||||
"createChore": "Create Chore"
|
"createChore": "Create Chore",
|
||||||
|
"intervalPlaceholder": "e.g., 10"
|
||||||
|
},
|
||||||
|
"consoleErrors": {
|
||||||
|
"loadFailed": "Failed to load all chores:",
|
||||||
|
"loadGroupsFailed": "Failed to load groups",
|
||||||
|
"createAssignmentForNewChoreFailed": "Failed to create assignment for new chore:",
|
||||||
|
"saveFailed": "Failed to save chore:",
|
||||||
|
"deleteFailed": "Failed to delete chore:",
|
||||||
|
"createAssignmentFailed": "Failed to create assignment:",
|
||||||
|
"updateCompletionStatusFailed": "Failed to update chore completion status:"
|
||||||
},
|
},
|
||||||
"deleteConfirm": {
|
"deleteConfirm": {
|
||||||
"title": "Confirm Deletion",
|
"title": "Confirm Deletion",
|
||||||
@ -160,10 +174,14 @@
|
|||||||
"title": "Group Members",
|
"title": "Group Members",
|
||||||
"defaultRole": "Member",
|
"defaultRole": "Member",
|
||||||
"removeButton": "Remove",
|
"removeButton": "Remove",
|
||||||
"emptyState": "No members found."
|
"emptyState": "No members found.",
|
||||||
|
"closeMenuLabel": "Close menu"
|
||||||
},
|
},
|
||||||
"invites": {
|
"invites": {
|
||||||
"title": "Invite Members",
|
"title": "Invite Members",
|
||||||
|
"description": "Invite new members by generating a shareable code.",
|
||||||
|
"addMemberButtonLabel": "Add member",
|
||||||
|
"closeInviteLabel": "Close invite",
|
||||||
"regenerateButton": "Regenerate Invite Code",
|
"regenerateButton": "Regenerate Invite Code",
|
||||||
"generateButton": "Generate Invite Code",
|
"generateButton": "Generate Invite Code",
|
||||||
"activeCodeLabel": "Current Active Invite Code:",
|
"activeCodeLabel": "Current Active Invite Code:",
|
||||||
@ -174,6 +192,15 @@
|
|||||||
"newDataInvalid": "New invite code data is invalid."
|
"newDataInvalid": "New invite code data is invalid."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"failedToFetchActiveInvite": "Failed to fetch active invite code.",
|
||||||
|
"failedToFetchGroupDetails": "Failed to fetch group details.",
|
||||||
|
"failedToLoadUpcomingChores": "Error loading upcoming chores:",
|
||||||
|
"failedToLoadRecentExpenses": "Error loading recent expenses:"
|
||||||
|
},
|
||||||
|
"console": {
|
||||||
|
"noActiveInvite": "No active invite code found for this group."
|
||||||
|
},
|
||||||
"chores": {
|
"chores": {
|
||||||
"title": "Group Chores",
|
"title": "Group Chores",
|
||||||
"manageButton": "Manage Chores",
|
"manageButton": "Manage Chores",
|
||||||
@ -191,6 +218,8 @@
|
|||||||
"settleShareButton": "Settle My Share",
|
"settleShareButton": "Settle My Share",
|
||||||
"activityLabel": "Activity:",
|
"activityLabel": "Activity:",
|
||||||
"byUser": "by",
|
"byUser": "by",
|
||||||
|
"fallbackUserName": "User ID: {userId}",
|
||||||
|
"activityByUserFallback": "User {userId}",
|
||||||
"splitTypes": {
|
"splitTypes": {
|
||||||
"equal": "Equal",
|
"equal": "Equal",
|
||||||
"exactAmounts": "Exact Amounts",
|
"exactAmounts": "Exact Amounts",
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,13 @@
|
|||||||
import en from './en.json';
|
import en from './en.json';
|
||||||
import de from './de.json';
|
import de from './de.json';
|
||||||
|
import nl from './nl.json';
|
||||||
import fr from './fr.json';
|
import fr from './fr.json';
|
||||||
import es from './es.json';
|
import es from './es.json';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
en,
|
en,
|
||||||
de,
|
de,
|
||||||
|
nl,
|
||||||
fr,
|
fr,
|
||||||
es
|
es
|
||||||
};
|
};
|
||||||
|
631
fe/src/i18n/nl.json
Normal file
631
fe/src/i18n/nl.json
Normal file
@ -0,0 +1,631 @@
|
|||||||
|
{
|
||||||
|
"message": {
|
||||||
|
"hello": "Hallo"
|
||||||
|
},
|
||||||
|
"loginPage": {
|
||||||
|
"emailLabel": "E-mail",
|
||||||
|
"passwordLabel": "Wachtwoord",
|
||||||
|
"togglePasswordVisibilityLabel": "Wachtwoord zichtbaarheid wisselen",
|
||||||
|
"loginButton": "Inloggen",
|
||||||
|
"signupLink": "Geen account? Aanmelden",
|
||||||
|
"errors": {
|
||||||
|
"emailRequired": "E-mail is vereist",
|
||||||
|
"emailInvalid": "Ongeldig e-mailformaat",
|
||||||
|
"passwordRequired": "Wachtwoord is vereist",
|
||||||
|
"loginFailed": "Inloggen mislukt. Controleer uw gegevens."
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"loginSuccess": "Succesvol ingelogd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"listsPage": {
|
||||||
|
"retryButton": "Opnieuw proberen",
|
||||||
|
"emptyState": {
|
||||||
|
"noListsForGroup": "Geen lijsten gevonden voor deze groep.",
|
||||||
|
"noListsYet": "U heeft nog geen lijsten.",
|
||||||
|
"personalGlobalInfo": "Maak een persoonlijke lijst of word lid van een groep om gedeelde lijsten te zien.",
|
||||||
|
"groupSpecificInfo": "Deze groep heeft nog geen lijsten."
|
||||||
|
},
|
||||||
|
"createNewListButton": "Nieuwe lijst maken",
|
||||||
|
"loadingLists": "Lijsten laden...",
|
||||||
|
"noDescription": "Geen beschrijving",
|
||||||
|
"addItemPlaceholder": "Nieuw item toevoegen...",
|
||||||
|
"createCard": {
|
||||||
|
"title": "+ Lijst"
|
||||||
|
},
|
||||||
|
"pageTitle": {
|
||||||
|
"forGroup": "Lijsten voor {groupName}",
|
||||||
|
"forGroupId": "Lijsten voor Groep {groupId}",
|
||||||
|
"myLists": "Mijn Lijsten"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"fetchFailed": "Ophalen van lijsten mislukt."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"groupsPage": {
|
||||||
|
"retryButton": "Opnieuw proberen",
|
||||||
|
"emptyState": {
|
||||||
|
"title": "Nog geen groepen!",
|
||||||
|
"description": "U bent nog geen lid van groepen. Maak er een aan of word lid met een uitnodigingscode.",
|
||||||
|
"createButton": "Nieuwe groep maken"
|
||||||
|
},
|
||||||
|
"groupCard": {
|
||||||
|
"newListButton": "Lijst"
|
||||||
|
},
|
||||||
|
"createCard": {
|
||||||
|
"title": "+ Groep"
|
||||||
|
},
|
||||||
|
"joinGroup": {
|
||||||
|
"title": "Lid worden van een groep met uitnodigingscode",
|
||||||
|
"inputLabel": "Voer uitnodigingscode in",
|
||||||
|
"inputPlaceholder": "Voer uitnodigingscode in",
|
||||||
|
"joinButton": "Deelnemen"
|
||||||
|
},
|
||||||
|
"createDialog": {
|
||||||
|
"title": "Nieuwe groep maken",
|
||||||
|
"closeButtonLabel": "Sluiten",
|
||||||
|
"groupNameLabel": "Groepsnaam",
|
||||||
|
"cancelButton": "Annuleren",
|
||||||
|
"createButton": "Maken"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"fetchFailed": "Laden van groepen mislukt",
|
||||||
|
"groupNameRequired": "Groepsnaam is vereist",
|
||||||
|
"createFailed": "Maken van groep mislukt. Probeer het opnieuw.",
|
||||||
|
"inviteCodeRequired": "Uitnodigingscode is vereist",
|
||||||
|
"joinFailed": "Deelnemen aan groep mislukt. Controleer de uitnodigingscode en probeer het opnieuw.",
|
||||||
|
"invalidDataFromServer": "Ongeldige gegevens ontvangen van server.",
|
||||||
|
"createFailedConsole": "Fout bij het maken van groep:",
|
||||||
|
"joinFailedConsole": "Fout bij het deelnemen aan groep:"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"groupCreatedSuccess": "Groep '{groupName}' succesvol aangemaakt.",
|
||||||
|
"joinSuccessNamed": "Succesvol lid geworden van groep '{groupName}'.",
|
||||||
|
"joinSuccessGeneric": "Succesvol lid geworden van groep.",
|
||||||
|
"listCreatedSuccess": "Lijst '{listName}' succesvol aangemaakt."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authCallbackPage": {
|
||||||
|
"redirecting": "Bezig met omleiden...",
|
||||||
|
"errors": {
|
||||||
|
"authenticationFailed": "Authenticatie mislukt",
|
||||||
|
"noTokenProvided": "Geen token opgegeven"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"choresPage": {
|
||||||
|
"title": "Taken",
|
||||||
|
"tabs": {
|
||||||
|
"overdue": "Achterstallig",
|
||||||
|
"today": "Vandaag",
|
||||||
|
"upcoming": "Aankomend",
|
||||||
|
"allPending": "Alle openstaande",
|
||||||
|
"completed": "Voltooid"
|
||||||
|
},
|
||||||
|
"viewToggle": {
|
||||||
|
"calendarLabel": "Kalenderweergave",
|
||||||
|
"calendarText": "Kalender",
|
||||||
|
"listLabel": "Lijstweergave",
|
||||||
|
"listText": "Lijst"
|
||||||
|
},
|
||||||
|
"newChoreButtonLabel": "Nieuwe taak",
|
||||||
|
"newChoreButtonText": "Nieuwe taak",
|
||||||
|
"loadingState": {
|
||||||
|
"loadingChores": "Taken laden..."
|
||||||
|
},
|
||||||
|
"calendar": {
|
||||||
|
"prevMonthLabel": "Vorige maand",
|
||||||
|
"nextMonthLabel": "Volgende maand",
|
||||||
|
"weekdays": {
|
||||||
|
"sun": "Zo",
|
||||||
|
"mon": "Ma",
|
||||||
|
"tue": "Di",
|
||||||
|
"wed": "Wo",
|
||||||
|
"thu": "Do",
|
||||||
|
"fri": "Vr",
|
||||||
|
"sat": "Za"
|
||||||
|
},
|
||||||
|
"addChoreToDayLabel": "Taak aan deze dag toevoegen",
|
||||||
|
"emptyState": "Geen taken om weer te geven voor deze periode."
|
||||||
|
},
|
||||||
|
"listView": {
|
||||||
|
"choreTypePersonal": "Persoonlijk",
|
||||||
|
"choreTypeGroupFallback": "Groep",
|
||||||
|
"completedDatePrefix": "Voltooid:",
|
||||||
|
"actions": {
|
||||||
|
"doneTitle": "Markeer als voltooid",
|
||||||
|
"doneText": "Gedaan",
|
||||||
|
"undoTitle": "Markeer als niet voltooid",
|
||||||
|
"undoText": "Ongedaan maken",
|
||||||
|
"editTitle": "Bewerken",
|
||||||
|
"editLabel": "Taak bewerken",
|
||||||
|
"editText": "Bewerken",
|
||||||
|
"deleteTitle": "Verwijderen",
|
||||||
|
"deleteLabel": "Taak verwijderen",
|
||||||
|
"deleteText": "Verwijderen"
|
||||||
|
},
|
||||||
|
"emptyState": {
|
||||||
|
"message": "Geen taken in deze weergave. Goed gedaan!",
|
||||||
|
"viewAllButton": "Alle openstaande bekijken"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"choreModal": {
|
||||||
|
"editTitle": "Taak bewerken",
|
||||||
|
"newTitle": "Nieuwe taak",
|
||||||
|
"closeButtonLabel": "Modal sluiten",
|
||||||
|
"nameLabel": "Naam",
|
||||||
|
"namePlaceholder": "Voer taaknaam in",
|
||||||
|
"typeLabel": "Type",
|
||||||
|
"typePersonal": "Persoonlijk",
|
||||||
|
"typeGroup": "Groep",
|
||||||
|
"groupLabel": "Groep",
|
||||||
|
"groupSelectDefault": "Selecteer een groep",
|
||||||
|
"descriptionLabel": "Beschrijving",
|
||||||
|
"descriptionPlaceholder": "Voeg een beschrijving toe (optioneel)",
|
||||||
|
"frequencyLabel": "Frequentie",
|
||||||
|
"intervalLabel": "Interval (dagen)",
|
||||||
|
"intervalPlaceholder": "bijv. 10",
|
||||||
|
"dueDateLabel": "Vervaldatum",
|
||||||
|
"quickDueDateToday": "Vandaag",
|
||||||
|
"quickDueDateTomorrow": "Morgen",
|
||||||
|
"quickDueDateNextWeek": "Volgende week",
|
||||||
|
"cancelButton": "Annuleren",
|
||||||
|
"saveButton": "Opslaan"
|
||||||
|
},
|
||||||
|
"consoleErrors": {
|
||||||
|
"loadFailed": "Laden van alle taken mislukt:",
|
||||||
|
"loadGroupsFailed": "Laden van groepen mislukt",
|
||||||
|
"createAssignmentForNewChoreFailed": "Toewijzing voor nieuwe taak kon niet worden gemaakt:",
|
||||||
|
"saveFailed": "Opslaan van taak mislukt:",
|
||||||
|
"deleteFailed": "Verwijderen van taak mislukt:",
|
||||||
|
"createAssignmentFailed": "Toewijzing kon niet worden gemaakt:",
|
||||||
|
"updateCompletionStatusFailed": "Voltooiingsstatus van taak kon niet worden bijgewerkt:"
|
||||||
|
},
|
||||||
|
"deleteDialog": {
|
||||||
|
"title": "Taak verwijderen",
|
||||||
|
"confirmationText": "Weet u zeker dat u deze taak wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.",
|
||||||
|
"deleteButton": "Verwijderen"
|
||||||
|
},
|
||||||
|
"shortcutsModal": {
|
||||||
|
"title": "Sneltoetsen",
|
||||||
|
"descNewChore": "Nieuwe taak",
|
||||||
|
"descToggleView": "Weergave wisselen (Lijst/Kalender)",
|
||||||
|
"descToggleShortcuts": "Sneltoetsen tonen/verbergen",
|
||||||
|
"descCloseModal": "Open Modal/Dialoog sluiten"
|
||||||
|
},
|
||||||
|
"frequencyOptions": {
|
||||||
|
"oneTime": "Eenmalig",
|
||||||
|
"daily": "Dagelijks",
|
||||||
|
"weekly": "Wekelijks",
|
||||||
|
"monthly": "Maandelijks",
|
||||||
|
"custom": "Aangepast"
|
||||||
|
},
|
||||||
|
"frequency": {
|
||||||
|
"customInterval": "Elke {n} dag | Elke {n} dagen"
|
||||||
|
},
|
||||||
|
"formatters": {
|
||||||
|
"noDueDate": "Geen vervaldatum",
|
||||||
|
"dueToday": "Vandaag te doen",
|
||||||
|
"dueTomorrow": "Morgen te doen",
|
||||||
|
"overdueFull": "Achterstallig: {date}",
|
||||||
|
"dueFull": "Vervalt op {date}",
|
||||||
|
"invalidDate": "Ongeldige datum"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"loadFailed": "Laden van taken mislukt.",
|
||||||
|
"loadGroupsFailed": "Laden van groepen mislukt.",
|
||||||
|
"updateSuccess": "Taak '{name}' succesvol bijgewerkt.",
|
||||||
|
"createSuccess": "Taak '{name}' succesvol aangemaakt.",
|
||||||
|
"updateFailed": "Bijwerken van taak mislukt.",
|
||||||
|
"createFailed": "Aanmaken van taak mislukt.",
|
||||||
|
"deleteSuccess": "Taak '{name}' succesvol verwijderd.",
|
||||||
|
"deleteFailed": "Verwijderen van taak mislukt.",
|
||||||
|
"markedDone": "{name} gemarkeerd als voltooid.",
|
||||||
|
"markedNotDone": "{name} gemarkeerd als niet voltooid.",
|
||||||
|
"statusUpdateFailed": "Status van taak kon niet worden bijgewerkt.",
|
||||||
|
"createAssignmentFailed": "Toewijzing voor taak kon niet worden gemaakt."
|
||||||
|
},
|
||||||
|
"validation": {
|
||||||
|
"nameRequired": "Taaknaam is vereist.",
|
||||||
|
"groupRequired": "Selecteer een groep voor groepstaken.",
|
||||||
|
"intervalRequired": "Aangepast interval moet minimaal 1 dag zijn.",
|
||||||
|
"dueDateRequired": "Vervaldatum is vereist.",
|
||||||
|
"invalidDueDate": "Ongeldig formaat vervaldatum."
|
||||||
|
},
|
||||||
|
"unsavedChangesConfirmation": "U heeft niet-opgeslagen wijzigingen in het taakformulier. Weet u zeker dat u wilt vertrekken?"
|
||||||
|
},
|
||||||
|
"errorNotFoundPage": {
|
||||||
|
"errorCode": "404",
|
||||||
|
"errorMessage": "Oeps. Hier is niets...",
|
||||||
|
"goHomeButton": "Naar de startpagina"
|
||||||
|
},
|
||||||
|
"groupDetailPage": {
|
||||||
|
"loadingLabel": "Groepsdetails laden...",
|
||||||
|
"retryButton": "Opnieuw proberen",
|
||||||
|
"groupNotFound": "Groep niet gevonden of er is een fout opgetreden.",
|
||||||
|
"members": {
|
||||||
|
"title": "Groepsleden",
|
||||||
|
"defaultRole": "Lid",
|
||||||
|
"removeButton": "Verwijderen",
|
||||||
|
"emptyState": "Geen leden gevonden.",
|
||||||
|
"closeMenuLabel": "Menu sluiten"
|
||||||
|
},
|
||||||
|
"invites": {
|
||||||
|
"title": "Leden uitnodigen",
|
||||||
|
"description": "Nodig nieuwe leden uit door een deelbare code te genereren.",
|
||||||
|
"addMemberButtonLabel": "Lid toevoegen",
|
||||||
|
"closeInviteLabel": "Uitnodiging sluiten",
|
||||||
|
"regenerateButton": "Uitnodigingscode opnieuw genereren",
|
||||||
|
"generateButton": "Uitnodigingscode genereren",
|
||||||
|
"activeCodeLabel": "Huidige actieve uitnodigingscode:",
|
||||||
|
"copyButtonLabel": "Kopieer uitnodigingscode",
|
||||||
|
"copySuccess": "Uitnodigingscode gekopieerd naar klembord!",
|
||||||
|
"emptyState": "Geen actieve uitnodigingscode. Klik op de knop hierboven om er een te genereren.",
|
||||||
|
"errors": {
|
||||||
|
"newDataInvalid": "Gegevens van nieuwe uitnodigingscode zijn ongeldig."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"failedToFetchActiveInvite": "Ophalen van actieve uitnodigingscode mislukt.",
|
||||||
|
"failedToFetchGroupDetails": "Ophalen van groepsdetails mislukt.",
|
||||||
|
"failedToLoadUpcomingChores": "Fout bij het laden van aankomende taken:",
|
||||||
|
"failedToLoadRecentExpenses": "Fout bij het laden van recente uitgaven:"
|
||||||
|
},
|
||||||
|
"console": {
|
||||||
|
"noActiveInvite": "Geen actieve uitnodigingscode gevonden voor deze groep."
|
||||||
|
},
|
||||||
|
"chores": {
|
||||||
|
"title": "Groepstaken",
|
||||||
|
"manageButton": "Taken beheren",
|
||||||
|
"duePrefix": "Vervalt:",
|
||||||
|
"emptyState": "Geen taken gepland. Klik op \"Taken beheren\" om er enkele aan te maken!"
|
||||||
|
},
|
||||||
|
"expenses": {
|
||||||
|
"title": "Groepsuitgaven",
|
||||||
|
"manageButton": "Uitgaven beheren",
|
||||||
|
"emptyState": "Geen uitgaven geregistreerd. Klik op \"Uitgaven beheren\" om er enkele toe te voegen!",
|
||||||
|
"paidBy": "Betaald door:",
|
||||||
|
"owes": "is verschuldigd",
|
||||||
|
"paidAmount": "Betaald:",
|
||||||
|
"onDate": "op",
|
||||||
|
"settleShareButton": "Mijn deel vereffenen",
|
||||||
|
"activityLabel": "Activiteit:",
|
||||||
|
"byUser": "door",
|
||||||
|
"fallbackUserName": "Gebruikers-ID: {userId}",
|
||||||
|
"activityByUserFallback": "Gebruiker {userId}",
|
||||||
|
"splitTypes": {
|
||||||
|
"equal": "Gelijk",
|
||||||
|
"exactAmounts": "Exacte bedragen",
|
||||||
|
"percentage": "Percentage",
|
||||||
|
"shares": "Aandelen",
|
||||||
|
"itemBased": "Op item gebaseerd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"fetchDetailsFailed": "Ophalen van groepsdetails mislukt.",
|
||||||
|
"fetchInviteFailed": "Ophalen van actieve uitnodigingscode mislukt.",
|
||||||
|
"generateInviteSuccess": "Nieuwe uitnodigingscode succesvol gegenereerd!",
|
||||||
|
"generateInviteError": "Genereren van uitnodigingscode mislukt.",
|
||||||
|
"clipboardNotSupported": "Klembord niet ondersteund of geen code om te kopiëren.",
|
||||||
|
"copyInviteFailed": "Kopiëren van uitnodigingscode mislukt.",
|
||||||
|
"removeMemberSuccess": "Lid succesvol verwijderd",
|
||||||
|
"removeMemberFailed": "Verwijderen van lid mislukt",
|
||||||
|
"loadExpensesFailed": "Laden van recente uitgaven mislukt.",
|
||||||
|
"cannotSettleOthersShares": "U kunt alleen uw eigen aandelen vereffenen.",
|
||||||
|
"settlementDataMissing": "Kan vereffening niet verwerken: gegevens ontbreken.",
|
||||||
|
"settleShareSuccess": "Aandeel succesvol vereffend!",
|
||||||
|
"settleShareFailed": "Vereffenen van aandeel mislukt."
|
||||||
|
},
|
||||||
|
"loading": {
|
||||||
|
"settlement": "Bezig met vereffenen..."
|
||||||
|
},
|
||||||
|
"settleShareModal": {
|
||||||
|
"title": "Aandeel vereffenen",
|
||||||
|
"settleAmountFor": "Bedrag vereffenen voor {userName}:",
|
||||||
|
"amountLabel": "Bedrag",
|
||||||
|
"cancelButton": "Annuleren",
|
||||||
|
"confirmButton": "Bevestigen",
|
||||||
|
"errors": {
|
||||||
|
"enterAmount": "Voer een bedrag in.",
|
||||||
|
"positiveAmount": "Voer een positief bedrag in.",
|
||||||
|
"exceedsRemaining": "Bedrag mag resterend bedrag niet overschrijden: {amount}.",
|
||||||
|
"noSplitSelected": "Fout: Geen verdeling geselecteerd."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"settled": "Vereffend",
|
||||||
|
"partiallySettled": "Gedeeltelijk vereffend",
|
||||||
|
"unsettled": "Openstaand",
|
||||||
|
"paid": "Betaald",
|
||||||
|
"partiallyPaid": "Gedeeltelijk betaald",
|
||||||
|
"unpaid": "Onbetaald",
|
||||||
|
"unknown": "Onbekende status"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"accountPage": {
|
||||||
|
"title": "Accountinstellingen",
|
||||||
|
"loadingProfile": "Profiel laden...",
|
||||||
|
"retryButton": "Opnieuw proberen",
|
||||||
|
"profileSection": {
|
||||||
|
"header": "Profielinformatie",
|
||||||
|
"nameLabel": "Naam",
|
||||||
|
"emailLabel": "E-mail",
|
||||||
|
"saveButton": "Wijzigingen opslaan"
|
||||||
|
},
|
||||||
|
"passwordSection": {
|
||||||
|
"header": "Wachtwoord wijzigen",
|
||||||
|
"currentPasswordLabel": "Huidig wachtwoord",
|
||||||
|
"newPasswordLabel": "Nieuw wachtwoord",
|
||||||
|
"changeButton": "Wachtwoord wijzigen"
|
||||||
|
},
|
||||||
|
"notificationsSection": {
|
||||||
|
"header": "Notificatievoorkeuren",
|
||||||
|
"emailNotificationsLabel": "E-mailnotificaties",
|
||||||
|
"emailNotificationsDescription": "Ontvang e-mailnotificaties voor belangrijke updates",
|
||||||
|
"listUpdatesLabel": "Lijstupdates",
|
||||||
|
"listUpdatesDescription": "Ontvang een melding wanneer lijsten worden bijgewerkt",
|
||||||
|
"groupActivitiesLabel": "Groepsactiviteiten",
|
||||||
|
"groupActivitiesDescription": "Ontvang meldingen voor groepsactiviteiten"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"profileLoadFailed": "Laden van profiel mislukt",
|
||||||
|
"profileUpdateSuccess": "Profiel succesvol bijgewerkt",
|
||||||
|
"profileUpdateFailed": "Bijwerken van profiel mislukt",
|
||||||
|
"passwordFieldsRequired": "Vul zowel het huidige als het nieuwe wachtwoordveld in.",
|
||||||
|
"passwordTooShort": "Nieuw wachtwoord moet minimaal 8 tekens lang zijn.",
|
||||||
|
"passwordChangeSuccess": "Wachtwoord succesvol gewijzigd",
|
||||||
|
"passwordChangeFailed": "Wijzigen van wachtwoord mislukt",
|
||||||
|
"preferencesUpdateSuccess": "Voorkeuren succesvol bijgewerkt",
|
||||||
|
"preferencesUpdateFailed": "Bijwerken van voorkeuren mislukt"
|
||||||
|
},
|
||||||
|
"saving": "Opslaan..."
|
||||||
|
},
|
||||||
|
"signupPage": {
|
||||||
|
"header": "Aanmelden",
|
||||||
|
"fullNameLabel": "Volledige naam",
|
||||||
|
"emailLabel": "E-mail",
|
||||||
|
"passwordLabel": "Wachtwoord",
|
||||||
|
"confirmPasswordLabel": "Bevestig wachtwoord",
|
||||||
|
"togglePasswordVisibility": "Wachtwoord zichtbaarheid wisselen",
|
||||||
|
"submitButton": "Aanmelden",
|
||||||
|
"loginLink": "Heeft u al een account? Inloggen",
|
||||||
|
"validation": {
|
||||||
|
"nameRequired": "Naam is vereist",
|
||||||
|
"emailRequired": "E-mail is vereist",
|
||||||
|
"emailInvalid": "Ongeldig e-mailformaat",
|
||||||
|
"passwordRequired": "Wachtwoord is vereist",
|
||||||
|
"passwordLength": "Wachtwoord moet minimaal 8 tekens lang zijn",
|
||||||
|
"confirmPasswordRequired": "Bevestig uw wachtwoord",
|
||||||
|
"passwordsNoMatch": "Wachtwoorden komen niet overeen"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"signupFailed": "Aanmelden mislukt. Probeer het opnieuw.",
|
||||||
|
"signupSuccess": "Account succesvol aangemaakt. Log in alstublieft."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"listDetailPage": {
|
||||||
|
"loading": {
|
||||||
|
"list": "Lijst laden...",
|
||||||
|
"items": "Items laden...",
|
||||||
|
"ocrProcessing": "Afbeelding verwerken...",
|
||||||
|
"addingOcrItems": "OCR-items toevoegen...",
|
||||||
|
"costSummary": "Samenvatting laden...",
|
||||||
|
"expenses": "Uitgaven laden...",
|
||||||
|
"settlement": "Bezig met vereffenen..."
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"fetchFailed": "Laden van lijstdetails mislukt.",
|
||||||
|
"genericLoadFailure": "Groep niet gevonden of er is een fout opgetreden.",
|
||||||
|
"ocrNoItems": "Geen items uit de afbeelding gehaald.",
|
||||||
|
"ocrFailed": "Verwerken van afbeelding mislukt.",
|
||||||
|
"addItemFailed": "Toevoegen van item mislukt.",
|
||||||
|
"updateItemFailed": "Bijwerken van item mislukt.",
|
||||||
|
"updateItemPriceFailed": "Bijwerken van itemprijs mislukt.",
|
||||||
|
"deleteItemFailed": "Verwijderen van item mislukt.",
|
||||||
|
"addOcrItemsFailed": "Toevoegen van OCR-items mislukt.",
|
||||||
|
"fetchItemsFailed": "Laden van items mislukt: {errorMessage}",
|
||||||
|
"loadCostSummaryFailed": "Laden van kostensamenvatting mislukt."
|
||||||
|
},
|
||||||
|
"retryButton": "Opnieuw proberen",
|
||||||
|
"buttons": {
|
||||||
|
"addViaOcr": "Toevoegen via OCR",
|
||||||
|
"addItem": "Toevoegen",
|
||||||
|
"addItems": "Items toevoegen",
|
||||||
|
"cancel": "Annuleren",
|
||||||
|
"confirm": "Bevestigen",
|
||||||
|
"saveChanges": "Wijzigingen opslaan",
|
||||||
|
"close": "Sluiten",
|
||||||
|
"costSummary": "Kostensamenvatting"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"groupList": "Groepslijst",
|
||||||
|
"personalList": "Persoonlijke lijst"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"emptyState": {
|
||||||
|
"title": "Nog geen items!",
|
||||||
|
"message": "Voeg items toe via het onderstaande formulier."
|
||||||
|
},
|
||||||
|
"addItemForm": {
|
||||||
|
"placeholder": "Nieuw item toevoegen",
|
||||||
|
"quantityPlaceholder": "Aantal",
|
||||||
|
"itemNameSrLabel": "Naam nieuw item",
|
||||||
|
"quantitySrLabel": "Hoeveelheid"
|
||||||
|
},
|
||||||
|
"pricePlaceholder": "Prijs",
|
||||||
|
"editItemAriaLabel": "Item bewerken",
|
||||||
|
"deleteItemAriaLabel": "Item verwijderen"
|
||||||
|
},
|
||||||
|
"modals": {
|
||||||
|
"ocr": {
|
||||||
|
"title": "Items toevoegen via OCR",
|
||||||
|
"uploadLabel": "Afbeelding uploaden"
|
||||||
|
},
|
||||||
|
"confirmation": {
|
||||||
|
"title": "Bevestiging"
|
||||||
|
},
|
||||||
|
"editItem": {
|
||||||
|
"title": "Item bewerken",
|
||||||
|
"nameLabel": "Itemnaam",
|
||||||
|
"quantityLabel": "Hoeveelheid"
|
||||||
|
},
|
||||||
|
"costSummary": {
|
||||||
|
"title": "Kostensamenvatting lijst",
|
||||||
|
"totalCostLabel": "Totale kosten lijst:",
|
||||||
|
"equalShareLabel": "Gelijk deel per gebruiker:",
|
||||||
|
"participantsLabel": "Deelnemende gebruikers:",
|
||||||
|
"userBalancesHeader": "Gebruikerssaldi",
|
||||||
|
"tableHeaders": {
|
||||||
|
"user": "Gebruiker",
|
||||||
|
"itemsAddedValue": "Waarde toegevoegde items",
|
||||||
|
"amountDue": "Verschuldigd bedrag",
|
||||||
|
"balance": "Saldo"
|
||||||
|
},
|
||||||
|
"emptyState": "Geen kostensamenvatting beschikbaar."
|
||||||
|
},
|
||||||
|
"settleShare": {
|
||||||
|
"title": "Aandeel vereffenen",
|
||||||
|
"settleAmountFor": "Bedrag vereffenen voor {userName}:",
|
||||||
|
"amountLabel": "Bedrag",
|
||||||
|
"errors": {
|
||||||
|
"enterAmount": "Voer een bedrag in.",
|
||||||
|
"positiveAmount": "Voer een positief bedrag in.",
|
||||||
|
"exceedsRemaining": "Bedrag mag resterend bedrag niet overschrijden: {amount}.",
|
||||||
|
"noSplitSelected": "Fout: Geen verdeling geselecteerd."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"confirmations": {
|
||||||
|
"updateMessage": "'{itemName}' markeren als {status}?",
|
||||||
|
"statusComplete": "voltooid",
|
||||||
|
"statusIncomplete": "onvolledig",
|
||||||
|
"deleteMessage": "'{itemName}' verwijderen? Dit kan niet ongedaan worden gemaakt."
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"itemAddedSuccess": "Item succesvol toegevoegd.",
|
||||||
|
"itemsAddedSuccessOcr": "{count} item(s) succesvol toegevoegd via OCR.",
|
||||||
|
"itemUpdatedSuccess": "Item succesvol bijgewerkt.",
|
||||||
|
"itemDeleteSuccess": "Item succesvol verwijderd.",
|
||||||
|
"enterItemName": "Voer een itemnaam in.",
|
||||||
|
"costSummaryLoadFailed": "Laden van kostensamenvatting mislukt.",
|
||||||
|
"cannotSettleOthersShares": "U kunt alleen uw eigen aandelen vereffenen.",
|
||||||
|
"settlementDataMissing": "Kan vereffening niet verwerken: gegevens ontbreken.",
|
||||||
|
"settleShareSuccess": "Aandeel succesvol vereffend!",
|
||||||
|
"settleShareFailed": "Vereffenen van aandeel mislukt."
|
||||||
|
},
|
||||||
|
"expensesSection": {
|
||||||
|
"title": "Uitgaven",
|
||||||
|
"addExpenseButton": "Uitgave toevoegen",
|
||||||
|
"loading": "Uitgaven laden...",
|
||||||
|
"emptyState": "Nog geen uitgaven geregistreerd voor deze lijst.",
|
||||||
|
"paidBy": "Betaald door:",
|
||||||
|
"onDate": "op",
|
||||||
|
"owes": "is verschuldigd",
|
||||||
|
"paidAmount": "Betaald:",
|
||||||
|
"activityLabel": "Activiteit:",
|
||||||
|
"byUser": "door",
|
||||||
|
"settleShareButton": "Mijn deel vereffenen",
|
||||||
|
"retryButton": "Opnieuw proberen"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"settled": "Vereffend",
|
||||||
|
"partiallySettled": "Gedeeltelijk vereffend",
|
||||||
|
"unsettled": "Openstaand",
|
||||||
|
"paid": "Betaald",
|
||||||
|
"partiallyPaid": "Gedeeltelijk betaald",
|
||||||
|
"unpaid": "Onbetaald",
|
||||||
|
"unknown": "Onbekende status"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"myChoresPage": {
|
||||||
|
"title": "Mijn toegewezen taken",
|
||||||
|
"showCompletedToggle": "Voltooide tonen",
|
||||||
|
"timelineHeaders": {
|
||||||
|
"overdue": "Achterstallig",
|
||||||
|
"today": "Vandaag te doen",
|
||||||
|
"thisWeek": "Deze week",
|
||||||
|
"later": "Later",
|
||||||
|
"completed": "Voltooid"
|
||||||
|
},
|
||||||
|
"choreCard": {
|
||||||
|
"personal": "Persoonlijk",
|
||||||
|
"group": "Groep",
|
||||||
|
"duePrefix": "Vervalt",
|
||||||
|
"completedPrefix": "Voltooid",
|
||||||
|
"dueToday": "Vandaag te doen",
|
||||||
|
"markCompleteButton": "Markeer als voltooid"
|
||||||
|
},
|
||||||
|
"frequencies": {
|
||||||
|
"one_time": "Eenmalig",
|
||||||
|
"daily": "Dagelijks",
|
||||||
|
"weekly": "Wekelijks",
|
||||||
|
"monthly": "Maandelijks",
|
||||||
|
"custom": "Aangepast",
|
||||||
|
"unknown": "Onbekende frequentie"
|
||||||
|
},
|
||||||
|
"dates": {
|
||||||
|
"invalidDate": "Ongeldige datum",
|
||||||
|
"unknownDate": "Onbekende datum"
|
||||||
|
},
|
||||||
|
"emptyState": {
|
||||||
|
"title": "Nog geen toewijzingen!",
|
||||||
|
"noAssignmentsPending": "U heeft geen openstaande taaktoewijzingen.",
|
||||||
|
"noAssignmentsAll": "U heeft geen taaktoewijzingen (voltooid of openstaand).",
|
||||||
|
"viewAllChoresButton": "Alle taken bekijken"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"loadFailed": "Laden van toewijzingen mislukt",
|
||||||
|
"markedComplete": "\"{choreName}\" gemarkeerd als voltooid!",
|
||||||
|
"markCompleteFailed": "Markeren van toewijzing als voltooid mislukt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"personalChoresPage": {
|
||||||
|
"title": "Persoonlijke taken",
|
||||||
|
"newChoreButton": "Nieuwe taak",
|
||||||
|
"editButton": "Bewerken",
|
||||||
|
"deleteButton": "Verwijderen",
|
||||||
|
"cancelButton": "Annuleren",
|
||||||
|
"saveButton": "Opslaan",
|
||||||
|
"modals": {
|
||||||
|
"editChoreTitle": "Taak bewerken",
|
||||||
|
"newChoreTitle": "Nieuwe taak",
|
||||||
|
"deleteChoreTitle": "Taak verwijderen"
|
||||||
|
},
|
||||||
|
"form": {
|
||||||
|
"nameLabel": "Naam",
|
||||||
|
"descriptionLabel": "Beschrijving",
|
||||||
|
"frequencyLabel": "Frequentie",
|
||||||
|
"intervalLabel": "Interval (dagen)",
|
||||||
|
"dueDateLabel": "Volgende vervaldatum"
|
||||||
|
},
|
||||||
|
"deleteDialog": {
|
||||||
|
"confirmationText": "Weet u zeker dat u deze taak wilt verwijderen?"
|
||||||
|
},
|
||||||
|
"frequencies": {
|
||||||
|
"one_time": "Eenmalig",
|
||||||
|
"daily": "Dagelijks",
|
||||||
|
"weekly": "Wekelijks",
|
||||||
|
"monthly": "Maandelijks",
|
||||||
|
"custom": "Aangepast",
|
||||||
|
"unknown": "Onbekende frequentie"
|
||||||
|
},
|
||||||
|
"dates": {
|
||||||
|
"invalidDate": "Ongeldige datum",
|
||||||
|
"duePrefix": "Vervalt"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"loadFailed": "Laden van persoonlijke taken mislukt",
|
||||||
|
"updateSuccess": "Persoonlijke taak succesvol bijgewerkt",
|
||||||
|
"createSuccess": "Persoonlijke taak succesvol aangemaakt",
|
||||||
|
"saveFailed": "Opslaan van persoonlijke taak mislukt",
|
||||||
|
"deleteSuccess": "Persoonlijke taak succesvol verwijderd",
|
||||||
|
"deleteFailed": "Verwijderen van persoonlijke taak mislukt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexPage": {
|
||||||
|
"welcomeMessage": "Welkom bij de Valerie UI App",
|
||||||
|
"mainPageInfo": "Dit is de hoofdindexpagina.",
|
||||||
|
"sampleTodosHeader": "Voorbeeldtaken (uit IndexPage-gegevens)",
|
||||||
|
"totalCountLabel": "Totaal aantal uit meta:",
|
||||||
|
"noTodos": "Geen taken om weer te geven."
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ import enMessages from './i18n/en.json' // Import en.json directly
|
|||||||
import deMessages from './i18n/de.json'
|
import deMessages from './i18n/de.json'
|
||||||
import frMessages from './i18n/fr.json'
|
import frMessages from './i18n/fr.json'
|
||||||
import esMessages from './i18n/es.json'
|
import esMessages from './i18n/es.json'
|
||||||
|
import nlMessages from './i18n/nl.json'
|
||||||
|
|
||||||
// Global styles
|
// Global styles
|
||||||
import './assets/main.scss'
|
import './assets/main.scss'
|
||||||
|
@ -38,7 +38,7 @@ onMounted(async () => {
|
|||||||
const tokenToUse = accessToken || legacyToken;
|
const tokenToUse = accessToken || legacyToken;
|
||||||
|
|
||||||
if (!tokenToUse) {
|
if (!tokenToUse) {
|
||||||
throw new Error('No token provided');
|
throw new Error(t('authCallbackPage.errors.noTokenProvided'));
|
||||||
}
|
}
|
||||||
|
|
||||||
await authStore.setTokens({ access_token: tokenToUse, refresh_token: refreshToken });
|
await authStore.setTokens({ access_token: tokenToUse, refresh_token: refreshToken });
|
||||||
|
@ -80,7 +80,7 @@ const loadChores = async () => {
|
|||||||
cachedChores.value = mappedChores;
|
cachedChores.value = mappedChores;
|
||||||
cachedTimestamp.value = Date.now()
|
cachedTimestamp.value = Date.now()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load all chores:', error)
|
console.error(t('choresPage.consoleErrors.loadFailed'), error)
|
||||||
notificationStore.addNotification({ message: t('choresPage.notifications.loadFailed', 'Failed to load chores.'), type: 'error' })
|
notificationStore.addNotification({ message: t('choresPage.notifications.loadFailed', 'Failed to load chores.'), type: 'error' })
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
@ -91,7 +91,7 @@ const loadGroups = async () => {
|
|||||||
try {
|
try {
|
||||||
groups.value = await groupService.getUserGroups();
|
groups.value = await groupService.getUserGroups();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to load groups", error);
|
console.error(t('choresPage.consoleErrors.loadGroupsFailed'), error);
|
||||||
notificationStore.addNotification({ message: t('choresPage.notifications.loadGroupsFailed', 'Failed to load groups.'), type: 'error' });
|
notificationStore.addNotification({ message: t('choresPage.notifications.loadGroupsFailed', 'Failed to load groups.'), type: 'error' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,7 +227,7 @@ const handleFormSubmit = async () => {
|
|||||||
due_date: createdChore.next_due_date
|
due_date: createdChore.next_due_date
|
||||||
});
|
});
|
||||||
} catch (assignmentError) {
|
} catch (assignmentError) {
|
||||||
console.error('Failed to create assignment for new chore:', assignmentError);
|
console.error(t('choresPage.consoleErrors.createAssignmentForNewChoreFailed'), assignmentError);
|
||||||
// Continue anyway since the chore was created
|
// Continue anyway since the chore was created
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,7 +237,7 @@ const handleFormSubmit = async () => {
|
|||||||
showChoreModal.value = false;
|
showChoreModal.value = false;
|
||||||
await loadChores();
|
await loadChores();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to save chore:', error);
|
console.error(t('choresPage.consoleErrors.saveFailed'), error);
|
||||||
notificationStore.addNotification({ message: t('choresPage.notifications.saveFailed', 'Failed to save the chore.'), type: 'error' });
|
notificationStore.addNotification({ message: t('choresPage.notifications.saveFailed', 'Failed to save the chore.'), type: 'error' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,7 +255,7 @@ const deleteChore = async () => {
|
|||||||
showDeleteDialog.value = false
|
showDeleteDialog.value = false
|
||||||
await loadChores()
|
await loadChores()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to delete chore:', error)
|
console.error(t('choresPage.consoleErrors.deleteFailed'), error)
|
||||||
notificationStore.addNotification({ message: t('choresPage.notifications.deleteFailed', 'Failed to delete chore.'), type: 'error' })
|
notificationStore.addNotification({ message: t('choresPage.notifications.deleteFailed', 'Failed to delete chore.'), type: 'error' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ const toggleCompletion = async (chore: ChoreWithCompletion) => {
|
|||||||
});
|
});
|
||||||
chore.current_assignment_id = assignment.id;
|
chore.current_assignment_id = assignment.id;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to create assignment:', error);
|
console.error(t('choresPage.consoleErrors.createAssignmentFailed'), error);
|
||||||
notificationStore.addNotification({
|
notificationStore.addNotification({
|
||||||
message: t('choresPage.notifications.createAssignmentFailed', 'Failed to create assignment for chore.'),
|
message: t('choresPage.notifications.createAssignmentFailed', 'Failed to create assignment for chore.'),
|
||||||
type: 'error'
|
type: 'error'
|
||||||
@ -299,7 +299,7 @@ const toggleCompletion = async (chore: ChoreWithCompletion) => {
|
|||||||
});
|
});
|
||||||
await loadChores();
|
await loadChores();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to update chore completion status:', error);
|
console.error(t('choresPage.consoleErrors.updateCompletionStatusFailed'), error);
|
||||||
notificationStore.addNotification({ message: t('choresPage.notifications.updateFailed', 'Failed to update chore status.'), type: 'error' });
|
notificationStore.addNotification({ message: t('choresPage.notifications.updateFailed', 'Failed to update chore status.'), type: 'error' });
|
||||||
chore.is_completed = originalCompleted;
|
chore.is_completed = originalCompleted;
|
||||||
} finally {
|
} finally {
|
||||||
@ -403,7 +403,7 @@ const toggleCompletion = async (chore: ChoreWithCompletion) => {
|
|||||||
<label class="form-label" for="chore-interval">{{ t('choresPage.form.interval', 'Interval (days)')
|
<label class="form-label" for="chore-interval">{{ t('choresPage.form.interval', 'Interval (days)')
|
||||||
}}</label>
|
}}</label>
|
||||||
<input id="chore-interval" type="number" v-model.number="choreForm.custom_interval_days"
|
<input id="chore-interval" type="number" v-model.number="choreForm.custom_interval_days"
|
||||||
class="form-input" placeholder="e.g., 10" min="1">
|
class="form-input" :placeholder="t('choresPage.form.intervalPlaceholder')" min="1">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">{{ t('choresPage.form.type', 'Type') }}</label>
|
<label class="form-label">{{ t('choresPage.form.type', 'Type') }}</label>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<div class="popup-header">
|
<div class="popup-header">
|
||||||
<span class="font-semibold truncate">{{ member.email }}</span>
|
<span class="font-semibold truncate">{{ member.email }}</span>
|
||||||
<VButton variant="neutral" size="sm" :icon-only="true" iconLeft="x" @click="activeMemberMenu = null"
|
<VButton variant="neutral" size="sm" :icon-only="true" iconLeft="x" @click="activeMemberMenu = null"
|
||||||
aria-label="Close menu" />
|
:aria-label="t('groupDetailPage.members.closeMenuLabel')" />
|
||||||
</div>
|
</div>
|
||||||
<div class="member-menu-content">
|
<div class="member-menu-content">
|
||||||
<VBadge :text="member.role || t('groupDetailPage.members.defaultRole')"
|
<VBadge :text="member.role || t('groupDetailPage.members.defaultRole')"
|
||||||
@ -37,8 +37,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<button ref="addMemberButtonRef" @click="toggleInviteUI" class="add-member-btn"
|
<button ref="addMemberButtonRef" @click="toggleInviteUI" class="add-member-btn"
|
||||||
:aria-label="t('groupDetailPage.invites.title')">
|
:aria-label="t('groupDetailPage.invites.title')">
|
||||||
<!-- <VIcon name="plus" size="md" /> -->
|
{{ t('groupDetailPage.invites.addMemberButtonLabel') }}
|
||||||
+
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Invite Members Popup -->
|
<!-- Invite Members Popup -->
|
||||||
@ -47,9 +46,9 @@
|
|||||||
<VHeading :level="3" class="!m-0 !p-0 !border-none">{{ t('groupDetailPage.invites.title') }}
|
<VHeading :level="3" class="!m-0 !p-0 !border-none">{{ t('groupDetailPage.invites.title') }}
|
||||||
</VHeading>
|
</VHeading>
|
||||||
<VButton variant="neutral" size="sm" :icon-only="true" iconLeft="x" @click="showInviteUI = false"
|
<VButton variant="neutral" size="sm" :icon-only="true" iconLeft="x" @click="showInviteUI = false"
|
||||||
aria-label="Close invite" />
|
:aria-label="t('groupDetailPage.invites.closeInviteLabel')" />
|
||||||
</div>
|
</div>
|
||||||
<p class="text-sm text-gray-500 my-2">Invite new members by generating a shareable code.</p>
|
<p class="text-sm text-gray-500 my-2">{{ t('groupDetailPage.invites.description') }}</p>
|
||||||
<VButton variant="primary" class="w-full" @click="generateInviteCode" :disabled="generatingInvite">
|
<VButton variant="primary" class="w-full" @click="generateInviteCode" :disabled="generatingInvite">
|
||||||
<VSpinner v-if="generatingInvite" size="sm" /> {{ inviteCode ?
|
<VSpinner v-if="generatingInvite" size="sm" /> {{ inviteCode ?
|
||||||
t('groupDetailPage.invites.regenerateButton') :
|
t('groupDetailPage.invites.regenerateButton') :
|
||||||
@ -146,7 +145,7 @@
|
|||||||
<div class="neo-splits-list">
|
<div class="neo-splits-list">
|
||||||
<div v-for="split in expense.splits" :key="split.id" class="neo-split-item">
|
<div v-for="split in expense.splits" :key="split.id" class="neo-split-item">
|
||||||
<div class="split-col split-user">
|
<div class="split-col split-user">
|
||||||
<strong>{{ split.user?.name || split.user?.email || `User ID: ${split.user_id}` }}</strong>
|
<strong>{{ split.user?.name || split.user?.email || t('groupDetailPage.expenses.fallbackUserName', { userId: split.user_id }) }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="split-col split-owes">
|
<div class="split-col split-owes">
|
||||||
{{ t('groupDetailPage.expenses.owes') }} <strong>{{
|
{{ t('groupDetailPage.expenses.owes') }} <strong>{{
|
||||||
@ -178,8 +177,7 @@
|
|||||||
{{ t('groupDetailPage.expenses.activityLabel') }} {{
|
{{ t('groupDetailPage.expenses.activityLabel') }} {{
|
||||||
formatCurrency(activity.amount_paid) }}
|
formatCurrency(activity.amount_paid) }}
|
||||||
{{
|
{{
|
||||||
t('groupDetailPage.expenses.byUser') }} {{ activity.payer?.name || `User
|
t('groupDetailPage.expenses.byUser') }} {{ activity.payer?.name || t('groupDetailPage.expenses.activityByUserFallback', { userId: activity.paid_by_user_id }) }} {{ t('groupDetailPage.expenses.onDate') }} {{ new
|
||||||
${activity.paid_by_user_id}` }} {{ t('groupDetailPage.expenses.onDate') }} {{ new
|
|
||||||
Date(activity.paid_at).toLocaleDateString() }}
|
Date(activity.paid_at).toLocaleDateString() }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -209,7 +207,7 @@
|
|||||||
<div v-else>
|
<div v-else>
|
||||||
<p>{{ t('groupDetailPage.settleShareModal.settleAmountFor', {
|
<p>{{ t('groupDetailPage.settleShareModal.settleAmountFor', {
|
||||||
userName: selectedSplitForSettlement?.user?.name
|
userName: selectedSplitForSettlement?.user?.name
|
||||||
|| selectedSplitForSettlement?.user?.email || `User ID: ${selectedSplitForSettlement?.user_id}`
|
|| selectedSplitForSettlement?.user?.email || t('groupDetailPage.expenses.fallbackUserName', { userId: selectedSplitForSettlement?.user_id })
|
||||||
}) }}</p>
|
}) }}</p>
|
||||||
<VFormField :label="t('groupDetailPage.settleShareModal.amountLabel')"
|
<VFormField :label="t('groupDetailPage.settleShareModal.amountLabel')"
|
||||||
:error-message="settleAmountError || undefined">
|
:error-message="settleAmountError || undefined">
|
||||||
@ -383,9 +381,9 @@ const fetchActiveInviteCode = async () => {
|
|||||||
inviteCode.value = null; // Explicitly set to null on 404
|
inviteCode.value = null; // Explicitly set to null on 404
|
||||||
inviteExpiresAt.value = null;
|
inviteExpiresAt.value = null;
|
||||||
// Optional: notify user or set a flag to show "generate one" message more prominently
|
// Optional: notify user or set a flag to show "generate one" message more prominently
|
||||||
console.info('No active invite code found for this group.');
|
console.info(t('groupDetailPage.console.noActiveInvite'));
|
||||||
} else {
|
} else {
|
||||||
const message = err instanceof Error ? err.message : 'Failed to fetch active invite code.';
|
const message = err instanceof Error ? err.message : t('groupDetailPage.errors.failedToFetchActiveInvite');
|
||||||
// error.value = message; // This would display a large error banner, might be too much
|
// error.value = message; // This would display a large error banner, might be too much
|
||||||
console.error('Error fetching active invite code:', err);
|
console.error('Error fetching active invite code:', err);
|
||||||
notificationStore.addNotification({ message, type: 'error' });
|
notificationStore.addNotification({ message, type: 'error' });
|
||||||
@ -418,7 +416,7 @@ const fetchGroupDetails = async () => {
|
|||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
};
|
};
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
const message = err instanceof Error ? err.message : 'Failed to fetch group details.';
|
const message = err instanceof Error ? err.message : t('groupDetailPage.errors.failedToFetchGroupDetails');
|
||||||
// Only show the main error banner if we have no data at all to show
|
// Only show the main error banner if we have no data at all to show
|
||||||
if (!group.value) {
|
if (!group.value) {
|
||||||
error.value = message;
|
error.value = message;
|
||||||
@ -524,7 +522,7 @@ const loadUpcomingChores = async () => {
|
|||||||
timestamp: Date.now()
|
timestamp: Date.now()
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading upcoming chores:', error)
|
console.error(t('groupDetailPage.errors.failedToLoadUpcomingChores'), error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,7 +561,7 @@ const loadRecentExpenses = async () => {
|
|||||||
)
|
)
|
||||||
recentExpenses.value = response.data
|
recentExpenses.value = response.data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading recent expenses:', error)
|
console.error(t('groupDetailPage.errors.failedToLoadRecentExpenses'), error)
|
||||||
notificationStore.addNotification({ message: t('groupDetailPage.notifications.loadExpensesFailed'), type: 'error' });
|
notificationStore.addNotification({ message: t('groupDetailPage.notifications.loadExpensesFailed'), type: 'error' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,12 +281,12 @@ const handleCreateGroup = async () => {
|
|||||||
cachedGroups.value = groups.value;
|
cachedGroups.value = groups.value;
|
||||||
cachedTimestamp.value = Date.now();
|
cachedTimestamp.value = Date.now();
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid data received from server.');
|
throw new Error(t('groupsPage.errors.invalidDataFromServer'));
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
const message = error.response?.data?.detail || (error instanceof Error ? error.message : t('groupsPage.errors.createFailed'));
|
const message = error.response?.data?.detail || (error instanceof Error ? error.message : t('groupsPage.errors.createFailed'));
|
||||||
createGroupFormError.value = message;
|
createGroupFormError.value = message;
|
||||||
console.error('Error creating group:', error);
|
console.error(t('groupsPage.errors.createFailedConsole'), error);
|
||||||
notificationStore.addNotification({ message, type: 'error' });
|
notificationStore.addNotification({ message, type: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
creatingGroup.value = false;
|
creatingGroup.value = false;
|
||||||
@ -327,7 +327,7 @@ const handleJoinGroup = async () => {
|
|||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
const message = error.response?.data?.detail || (error instanceof Error ? error.message : t('groupsPage.errors.joinFailed'));
|
const message = error.response?.data?.detail || (error instanceof Error ? error.message : t('groupsPage.errors.joinFailed'));
|
||||||
joinGroupFormError.value = message;
|
joinGroupFormError.value = message;
|
||||||
console.error('Error joining group:', error);
|
console.error(t('groupsPage.errors.joinFailedConsole'), error);
|
||||||
notificationStore.addNotification({ message, type: 'error' });
|
notificationStore.addNotification({ message, type: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
joiningGroup.value = false;
|
joiningGroup.value = false;
|
||||||
|
@ -57,6 +57,7 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
|
|
||||||
const fetchCurrentUser = async () => {
|
const fetchCurrentUser = async () => {
|
||||||
if (!accessToken.value) {
|
if (!accessToken.value) {
|
||||||
|
// No token, so definitely clear any residual state and return.
|
||||||
clearTokens()
|
clearTokens()
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -65,7 +66,28 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
setUser(response.data)
|
setUser(response.data)
|
||||||
return response.data
|
return response.data
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
clearTokens()
|
// Check if the error is from an Axios request and has a response status
|
||||||
|
if (error.isAxiosError && error.response) {
|
||||||
|
const status = error.response.status
|
||||||
|
if (status === 401 || status === 403) {
|
||||||
|
// Authentication error from the server, clear tokens.
|
||||||
|
console.error('Authentication error fetching user, clearing tokens:', error)
|
||||||
|
clearTokens()
|
||||||
|
} else {
|
||||||
|
// Other HTTP error, log it but don't clear tokens.
|
||||||
|
// The user might be null, but the token remains for other cached calls.
|
||||||
|
console.error('HTTP error fetching user, token preserved:', error)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Network error (offline) or other non-HTTP error.
|
||||||
|
// Log the error but preserve tokens.
|
||||||
|
// This allows the app to function with cached data if available.
|
||||||
|
console.error('Network or other error fetching user, token preserved:', error)
|
||||||
|
}
|
||||||
|
// In all error cases where tokens are not cleared, return null for the user object.
|
||||||
|
// The existing user object (if any) will remain until explicitly cleared or overwritten.
|
||||||
|
// If the intention is to clear the user object on any fetch error, uncomment the next line:
|
||||||
|
// setUser(null);
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user