Files
TX/artifacts/teaboy-os/src/locales/en.json
T
riyadhafraa 4595e792e4 Fix 5 validator blockers in groups/users admin work
1. apps.ts getVisibleAppsForUser: use getEffectiveRoleIds() so admin
   gate honors group_roles inheritance (was direct user_roles only —
   security bypass for group-only admins). Exported helper from
   middlewares/auth.ts.

2. POST /users: switch from RegisterBody to new CreateUserBody schema
   that accepts optional groupIds[]. Validates ids exist; user creation
   + auto-Everyone + requested groups happen in single transaction.
   OpenAPI spec extended; api-zod and api-client-react regenerated.

3. DELETE /users/🆔 400 if req.session.userId === target (no
   self-delete).

4. scripts/src/seed.ts: removed `void inArray;` AI-slop and dropped
   unused inArray import.

5. Locales (ar.json + en.json): added admin.users.col.displayNameAr,
   displayNameEn, language and admin.groups.searchPlaceholder.

Typecheck clean. groups-crud + service-orders + users tests pass.
Pre-existing admin-app-opens-pagination flake unrelated.
Architect re-review: PASS.
2026-04-22 08:47:35 +00:00

508 lines
18 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"nav": {
"home": "Home",
"services": "Services",
"chat": "Chat",
"notifications": "Notifications",
"admin": "Admin Dashboard",
"logout": "Logout"
},
"auth": {
"login": "Login",
"register": "Register",
"username": "Username",
"email": "Email",
"password": "Password",
"loginButton": "Login",
"registerButton": "Register",
"welcomeBack": "Welcome Back",
"createAccount": "Create Account",
"registrationClosed": "Public registration is currently closed. Please contact the administrator.",
"displayNameAr": "Name (Arabic)",
"displayNameEn": "Name (English)",
"subtitle": "Sign in to your account to continue",
"signingIn": "Signing in...",
"noAccount": "Don't have an account?",
"showPassword": "Show password",
"hidePassword": "Hide password",
"errRequired": "Please enter your username and password.",
"errInvalid": "Invalid username or password.",
"forgotPassword": "Forgot password?",
"forgot": {
"title": "Reset your password",
"subtitle": "Enter your username or email and we'll send you a link to reset your password.",
"identifier": "Username or email",
"identifierPlaceholder": "you@example.com",
"submit": "Send reset link",
"sending": "Sending...",
"errRequired": "Please enter your username or email.",
"errGeneric": "Something went wrong. Please try again.",
"successMessage": "Your request has been received. An administrator will share a reset link with you shortly.",
"adminNotice": "Email delivery is not configured for this workspace yet, so an administrator will issue a one-time reset link manually.",
"backToLogin": "Back to sign in"
},
"reset": {
"title": "Set a new password",
"subtitle": "Choose a new password for your account.",
"newPassword": "New password",
"confirmPassword": "Confirm password",
"submit": "Update password",
"saving": "Saving...",
"errMinLength": "Password must be at least 6 characters.",
"errMismatch": "Passwords do not match.",
"errGeneric": "Could not reset password. The link may have expired.",
"invalidToken": "This reset link is invalid or has expired.",
"requestNew": "Request a new link",
"successMessage": "Your password has been updated. You can now sign in with your new password.",
"goToLogin": "Go to sign in"
},
"heroTitle": "Welcome to your unified workspace.",
"heroSubtitle": "Sign in to manage everything from one place.",
"feat1": "All your tools in one dashboard",
"feat2": "Real-time updates",
"feat3": "Secure session-based access",
"rights": "All rights reserved."
},
"home": {
"myApps": "My Apps",
"noApps": "No apps yet",
"noAppsHint": "Apps you have access to will appear here.",
"greeting": {
"morning": "Good morning, {{name}}",
"afternoon": "Good afternoon, {{name}}",
"evening": "Good evening, {{name}}"
},
"stats": {
"apps": "Apps",
"services": "Services",
"messages": "Messages",
"alerts": "Alerts"
},
"clockStyle": {
"label": "Clock style",
"showWidget": "Show wall clock on home screen",
"showTopbar": "Show clock in top bar",
"hideWidget": "Hide clock",
"hourFormat": {
"label": "Hour format",
"h12": "12-hour (AM/PM)",
"h24": "24-hour"
},
"options": {
"full": "Full (time, weekday, Hijri & Gregorian)",
"digital": "Digital with seconds",
"digital-no-seconds": "Digital without seconds",
"analog": "Analog clock",
"minimal": "Minimal (time only)"
}
}
},
"services": {
"title": "Services",
"available": "Available",
"unavailable": "Unavailable",
"price": "Price",
"noServices": "No services available",
"category": "Category",
"free": "Free",
"order": "Order",
"orderModalTitle": "Order: {{name}}",
"orderNotes": "Notes (optional)",
"orderNotesPlaceholder": "Any extra notes?",
"orderNotesCounter": "{{count}}/500",
"placeOrder": "Send",
"placing": "Sending...",
"orderPlaced": "Order placed",
"orderFailed": "Could not place the order",
"myOrdersLink": "My Orders"
},
"myOrders": {
"title": "My Orders",
"loadError": "Could not load your orders. Please try again.",
"retry": "Retry",
"back": "Back",
"empty": "No orders yet",
"emptyHint": "Start from the services catalog.",
"browseServices": "Browse services",
"notesLabel": "Notes:",
"cancel": "Cancel order",
"cancelConfirmTitle": "Cancel this order?",
"cancelConfirmBody": "Once cancelled, it can't be reopened.",
"cancelConfirm": "Yes, cancel",
"keep": "Keep it",
"cancelled": "Order cancelled",
"cancelFailed": "Could not cancel the order",
"delete": "Delete",
"deleteConfirmTitle": "Delete this order?",
"deleteConfirmBody": "This will permanently remove the order from your history.",
"deleteConfirm": "Yes, delete",
"deleted": "Order deleted",
"deleteFailed": "Could not delete the order",
"undo": "Undo",
"undone": "Restored",
"clearFinished_one": "Clear 1 finished",
"clearFinished_other": "Clear {{count}} finished",
"clearConfirmTitle": "Clear finished orders?",
"clearConfirmBody_one": "1 finished order will be permanently removed from your history.",
"clearConfirmBody_other": "{{count}} finished orders will be permanently removed from your history.",
"clearConfirm": "Yes, clear",
"clearedCount_one": "1 order deleted",
"clearedCount_other": "{{count}} orders deleted",
"clearedPartial": "{{ok}} deleted, {{fail}} failed"
},
"orderStatus": {
"pending": "Awaiting receiver",
"received": "Received",
"preparing": "Preparing",
"completed": "Completed",
"cancelled": "Cancelled"
},
"incomingOrders": {
"title": "Incoming Orders",
"linkLabel": "Incoming",
"subtitleUnclaimed": "Awaiting receiver",
"subtitleMine": "My active orders",
"empty": "No incoming orders right now",
"emptyHint": "New orders will show up here as they arrive.",
"loadError": "Could not load incoming orders.",
"retry": "Retry",
"noAccess": "You don't have permission to receive orders.",
"back": "Back",
"ageJustNow": "just now",
"ageMinutes": "{{count}}m ago",
"ageHours": "{{count}}h ago",
"ageDays": "{{count}}d ago",
"from": "From",
"confirmReceipt": "Confirm Receipt",
"confirming": "Confirming...",
"markPreparing": "Mark Preparing",
"markCompleted": "Mark Completed",
"cancel": "Cancel",
"alreadyClaimed": "Already claimed by someone else",
"actionFailed": "Could not complete the action",
"claimed": "Order received",
"marked": "Status updated"
},
"chat": {
"title": "Chat",
"newMessage": "New Message",
"typeMessage": "Type a message...",
"send": "Send",
"noConversations": "No conversations",
"createConversation": "New Conversation",
"groupChat": "Group",
"directMessage": "Direct Message",
"participants": "Participants",
"searchUsers": "Search users",
"modeDirect": "Direct",
"modeGroup": "Group",
"groupNameAr": "Group name (Arabic)",
"groupNameEn": "Group name (English)",
"groupNamePlaceholderAr": "مثلاً: فريق المبيعات",
"groupNamePlaceholderEn": "e.g. Sales team",
"searchUsersPlaceholder": "Search by name or username",
"participantsCount_one": "{{count}} person selected",
"participantsCount_other": "{{count}} people selected",
"participantsCount_zero": "No one selected",
"noUsersFound": "No matching users",
"uploadAvatar": "Upload picture",
"replaceAvatar": "Replace picture",
"removeAvatar": "Remove picture",
"changeAvatar": "Change group picture",
"uploadingAvatar": "Uploading… {{progress}}%",
"avatarUploadFailed": "Could not upload picture",
"validation": {
"needGroupName": "Enter a group name in Arabic or English.",
"minTwoMembers": "Pick at least 2 people for a group.",
"pickOnePerson": "Pick one person to chat with."
},
"create": "Create",
"settings": {
"title": "Group settings",
"openSettings": "Open group settings",
"groupName": "Group name",
"saveName": "Save name",
"nameSaved": "Group name updated",
"saveFailed": "Could not save changes",
"needGroupName": "Enter a group name in Arabic or English.",
"members_one": "{{count}} member",
"members_other": "{{count}} members",
"addMembers": "Add members",
"addSelected": "Add",
"membersAdded": "Members added",
"addFailed": "Could not add members",
"removeMember": "Remove member",
"removeFailed": "Could not remove member",
"admin": "Admin",
"you": "(you)",
"viewOnly": "Only the group admin can change the name or members."
},
"filterAll": "Active",
"filterArchived": "Archived",
"noArchived": "No archived chats",
"actions": {
"title": "Chat options",
"openActions": "Open chat options",
"mute": "Mute notifications",
"unmute": "Unmute notifications",
"archive": "Archive chat",
"unarchive": "Unarchive chat",
"leave": "Leave group",
"leaveConfirmTitle": "Leave this group?",
"leaveConfirmBody": "You will be removed from \"{{name}}\" and stop receiving its messages.",
"successorTitle": "Choose the next admin",
"successorHelp": "You're the only admin. Pick who should take over, or let us promote the longest-tenured member.",
"successorAuto": "Auto (longest-tenured member)",
"muted": "Notifications muted",
"unmuted": "Notifications on",
"archived": "Chat archived",
"unarchived": "Chat moved back to active",
"left": "You left the group",
"actionFailed": "Could not complete action",
"mutedLabel": "Muted",
"youAreAdminTitle": "You are now the admin",
"youAreAdminDescription": "You're now in charge of \"{{name}}\".",
"newAdminBadge": "New admin",
"newAdminLabel": "New admin: {{name}}"
},
"system": {
"someone": "Someone",
"listSeparator": ", ",
"groupRenamed": "{{actor}} renamed the group to \"{{name}}\"",
"membersAdded_one": "{{actor}} added {{names}}",
"membersAdded_other": "{{actor}} added {{names}}",
"memberRemoved": "{{actor}} removed {{target}}",
"memberLeft": "{{actor}} left the group",
"adminPromoted": "{{target}} is now a group admin",
"adminPromotedAfterLeave": "{{target}} was promoted to admin after the previous admin left"
}
},
"notifications": {
"title": "Notifications",
"markAllRead": "Mark All Read",
"noNotifications": "No new notifications",
"unread": "Unread"
},
"admin": {
"title": "Admin Dashboard",
"manageApps": "Manage Apps",
"manageServices": "Manage Services",
"manageUsers": "Manage Users",
"addApp": "Add App",
"addService": "Add Service",
"addUser": "Add User",
"editApp": "Edit App",
"editService": "Edit Service",
"editUser": "Edit User",
"deleteConfirm": "Are you sure you want to delete?",
"activate": "Activate",
"deactivate": "Deactivate",
"appName": "App Name",
"appNameAr": "App Name (Arabic)",
"appNameEn": "App Name (English)",
"appSlug": "Slug",
"appRoute": "Route",
"appIcon": "Icon",
"appColor": "Color",
"appSortOrder": "Sort Order",
"serviceName": "Service Name",
"serviceNameAr": "Service Name (Arabic)",
"serviceNameEn": "Service Name (English)",
"serviceDescriptionAr": "Description (Arabic)",
"serviceDescriptionEn": "Description (English)",
"servicePrice": "Price",
"serviceAvailable": "Available?",
"serviceImageUrl": "Image URL",
"serviceImage": "Service Image",
"uploadImage": "Upload Image",
"replaceImage": "Replace Image",
"uploading": "Uploading...",
"uploadFailed": "Image upload failed",
"users": "Users",
"username": "Username",
"email": "Email",
"password": "Password",
"roles": "Roles",
"active": "Active",
"issueResetLink": "Issue password reset link",
"orderReceiverRole": "Order Receiver",
"resetLinkModal": {
"title": "Password reset link for {{username}}",
"description": "Share this one-time link with the user. It can only be used once.",
"expires": "Expires: {{time}}",
"copy": "Copy link",
"copied": "Link copied to clipboard"
},
"siteSettings": "Site Settings",
"siteNameAr": "Site Name (Arabic)",
"siteNameEn": "Site Name (English)",
"registrationOpen": "Allow public registration",
"registrationOpenHint": "When off, only admins can create new users.",
"footerTextAr": "Footer Text (Arabic)",
"footerTextEn": "Footer Text (English)",
"nav": {
"dashboard": "Dashboard",
"apps": "Apps",
"services": "Services",
"users": "Users",
"groups": "Groups",
"userManagement": "User Management",
"settings": "Settings",
"menu": "Menu"
},
"users": {
"searchPlaceholder": "Search by username or email...",
"allGroups": "All groups",
"allStatuses": "All statuses",
"statusActive": "Active",
"statusInactive": "Inactive",
"showing": "Showing {{count}} of {{total}}",
"empty": "No users match your filters.",
"editGroups": "Edit groups",
"editUserGroups": "Edit groups for {{username}}",
"col": {
"username": "Username",
"email": "Email",
"displayNameAr": "Name (Arabic)",
"displayNameEn": "Name (English)",
"language": "Language",
"createdAt": "Created",
"groups": "Groups",
"actions": "Actions"
}
},
"groups": {
"searchPlaceholder": "Search groups...",
"addGroup": "Add Group",
"editGroup": "Edit Group",
"name": "Name",
"descriptionAr": "Description (Arabic)",
"descriptionEn": "Description (English)",
"system": "System",
"empty": "No groups yet.",
"members": "{{count}} members",
"appsCount": "{{count}} apps",
"rolesCount": "{{count}} roles",
"appsHint": "Members of this group will see these apps.",
"usersHint": "Members of this group.",
"tab": {
"info": "Info",
"apps": "Apps",
"users": "Users"
}
},
"dashboardSoon": "Dashboard widgets coming soon.",
"dashboard": {
"totalApps": "Total Apps",
"totalServices": "Total Services",
"totalUsers": "Total Users",
"registration": "Registration",
"open": "Open",
"closed": "Closed",
"recentActivity": "Recent Activity",
"latestUser": "Latest User",
"latestApp": "Latest App",
"none": "—",
"newUsers7d": "New users (7d)",
"vsPrev7d": "Previous 7d: {{count}}",
"newUsersInRange": "New users · {{range}}",
"vsPrevRange": "{{range}}: {{count}}",
"activeServices": "Active services",
"inactiveServices": "Inactive: {{count}}",
"signupsTrend": "Sign-ups",
"last7Days": "Last 7 days",
"appOpensTrend": "App opens",
"appOpensSummary": "{{count}} total · {{delta}}",
"appOpensSummaryRanged": "{{count}} in {{range}} · {{delta}}",
"servicesCreatedTrend": "Services added",
"servicesCreatedSummary": "{{count}} added",
"servicesCreatedSummaryRanged": "{{count}} in {{range}}",
"trends": "Trends",
"rangeSelector": "Time range",
"range": {
"7d": "Last 7 days",
"30d": "Last 30 days",
"90d": "Last 90 days",
"custom": "Custom range",
"customLabel": "{{from}} {{to}}"
},
"prevRange": {
"7d": "Previous 7 days",
"30d": "Previous 30 days",
"90d": "Previous 90 days",
"custom": "Previous {{count}} days"
},
"customRange": {
"from": "From",
"to": "To",
"apply": "Apply",
"invalid": "Pick a valid date range",
"loadError": "Couldn't load stats for the selected dates. Please check the range and try again."
},
"topApps": "Top apps",
"topAppsSubtitle": "By opens in {{range}}",
"mostActiveUsers": "Most active users",
"mostActiveUsersSubtitle": "By app opens in {{range}}",
"leaderboardEmpty": "No activity yet",
"openCount": "{{count}} opens",
"viewAppDetails": "View details for {{name}}",
"viewUserDetails": "View details for {{name}}",
"drillIn": {
"loading": "Loading…",
"appTitle": "Recent opens · {{name}}",
"userTitle": "Recent opens · {{name}}",
"subtitle": "{{count}} opens in {{range}}",
"empty": "No opens in this range",
"loadError": "Couldn't load recent opens.",
"editApp": "Edit app",
"viewUser": "View user",
"loadMore": "Load more",
"loadMoreError": "Couldn't load more opens.",
"shownOf": "Showing {{shown}} of {{total}}"
}
}
},
"notFound": {
"title": "404 — Page Not Found",
"description": "The page you are looking for does not exist."
},
"common": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"edit": "Edit",
"add": "Add",
"close": "Close",
"loading": "Loading...",
"error": "An error occurred",
"success": "Success",
"language": "العربية",
"appName": "TeaBoy OS"
},
"notes": {
"title": "Notes",
"searchPlaceholder": "Search notes",
"labels": "Labels",
"manageLabels": "Manage labels",
"newLabel": "New label",
"noLabelsYet": "No labels yet",
"allLabels": "All",
"tabs": { "active": "Notes", "archived": "Archived" },
"pinned": "Pinned",
"others": "Others",
"empty": "Your notes will appear here",
"emptyArchived": "No archived notes",
"takeNote": "Take a note...",
"titlePlaceholder": "Title",
"contentPlaceholder": "Take a note...",
"save": "Save",
"pin": "Pin",
"archive": "Archive",
"unarchive": "Unarchive",
"delete": "Delete",
"deleteConfirm": "Delete this note?",
"deleteLabelConfirm": "Delete this label?",
"editTitle": "Edit note"
}
}