feat: Add missing i18n translations for page components (partial)
This commit introduces internationalization for several page components by identifying hardcoded strings, adding them to translation files, and updating the components to use translation keys. Processed pages: - fe/src/pages/AuthCallbackPage.vue: I internationalized an error message. - fe/src/pages/ChoresPage.vue: I internationalized console error messages and an input placeholder. - fe/src/pages/ErrorNotFound.vue: I found no missing translations. - fe/src/pages/GroupDetailPage.vue: I internationalized various UI elements (ARIA labels, button text, fallback user display names) and console/error messages. - fe/src/pages/GroupsPage.vue: I internationalized error messages and console logs. - fe/src/pages/IndexPage.vue: I found no missing user-facing translations. - fe/src/pages/ListDetailPage.vue: My analysis is complete, and I identified a console message and a fallback string for translation (implementation of changes for this page is pending). For each processed page where changes were needed: - I added new keys to `fe/src/i18n/en.json`. - I added corresponding placeholder keys `"[TRANSLATE] Original Text"` to `fe/src/i18n/de.json`, `fe/src/i18n/es.json`, and `fe/src/i18n/fr.json`. - I updated the Vue component to use the `t()` function with the new keys. Further pages in `fe/src/pages/` are pending analysis and internationalization as per our original plan.
This commit is contained in:
parent
550fac1c0c
commit
198222c3ff
@ -73,7 +73,10 @@
|
|||||||
"groupNameRequired": "DE: Group name is required",
|
"groupNameRequired": "DE: Group name is required",
|
||||||
"createFailed": "DE: Failed to create group. Please try again.",
|
"createFailed": "DE: Failed to create group. Please try again.",
|
||||||
"inviteCodeRequired": "DE: Invite code is required",
|
"inviteCodeRequired": "DE: Invite code is required",
|
||||||
"joinFailed": "DE: Failed to join group. Please check the invite code and try again."
|
"joinFailed": "DE: Failed to join group. Please check the invite code and try again.",
|
||||||
|
"invalidDataFromServer": "[TRANSLATE] Invalid data received from server.",
|
||||||
|
"createFailedConsole": "[TRANSLATE] Error creating group:",
|
||||||
|
"joinFailedConsole": "[TRANSLATE] Error joining group:"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"groupCreatedSuccess": "DE: Group '{groupName}' created successfully.",
|
"groupCreatedSuccess": "DE: Group '{groupName}' created successfully.",
|
||||||
@ -85,7 +88,8 @@
|
|||||||
"authCallbackPage": {
|
"authCallbackPage": {
|
||||||
"redirecting": "DE: Redirecting...",
|
"redirecting": "DE: Redirecting...",
|
||||||
"errors": {
|
"errors": {
|
||||||
"authenticationFailed": "DE: Authentication failed"
|
"authenticationFailed": "DE: Authentication failed",
|
||||||
|
"noTokenProvided": "[TRANSLATE] No token provided"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"choresPage": {
|
"choresPage": {
|
||||||
@ -165,7 +169,17 @@
|
|||||||
"quickDueDateTomorrow": "DE: Tomorrow",
|
"quickDueDateTomorrow": "DE: Tomorrow",
|
||||||
"quickDueDateNextWeek": "DE: Next Week",
|
"quickDueDateNextWeek": "DE: Next Week",
|
||||||
"cancelButton": "DE: Cancel",
|
"cancelButton": "DE: Cancel",
|
||||||
"saveButton": "DE: Save"
|
"saveButton": "DE: Save",
|
||||||
|
"intervalPlaceholder": "[TRANSLATE] e.g., 10"
|
||||||
|
},
|
||||||
|
"consoleErrors": {
|
||||||
|
"loadFailed": "[TRANSLATE] Failed to load all chores:",
|
||||||
|
"loadGroupsFailed": "[TRANSLATE] Failed to load groups",
|
||||||
|
"createAssignmentForNewChoreFailed": "[TRANSLATE] Failed to create assignment for new chore:",
|
||||||
|
"saveFailed": "[TRANSLATE] Failed to save chore:",
|
||||||
|
"deleteFailed": "[TRANSLATE] Failed to delete chore:",
|
||||||
|
"createAssignmentFailed": "[TRANSLATE] Failed to create assignment:",
|
||||||
|
"updateCompletionStatusFailed": "[TRANSLATE] Failed to update chore completion status:"
|
||||||
},
|
},
|
||||||
"deleteDialog": {
|
"deleteDialog": {
|
||||||
"title": "DE: Delete Chore",
|
"title": "DE: Delete Chore",
|
||||||
@ -228,10 +242,14 @@
|
|||||||
"title": "DE: Group Members",
|
"title": "DE: Group Members",
|
||||||
"defaultRole": "DE: Member",
|
"defaultRole": "DE: Member",
|
||||||
"removeButton": "DE: Remove",
|
"removeButton": "DE: Remove",
|
||||||
"emptyState": "DE: No members found."
|
"emptyState": "DE: No members found.",
|
||||||
|
"closeMenuLabel": "[TRANSLATE] Close menu"
|
||||||
},
|
},
|
||||||
"invites": {
|
"invites": {
|
||||||
"title": "DE: Invite Members",
|
"title": "DE: Invite Members",
|
||||||
|
"description": "[TRANSLATE] Invite new members by generating a shareable code.",
|
||||||
|
"addMemberButtonLabel": "[TRANSLATE] Add member",
|
||||||
|
"closeInviteLabel": "[TRANSLATE] Close invite",
|
||||||
"regenerateButton": "DE: Regenerate Invite Code",
|
"regenerateButton": "DE: Regenerate Invite Code",
|
||||||
"generateButton": "DE: Generate Invite Code",
|
"generateButton": "DE: Generate Invite Code",
|
||||||
"activeCodeLabel": "DE: Current Active Invite Code:",
|
"activeCodeLabel": "DE: Current Active Invite Code:",
|
||||||
@ -242,6 +260,15 @@
|
|||||||
"newDataInvalid": "DE: New invite code data is invalid."
|
"newDataInvalid": "DE: New invite code data is invalid."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"failedToFetchActiveInvite": "[TRANSLATE] Failed to fetch active invite code.",
|
||||||
|
"failedToFetchGroupDetails": "[TRANSLATE] Failed to fetch group details.",
|
||||||
|
"failedToLoadUpcomingChores": "[TRANSLATE] Error loading upcoming chores:",
|
||||||
|
"failedToLoadRecentExpenses": "[TRANSLATE] Error loading recent expenses:"
|
||||||
|
},
|
||||||
|
"console": {
|
||||||
|
"noActiveInvite": "[TRANSLATE] No active invite code found for this group."
|
||||||
|
},
|
||||||
"chores": {
|
"chores": {
|
||||||
"title": "DE: Group Chores",
|
"title": "DE: Group Chores",
|
||||||
"manageButton": "DE: Manage Chores",
|
"manageButton": "DE: Manage Chores",
|
||||||
@ -252,6 +279,8 @@
|
|||||||
"title": "DE: Group Expenses",
|
"title": "DE: Group Expenses",
|
||||||
"manageButton": "DE: Manage Expenses",
|
"manageButton": "DE: Manage Expenses",
|
||||||
"emptyState": "DE: No expenses recorded. Click \"Manage Expenses\" to add some!",
|
"emptyState": "DE: No expenses recorded. Click \"Manage Expenses\" to add some!",
|
||||||
|
"fallbackUserName": "[TRANSLATE] User ID: {userId}",
|
||||||
|
"activityByUserFallback": "[TRANSLATE] User {userId}",
|
||||||
"splitTypes": {
|
"splitTypes": {
|
||||||
"equal": "DE: Equal",
|
"equal": "DE: Equal",
|
||||||
"exactAmounts": "DE: Exact Amounts",
|
"exactAmounts": "DE: Exact Amounts",
|
||||||
|
@ -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",
|
||||||
|
@ -73,7 +73,10 @@
|
|||||||
"groupNameRequired": "ES: Group name is required",
|
"groupNameRequired": "ES: Group name is required",
|
||||||
"createFailed": "ES: Failed to create group. Please try again.",
|
"createFailed": "ES: Failed to create group. Please try again.",
|
||||||
"inviteCodeRequired": "ES: Invite code is required",
|
"inviteCodeRequired": "ES: Invite code is required",
|
||||||
"joinFailed": "ES: Failed to join group. Please check the invite code and try again."
|
"joinFailed": "ES: Failed to join group. Please check the invite code and try again.",
|
||||||
|
"invalidDataFromServer": "[TRANSLATE] Invalid data received from server.",
|
||||||
|
"createFailedConsole": "[TRANSLATE] Error creating group:",
|
||||||
|
"joinFailedConsole": "[TRANSLATE] Error joining group:"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"groupCreatedSuccess": "ES: Group '{groupName}' created successfully.",
|
"groupCreatedSuccess": "ES: Group '{groupName}' created successfully.",
|
||||||
@ -85,7 +88,8 @@
|
|||||||
"authCallbackPage": {
|
"authCallbackPage": {
|
||||||
"redirecting": "ES: Redirecting...",
|
"redirecting": "ES: Redirecting...",
|
||||||
"errors": {
|
"errors": {
|
||||||
"authenticationFailed": "ES: Authentication failed"
|
"authenticationFailed": "ES: Authentication failed",
|
||||||
|
"noTokenProvided": "[TRANSLATE] No token provided"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"choresPage": {
|
"choresPage": {
|
||||||
@ -165,7 +169,17 @@
|
|||||||
"quickDueDateTomorrow": "ES: Tomorrow",
|
"quickDueDateTomorrow": "ES: Tomorrow",
|
||||||
"quickDueDateNextWeek": "ES: Next Week",
|
"quickDueDateNextWeek": "ES: Next Week",
|
||||||
"cancelButton": "ES: Cancel",
|
"cancelButton": "ES: Cancel",
|
||||||
"saveButton": "ES: Save"
|
"saveButton": "ES: Save",
|
||||||
|
"intervalPlaceholder": "[TRANSLATE] e.g., 10"
|
||||||
|
},
|
||||||
|
"consoleErrors": {
|
||||||
|
"loadFailed": "[TRANSLATE] Failed to load all chores:",
|
||||||
|
"loadGroupsFailed": "[TRANSLATE] Failed to load groups",
|
||||||
|
"createAssignmentForNewChoreFailed": "[TRANSLATE] Failed to create assignment for new chore:",
|
||||||
|
"saveFailed": "[TRANSLATE] Failed to save chore:",
|
||||||
|
"deleteFailed": "[TRANSLATE] Failed to delete chore:",
|
||||||
|
"createAssignmentFailed": "[TRANSLATE] Failed to create assignment:",
|
||||||
|
"updateCompletionStatusFailed": "[TRANSLATE] Failed to update chore completion status:"
|
||||||
},
|
},
|
||||||
"deleteDialog": {
|
"deleteDialog": {
|
||||||
"title": "ES: Delete Chore",
|
"title": "ES: Delete Chore",
|
||||||
@ -228,10 +242,14 @@
|
|||||||
"title": "ES: Group Members",
|
"title": "ES: Group Members",
|
||||||
"defaultRole": "ES: Member",
|
"defaultRole": "ES: Member",
|
||||||
"removeButton": "ES: Remove",
|
"removeButton": "ES: Remove",
|
||||||
"emptyState": "ES: No members found."
|
"emptyState": "ES: No members found.",
|
||||||
|
"closeMenuLabel": "[TRANSLATE] Close menu"
|
||||||
},
|
},
|
||||||
"invites": {
|
"invites": {
|
||||||
"title": "ES: Invite Members",
|
"title": "ES: Invite Members",
|
||||||
|
"description": "[TRANSLATE] Invite new members by generating a shareable code.",
|
||||||
|
"addMemberButtonLabel": "[TRANSLATE] Add member",
|
||||||
|
"closeInviteLabel": "[TRANSLATE] Close invite",
|
||||||
"regenerateButton": "ES: Regenerate Invite Code",
|
"regenerateButton": "ES: Regenerate Invite Code",
|
||||||
"generateButton": "ES: Generate Invite Code",
|
"generateButton": "ES: Generate Invite Code",
|
||||||
"activeCodeLabel": "ES: Current Active Invite Code:",
|
"activeCodeLabel": "ES: Current Active Invite Code:",
|
||||||
@ -242,6 +260,15 @@
|
|||||||
"newDataInvalid": "ES: New invite code data is invalid."
|
"newDataInvalid": "ES: New invite code data is invalid."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"failedToFetchActiveInvite": "[TRANSLATE] Failed to fetch active invite code.",
|
||||||
|
"failedToFetchGroupDetails": "[TRANSLATE] Failed to fetch group details.",
|
||||||
|
"failedToLoadUpcomingChores": "[TRANSLATE] Error loading upcoming chores:",
|
||||||
|
"failedToLoadRecentExpenses": "[TRANSLATE] Error loading recent expenses:"
|
||||||
|
},
|
||||||
|
"console": {
|
||||||
|
"noActiveInvite": "[TRANSLATE] No active invite code found for this group."
|
||||||
|
},
|
||||||
"chores": {
|
"chores": {
|
||||||
"title": "ES: Group Chores",
|
"title": "ES: Group Chores",
|
||||||
"manageButton": "ES: Manage Chores",
|
"manageButton": "ES: Manage Chores",
|
||||||
@ -252,6 +279,8 @@
|
|||||||
"title": "ES: Group Expenses",
|
"title": "ES: Group Expenses",
|
||||||
"manageButton": "ES: Manage Expenses",
|
"manageButton": "ES: Manage Expenses",
|
||||||
"emptyState": "ES: No expenses recorded. Click \"Manage Expenses\" to add some!",
|
"emptyState": "ES: No expenses recorded. Click \"Manage Expenses\" to add some!",
|
||||||
|
"fallbackUserName": "[TRANSLATE] User ID: {userId}",
|
||||||
|
"activityByUserFallback": "[TRANSLATE] User {userId}",
|
||||||
"splitTypes": {
|
"splitTypes": {
|
||||||
"equal": "ES: Equal",
|
"equal": "ES: Equal",
|
||||||
"exactAmounts": "ES: Exact Amounts",
|
"exactAmounts": "ES: Exact Amounts",
|
||||||
|
@ -73,7 +73,10 @@
|
|||||||
"groupNameRequired": "FR: Group name is required",
|
"groupNameRequired": "FR: Group name is required",
|
||||||
"createFailed": "FR: Failed to create group. Please try again.",
|
"createFailed": "FR: Failed to create group. Please try again.",
|
||||||
"inviteCodeRequired": "FR: Invite code is required",
|
"inviteCodeRequired": "FR: Invite code is required",
|
||||||
"joinFailed": "FR: Failed to join group. Please check the invite code and try again."
|
"joinFailed": "FR: Failed to join group. Please check the invite code and try again.",
|
||||||
|
"invalidDataFromServer": "[TRANSLATE] Invalid data received from server.",
|
||||||
|
"createFailedConsole": "[TRANSLATE] Error creating group:",
|
||||||
|
"joinFailedConsole": "[TRANSLATE] Error joining group:"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"groupCreatedSuccess": "FR: Group '{groupName}' created successfully.",
|
"groupCreatedSuccess": "FR: Group '{groupName}' created successfully.",
|
||||||
@ -85,7 +88,8 @@
|
|||||||
"authCallbackPage": {
|
"authCallbackPage": {
|
||||||
"redirecting": "FR: Redirecting...",
|
"redirecting": "FR: Redirecting...",
|
||||||
"errors": {
|
"errors": {
|
||||||
"authenticationFailed": "FR: Authentication failed"
|
"authenticationFailed": "FR: Authentication failed",
|
||||||
|
"noTokenProvided": "[TRANSLATE] No token provided"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"choresPage": {
|
"choresPage": {
|
||||||
@ -165,7 +169,17 @@
|
|||||||
"quickDueDateTomorrow": "FR: Tomorrow",
|
"quickDueDateTomorrow": "FR: Tomorrow",
|
||||||
"quickDueDateNextWeek": "FR: Next Week",
|
"quickDueDateNextWeek": "FR: Next Week",
|
||||||
"cancelButton": "FR: Cancel",
|
"cancelButton": "FR: Cancel",
|
||||||
"saveButton": "FR: Save"
|
"saveButton": "FR: Save",
|
||||||
|
"intervalPlaceholder": "[TRANSLATE] e.g., 10"
|
||||||
|
},
|
||||||
|
"consoleErrors": {
|
||||||
|
"loadFailed": "[TRANSLATE] Failed to load all chores:",
|
||||||
|
"loadGroupsFailed": "[TRANSLATE] Failed to load groups",
|
||||||
|
"createAssignmentForNewChoreFailed": "[TRANSLATE] Failed to create assignment for new chore:",
|
||||||
|
"saveFailed": "[TRANSLATE] Failed to save chore:",
|
||||||
|
"deleteFailed": "[TRANSLATE] Failed to delete chore:",
|
||||||
|
"createAssignmentFailed": "[TRANSLATE] Failed to create assignment:",
|
||||||
|
"updateCompletionStatusFailed": "[TRANSLATE] Failed to update chore completion status:"
|
||||||
},
|
},
|
||||||
"deleteDialog": {
|
"deleteDialog": {
|
||||||
"title": "FR: Delete Chore",
|
"title": "FR: Delete Chore",
|
||||||
@ -228,10 +242,14 @@
|
|||||||
"title": "FR: Group Members",
|
"title": "FR: Group Members",
|
||||||
"defaultRole": "FR: Member",
|
"defaultRole": "FR: Member",
|
||||||
"removeButton": "FR: Remove",
|
"removeButton": "FR: Remove",
|
||||||
"emptyState": "FR: No members found."
|
"emptyState": "FR: No members found.",
|
||||||
|
"closeMenuLabel": "[TRANSLATE] Close menu"
|
||||||
},
|
},
|
||||||
"invites": {
|
"invites": {
|
||||||
"title": "FR: Invite Members",
|
"title": "FR: Invite Members",
|
||||||
|
"description": "[TRANSLATE] Invite new members by generating a shareable code.",
|
||||||
|
"addMemberButtonLabel": "[TRANSLATE] Add member",
|
||||||
|
"closeInviteLabel": "[TRANSLATE] Close invite",
|
||||||
"regenerateButton": "FR: Regenerate Invite Code",
|
"regenerateButton": "FR: Regenerate Invite Code",
|
||||||
"generateButton": "FR: Generate Invite Code",
|
"generateButton": "FR: Generate Invite Code",
|
||||||
"activeCodeLabel": "FR: Current Active Invite Code:",
|
"activeCodeLabel": "FR: Current Active Invite Code:",
|
||||||
@ -242,6 +260,15 @@
|
|||||||
"newDataInvalid": "FR: New invite code data is invalid."
|
"newDataInvalid": "FR: New invite code data is invalid."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"failedToFetchActiveInvite": "[TRANSLATE] Failed to fetch active invite code.",
|
||||||
|
"failedToFetchGroupDetails": "[TRANSLATE] Failed to fetch group details.",
|
||||||
|
"failedToLoadUpcomingChores": "[TRANSLATE] Error loading upcoming chores:",
|
||||||
|
"failedToLoadRecentExpenses": "[TRANSLATE] Error loading recent expenses:"
|
||||||
|
},
|
||||||
|
"console": {
|
||||||
|
"noActiveInvite": "[TRANSLATE] No active invite code found for this group."
|
||||||
|
},
|
||||||
"chores": {
|
"chores": {
|
||||||
"title": "FR: Group Chores",
|
"title": "FR: Group Chores",
|
||||||
"manageButton": "FR: Manage Chores",
|
"manageButton": "FR: Manage Chores",
|
||||||
@ -252,6 +279,8 @@
|
|||||||
"title": "FR: Group Expenses",
|
"title": "FR: Group Expenses",
|
||||||
"manageButton": "FR: Manage Expenses",
|
"manageButton": "FR: Manage Expenses",
|
||||||
"emptyState": "FR: No expenses recorded. Click \"Manage Expenses\" to add some!",
|
"emptyState": "FR: No expenses recorded. Click \"Manage Expenses\" to add some!",
|
||||||
|
"fallbackUserName": "[TRANSLATE] User ID: {userId}",
|
||||||
|
"activityByUserFallback": "[TRANSLATE] User {userId}",
|
||||||
"splitTypes": {
|
"splitTypes": {
|
||||||
"equal": "FR: Equal",
|
"equal": "FR: Equal",
|
||||||
"exactAmounts": "FR: Exact Amounts",
|
"exactAmounts": "FR: Exact Amounts",
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user