874 lines
37 KiB
TypeScript
874 lines
37 KiB
TypeScript
export const en = {
|
|
title: "Qlockify",
|
|
logout: "Logout",
|
|
logoutToast: "Successfully logged out!",
|
|
confirmLogoutTitle: "Confirm Logout",
|
|
confirmLogoutMessage: "Are you sure you want to log out of your account?",
|
|
confirmLeave: "You have unsaved changes. Are you sure you want to leave?",
|
|
cancel: "Cancel",
|
|
save: "Save",
|
|
lightMode: "Light Mode",
|
|
darkMode: "Dark Mode",
|
|
settings: "Settings",
|
|
loadingText: "Loading...",
|
|
loading: "Loading...",
|
|
add: "Add",
|
|
create: "Create",
|
|
remove: "Remove",
|
|
noMoreResults: "No more results.",
|
|
|
|
actions: {
|
|
create: "Create",
|
|
view: "View",
|
|
edit: "Edit",
|
|
delete: "Delete",
|
|
cancel: "Cancel",
|
|
},
|
|
|
|
login: {
|
|
welcome: (title: string = "Qlockifiy") => `Welcome to ${title}`,
|
|
loginTitle: "Sign in to your account",
|
|
loginDescription: "Enter your mobile number and we will send a one-time code.",
|
|
loginCta: "Login",
|
|
createAccount: "Create account",
|
|
haveNoAccount: "Need an account?",
|
|
haveAccount: "Already have an account?",
|
|
loginOtpTitle: "Verify your login code",
|
|
passwordLoginTitle: "Login with password",
|
|
passwordLoginDescription: (mobile: string) => `Enter the password for ${mobile}`,
|
|
usePasswordInstead: "Use password instead",
|
|
useOtpInstead: "Use OTP instead",
|
|
backToMobile: "Back to mobile step",
|
|
backToPasswordLogin: "Back to password login",
|
|
forgotPassword: "Forgot password?",
|
|
signupTitle: "Create your account",
|
|
signupDescription: "Start with your mobile number to receive a verification code.",
|
|
sendSignupCode: "Send verification code",
|
|
signupVerifyTitle: "Verify your mobile number",
|
|
continueToPassword: "Continue to password",
|
|
signupPasswordTitle: "Set your password",
|
|
signupPasswordDescription: "Choose a password for your new account.",
|
|
createAccountPasswordCta: "Create account",
|
|
forgotPasswordTitle: "Recover your password",
|
|
forgotPasswordDescription: "Enter your mobile number and we will send a verification code for password reset.",
|
|
sendResetCode: "Send reset code",
|
|
forgotPasswordVerifyTitle: "Enter your reset code",
|
|
continueToResetPassword: "Continue to reset password",
|
|
resetPasswordTitle: "Choose a new password",
|
|
resetPasswordDescription: "Set a new password for your account and confirm it.",
|
|
resetPasswordCta: "Reset password",
|
|
newPasswordPlaceholder: "New password",
|
|
confirmPasswordPlaceholder: "Confirm password",
|
|
passwordMismatch: "The password confirmation does not match.",
|
|
passwordRequirements:
|
|
"Password must be at least 8 characters and include at least one lowercase letter, one uppercase letter, one digit, and one symbol.",
|
|
passwordReuse: "New password must be different from your previous password.",
|
|
enterPassword: "Enter your password",
|
|
verifyNumber: "Verify your number",
|
|
enterMobileDesc: "Enter your mobile number to continue",
|
|
signInDesc: "Sign in using your account password",
|
|
sentCodeDesc: (mobile: string) => `We sent a 5-digit code to ${mobile}`,
|
|
mobilePlaceholder: "Mobile Number (e.g. 09123456789)",
|
|
continueWithPassword: "Continue with Password",
|
|
continueWithGoogle: "Continue with Google",
|
|
orContinueWith: "Or continue with",
|
|
otpLogin: "OTP Login",
|
|
register: "Register",
|
|
passwordPlaceholder: "Password",
|
|
signIn: "Sign In",
|
|
back: "Back",
|
|
otpPlaceholder: "5-digit code",
|
|
verifyAndContinue: "Verify & Continue",
|
|
sendingOtp: "Sending code...",
|
|
verifyingOtp: "Verifying code...",
|
|
resendOtp: "Resend code",
|
|
otpExpiresIn: (time: string) => `Code expires in ${time}`,
|
|
otpExpired: "This code has expired. Request a new code to continue.",
|
|
terms: "By clicking continue, you agree to our Terms of Service and Privacy Policy.",
|
|
brandingQuote: "Manage your time and workspaces efficiently with our minimal, fast, and secure platform.",
|
|
toasts: {
|
|
enterMobile: "Please enter your mobile number",
|
|
verifySent: "Verification code sent!",
|
|
failedOtp: "Failed to send OTP",
|
|
fillAll: "Please fill all fields",
|
|
successLogin: "Successfully logged in!",
|
|
accountCreated: "Account created successfully!",
|
|
failedSignup: "Failed to complete sign up",
|
|
invalidCreds: "Invalid credentials",
|
|
enterOtp: "Please enter the OTP code",
|
|
invalidOtp: "Invalid OTP code",
|
|
passwordResetSuccess: "Password reset successfully.",
|
|
passwordResetFailed: "Failed to reset password.",
|
|
},
|
|
throttle: {
|
|
title: "Too many attempts",
|
|
genericMessage: (time: string) => `Too many requests. Try again in ${time}.`,
|
|
otpSendMessage: (time: string) => `Too many OTP requests. Try again in ${time}.`,
|
|
passwordLoginMessage: (time: string) => `Too many password login attempts. Try again in ${time}.`,
|
|
otpLoginMessage: (time: string) => `Too many OTP login attempts. Try again in ${time}.`,
|
|
countdownLabel: (time: string) => `Retry in ${time}`,
|
|
fallback: "Too many requests. Please wait and try again.",
|
|
},
|
|
google: {
|
|
loadingTitle: "Completing Google sign in",
|
|
loadingDescription: "We are validating your Google account and preparing the next step.",
|
|
collectMobileTitle: "Finish your account setup",
|
|
collectMobileDescription: (email: string) =>
|
|
`Google verified ${email}. Enter your mobile number to finish creating your account.`,
|
|
existingEmailClaimDescription: (email: string, mobileHint: string) =>
|
|
`Google verified ${email}. Enter the mobile number already connected to this account (${mobileHint}) to confirm ownership.`,
|
|
claimTitle: "Verify your existing account",
|
|
claimDescription: (mobile: string) =>
|
|
`An account with ${mobile} already exists. Enter the verification code sent to that number to attach Google.`,
|
|
mobileClaimDescription: (mobile: string) =>
|
|
`A mobile-only account with ${mobile} already exists. Verify the code sent to that number to attach Google and keep that account.`,
|
|
errorTitle: "Google sign in could not be completed",
|
|
cancelled: "Google sign in was cancelled before it could be completed.",
|
|
missingFlow: "The Google sign-in flow is missing or has expired.",
|
|
loadFailed: "We could not load your Google sign-in state.",
|
|
callbackFailed: "We could not complete Google sign in. Please try again.",
|
|
tokenExchangeFailed: "Google sign in is temporarily unavailable. Please try again in a few minutes.",
|
|
profileLookupFailed: "We could not load your Google profile. Please try again.",
|
|
completeFailed: "We could not finish your Google account setup.",
|
|
claimOtpSent: "Verification code sent successfully.",
|
|
googleAccount: "Google account",
|
|
mobileHintLabel: (mobileHint: string) => `Expected mobile: ${mobileHint}`,
|
|
completeButton: "Continue and create account",
|
|
verifyClaimButton: "Verify and continue",
|
|
resendClaimOtp: "Resend verification code",
|
|
restartGoogle: "Start Google sign in again",
|
|
},
|
|
},
|
|
|
|
loginTerms: {
|
|
prefix: "By logging in, you agree to our ",
|
|
link: "Terms of Service and Privacy Policy",
|
|
suffix: ""
|
|
},
|
|
|
|
rateLimit: {
|
|
eyebrow: "Request limit reached",
|
|
title: "Please wait before trying again",
|
|
message: "You have sent too many requests. Access is temporarily locked until the cooldown finishes.",
|
|
cooldownLabel: "Cooldown",
|
|
waitingMessage: (time: string) => `Requests are blocked for now.`,
|
|
finishedMessage: "The cooldown has finished. You can continue now.",
|
|
continue: "Continue",
|
|
continueCooldown: (time: string) => `Continue in ${time}`,
|
|
ready: "Ready",
|
|
},
|
|
|
|
terms: {
|
|
back: "Back",
|
|
title: "Terms of Service and Privacy Policy",
|
|
lastUpdated: "Last Updated: March 12, 2026",
|
|
sections: {
|
|
acceptance: {
|
|
title: "1. Acceptance of Terms",
|
|
content: "By accessing and using Qlockify, you agree to be bound by these Terms of Service and all applicable laws and regulations. If you do not agree with any of these terms, you are prohibited from using or accessing this site."
|
|
},
|
|
license: {
|
|
title: "2. User License and Responsibilities",
|
|
items: [
|
|
"You must provide accurate, current, and complete information during the registration process.",
|
|
"You are responsible for maintaining the security of your account and password.",
|
|
"You may not use the service for any illegal or unauthorized purpose.",
|
|
"Your use of the service must not violate any laws in your jurisdiction."
|
|
]
|
|
},
|
|
privacy: {
|
|
title: "3. Privacy Policy & Data Collection",
|
|
p1: "We take your privacy seriously. We collect information to provide better services to our users. The types of personal data we collect include:",
|
|
personalLabel: "Personal Information",
|
|
personalText: "Name, email address, phone number, and birth date provided during registration or profile updates.",
|
|
usageLabel: "Usage Data",
|
|
usageText: "Information on how the service is accessed and used, including timestamps and device metrics.",
|
|
p2: "We do not sell, trade, or rent your personal identification information to others. We employ industry-standard security measures to protect against unauthorized access, alteration, disclosure, or destruction of your personal data."
|
|
},
|
|
liability: {
|
|
title: "4. Limitation of Liability",
|
|
content: "In no event shall Qlockify or its suppliers be liable for any damages (including, without limitation, damages for loss of data or profit, or due to business interruption) arising out of the use or inability to use the materials on the platform."
|
|
},
|
|
modifications: {
|
|
title: "5. Modifications",
|
|
content: "We may revise these terms of service at any time without notice. By using this website, you are agreeing to be bound by the then-current version of these terms of service."
|
|
},
|
|
},
|
|
},
|
|
|
|
profile: {
|
|
title: "User Profile",
|
|
firstName: "First Name",
|
|
lastName: "Last Name",
|
|
email: "Email",
|
|
description: "Description",
|
|
mobileNumber: "Mobile Number",
|
|
birthDate: "Birth Date",
|
|
yearsOld: "Years Old",
|
|
dateJoined: "Date Joined",
|
|
editInfo: "Edit Info",
|
|
changePicture: "Change Picture",
|
|
save: "Save",
|
|
cancel: "Cancel",
|
|
upload: "Upload",
|
|
remove: "Remove",
|
|
imageInput: "Click to select or drag & drop",
|
|
password: {
|
|
trigger: "Change password",
|
|
title: "Change password",
|
|
description: "Enter your current password and choose a new one.",
|
|
currentPassword: "Current password",
|
|
newPassword: "New password",
|
|
confirmPassword: "Confirm new password",
|
|
submit: "Save password",
|
|
saving: "Saving...",
|
|
toasts: {
|
|
success: "Password changed successfully.",
|
|
error: "Failed to change password.",
|
|
},
|
|
},
|
|
toasts: {
|
|
successEdit: "Profile updated successfully!",
|
|
successImage: "Profile picture updated!",
|
|
successRemoveImage: "Profile picture removed!",
|
|
error: "Something went wrong!"
|
|
}
|
|
},
|
|
|
|
workspace: {
|
|
title: "Workspace Management",
|
|
createNew: "Create New Workspace",
|
|
manage: "Manage Workspaces",
|
|
nameLabel: "Workspace Name",
|
|
namePlaceholder: "Enter workspace name",
|
|
descriptionLabel: "Description",
|
|
descriptionPlaceholder: "Enter description (optional)",
|
|
thumbnailLabel: "Thumbnail",
|
|
uploadImage: "Click to upload image",
|
|
removeImage: "Remove image",
|
|
thumbnailInvalidType: "Unsupported image type. Use JPG, PNG, or WebP.",
|
|
thumbnailMaxSizeError: "Image size must be 2MB or less.",
|
|
searchMemberPlaceholder: "Search exact mobile (e.g. 09123456789)",
|
|
addMember: "Add Member",
|
|
roleAdmin: "Admin",
|
|
roleMember: "Member",
|
|
userNotFound: "User not found",
|
|
userAlreadyAdded: "User already added",
|
|
inviteMembers: "Invite Members (Exact Mobile Number)",
|
|
selectedMembers: "Selected Members",
|
|
creating: "Creating...",
|
|
submit: "Create",
|
|
cancel: "Cancel",
|
|
loading: "Loading...",
|
|
confirmDelete: "Are you sure you want to delete this workspace?",
|
|
deleteError: "Error deleting workspace",
|
|
subtitle: "Manage your workspaces",
|
|
noDescription: "No description",
|
|
emptyState: "You are not a member of any workspace.",
|
|
noWorkspaceSearch: "Try adjusting your search query.",
|
|
noWorkspace: "No workspaces found.",
|
|
createTitle: "Create Workspace",
|
|
editTitle: "Edit Workspace",
|
|
detailTitle: "Workspace Details",
|
|
save: "Save",
|
|
create: "Create",
|
|
noWorkspaceTitle: "Welcome!",
|
|
noWorkspaceDesc: "Please create your first workspace.",
|
|
back: "Back to Workspaces",
|
|
roleLabel: "Your Role",
|
|
openReports: "Open reports",
|
|
statsMembers: "Members",
|
|
statsRates: "Rates set",
|
|
statsOwnersAdmins: "Owners & admins",
|
|
statsGuests: "Guests",
|
|
membersSectionTitle: "Members",
|
|
membersSectionSubtitle: "People in this workspace and their current roles.",
|
|
projectRateHint: "Project-specific user rates can be managed from the Projects page. Open a project and use its access modal to set a custom rate that overrides the workspace rate for that project.",
|
|
membersLocked: "Only owners and admins can view the full member list.",
|
|
manageMembers: "Manage members",
|
|
mobileNumber: "Mobile Number",
|
|
youLabel: "You",
|
|
resourcesTitle: "Resources",
|
|
resourceOpen: "Open",
|
|
roleDistributionTitle: "Role distribution",
|
|
unknownMember: "Unknown member",
|
|
roles: {
|
|
owner: "Owner",
|
|
admin: "Admin",
|
|
member: "Member",
|
|
guest: "Guest",
|
|
},
|
|
createdSuccess: "Workspace created successfully",
|
|
updatedSuccess: "Workspace updated successfully",
|
|
fetchError: "Failed to load workspace data",
|
|
remove: "Remove",
|
|
noUsersFound: "No user found",
|
|
selectRole: "Select Role",
|
|
add: "Add",
|
|
searchPlaceholder: "Seach Workspaces...",
|
|
orderByUpdatedDesc: "Recently Updated",
|
|
orderByCreatedDesc: "Newest First",
|
|
orderByCreatedAsc: "Oldest First",
|
|
orderByName: "Name (A-Z)",
|
|
deleteSuccess: "Workspace deleted successfully",
|
|
deleteTitle: "Delete Workspace",
|
|
deleteWarning: "To confirm deletion, please type the workspace name:",
|
|
members: "Members",
|
|
searchUser: "Search user by mobile number",
|
|
searching: "Searching...",
|
|
noMembers: "No members found.",
|
|
removeMemberTitle: "Remove member",
|
|
confirmDeleteTitle: "Remove Member",
|
|
confirmDeleteMessage: "Are you sure you want to remove this member from the workspace?",
|
|
successCreate: "Workspace created successfully.",
|
|
toast: {
|
|
successCreate: "Workspace created successfully.",
|
|
errorCreate: "Failed to create workspace.",
|
|
successUpdate: "Workspace updated successfully.",
|
|
errorUpdate: "Failed to update workspace.",
|
|
successAdd: "Member added successfully.",
|
|
errorAdd: "Failed to add member.",
|
|
successRemove: "Member removed successfully.",
|
|
errorRemove: "Failed to remove member.",
|
|
successRole: "Role updated successfully.",
|
|
errorRole: "Failed to update role.",
|
|
errorLoad: "Failed to load workspace data.",
|
|
cannotAddSelf: "You are automatically the owner.",
|
|
},
|
|
onlyNumbersAllowed: "Only numbers are allowed for mobile number.",
|
|
weekTotal: "Week Total"
|
|
},
|
|
|
|
clients: {
|
|
title: "Clients",
|
|
description: (workspaceName: string) => `Manage clients for ${workspaceName}`,
|
|
addClient: "Add Client",
|
|
searchPlaceholder: "Search clients...",
|
|
noClients: "No clients found",
|
|
noClientsSearch: "Try adjusting your search query.",
|
|
noClientsAdd: "Add your first client to get started.",
|
|
addedOn: "Added",
|
|
selectWorkspace: "Please select a workspace first.",
|
|
modalTitle: "Create New Client",
|
|
clientName: "Client Name",
|
|
clientNamePlaceholder: "e.g. Acme Corp",
|
|
notes: "Notes",
|
|
notesPlaceholder: "Optional details...",
|
|
create: "Create",
|
|
cancel: "Cancel",
|
|
editClient: "Edit Client",
|
|
deleteConfirmTitle: "Delete Client",
|
|
deleteConfirmMessage: (name: string) => `Are you sure you want to delete ${name}?`,
|
|
delete: "Delete",
|
|
saveChanges: "Save Changes",
|
|
createSuccess: "Client created successfully.",
|
|
updateSuccess: "Client updated successfully.",
|
|
deleteSuccess: "Client deleted successfully.",
|
|
errors: {
|
|
createFailed: "Failed to create client",
|
|
fetchFailed: "Failed to fetch clients",
|
|
updateFailed: "Failed to update client",
|
|
deleteFailed: "Failed to delete client",
|
|
},
|
|
},
|
|
|
|
pagination: {
|
|
perPage: "per page",
|
|
showing: "Showing",
|
|
to: "to",
|
|
of: "of",
|
|
previous: "Previous",
|
|
page: "Page",
|
|
next: "Next",
|
|
},
|
|
|
|
sidebar: {
|
|
timesheet: "Timesheet",
|
|
reports: "Reports",
|
|
logs: "Logs",
|
|
workspaces: 'Workspaces',
|
|
clients: 'Clients',
|
|
projects: "Projects",
|
|
tags: "Tags",
|
|
expand: 'Expand',
|
|
collapse: 'Collapse',
|
|
},
|
|
|
|
landing: {
|
|
brandLabel: "Operating system for time",
|
|
eyebrow: "Built for high-discipline teams that need clean time intelligence",
|
|
nav: {
|
|
demo: "Product demo",
|
|
features: "Core capabilities",
|
|
workflow: "How it works",
|
|
},
|
|
actions: {
|
|
switchToEnglish: "English",
|
|
switchToPersian: "فارسی",
|
|
signIn: "Sign in",
|
|
openApp: "Open app",
|
|
openWorkspace: "Open workspace",
|
|
startNow: "Start tracking with control",
|
|
watchDemo: "See the product demo",
|
|
readTerms: "Read terms",
|
|
},
|
|
hero: {
|
|
titleTop: "Turn every working hour into a reliable operating signal.",
|
|
titleAccent: "Qlockify makes time visible, accountable, and billable.",
|
|
description:
|
|
"A focused workspace for modern teams that need fast time capture, trustworthy project tracking, structured reports, and a log trail that management can actually use.",
|
|
},
|
|
metrics: {
|
|
capture: "cleaner billable capture",
|
|
visibility: "faster reporting visibility",
|
|
decision: "from raw entries to management context",
|
|
},
|
|
trust: {
|
|
first: "Precise timers with manual control when needed",
|
|
second: "Workspace permissions, logs, and rate-aware reporting",
|
|
third: "Built for agencies, consultancies, product teams, and operators",
|
|
},
|
|
capabilities: {
|
|
time: {
|
|
title: "Capture work without friction",
|
|
description:
|
|
"Start a timer, adjust historical entries, and keep project and tag context attached to every hour without slowing the team down.",
|
|
},
|
|
reports: {
|
|
title: "Read the business in minutes",
|
|
description:
|
|
"See daily output, billable performance, project distribution, and exportable report packs without spreadsheet cleanup.",
|
|
},
|
|
control: {
|
|
title: "Keep operations explainable",
|
|
description:
|
|
"Track who changed what, keep workspace roles explicit, and give management a cleaner operational trail than ad hoc chat or manual files.",
|
|
},
|
|
},
|
|
demo: {
|
|
timerTag: "Live timer",
|
|
timerTitle: "Current execution window",
|
|
timerText: "Design system refinement synced to the correct project, tags, and billable rate.",
|
|
panelLabel: "Interactive product preview",
|
|
panelTitle: "One surface for tracking, reporting, and operational clarity",
|
|
runningCard: "Active entry",
|
|
currentTask: "Enterprise landing page rollout",
|
|
currentTaskMeta: "Project: Qlockify Marketing · Tags: Design, Review, Delivery",
|
|
billableLabel: "Live billable rate",
|
|
reportCard: "Daily report trend",
|
|
opsCard: "Operational health",
|
|
opsLabels: ["Coverage", "Team focus", "Billing readiness"],
|
|
logCard: "Recent workspace activity",
|
|
logItems: [
|
|
{ title: "Rate updated for product design", meta: "Owner action · 3 minutes ago" },
|
|
{ title: "Client-facing project moved to archived", meta: "Admin action · 18 minutes ago" },
|
|
{ title: "Historic tag preserved on edited entry", meta: "Member action · 41 minutes ago" },
|
|
],
|
|
outcomeTag: "Management result",
|
|
outcomeText: "Less ambiguity at month end, fewer missing billable hours, and faster operational reviews.",
|
|
},
|
|
workflowTag: "Operational workflow",
|
|
workflowTitle: "A tighter loop from raw effort to usable management data.",
|
|
workflowDescription:
|
|
"Qlockify is designed to keep the path short: capture accurately, structure context once, and reuse the result everywhere from timesheets to reports to workspace-level decisions.",
|
|
workflow: {
|
|
capture: "Capture time at the source with project, tags, and billing context attached immediately.",
|
|
structure: "Keep every workspace action, membership change, and rate update visible and reviewable.",
|
|
improve: "Review daily and monthly performance with reports that are ready to export or act on.",
|
|
},
|
|
finalCtaTag: "Ready for production teams",
|
|
finalCtaTitle: "If your team sells expertise or ships client work, your time system should look this serious.",
|
|
finalCtaDescription:
|
|
"Open the app, create a workspace, and see how fast your reporting discipline improves when the product stops leaking context.",
|
|
},
|
|
|
|
ordering: {
|
|
createdAtDesc: "Newest First",
|
|
createdAt: "Olders First",
|
|
updatedAtDesc: "Recently Updated",
|
|
name: "Name (A-Z)",
|
|
nameDesc: "Name (Z-A)",
|
|
},
|
|
|
|
projects: {
|
|
title: "Projects",
|
|
description: (workspaceName: string) => `Manage projects for ${workspaceName}`,
|
|
active: "Active Projects",
|
|
archived: "Archived Projects",
|
|
createNew: "Create New",
|
|
searchPlaceholder: "Search projects...",
|
|
selectWorkspace: "Please select a workspace first.",
|
|
titlePlaceholder: "Enter title",
|
|
descriptionPlaceholder: "Enter desription",
|
|
titleLabel: "Title",
|
|
clientLabel: "Client",
|
|
colorLabel: "Color",
|
|
descriptionLabel: "Description",
|
|
loading: "Loading...",
|
|
client: "Client",
|
|
noClient: "No client",
|
|
emptyState: "No projects found",
|
|
noProjectsSearch: "Try adjusting your search query.",
|
|
deleteTitle: "Delete Project",
|
|
deleteWarning: "To confirm deletion, please type the project name:",
|
|
deleteSuccess: "Project deleted successfully",
|
|
deleteError: "Failed to delete project",
|
|
cancel: "Cancel",
|
|
create: "Create",
|
|
createProject: "Create New Project",
|
|
editProject: "Edit Project",
|
|
restore: "Restore",
|
|
archive: "Archive",
|
|
archiveSuccess: "Project archived successfully.",
|
|
restoreSuccess: "Project restored successfully.",
|
|
fetchError: "Failed to fetch projects.",
|
|
clientFetchError: "Failed to load clients.",
|
|
filterClients: "Filter by client",
|
|
clearClientFilters: "Clear filters",
|
|
namePlaceholder: "Project name...",
|
|
teamMembers: "Team Members",
|
|
manageAccess: "Projects & Rates",
|
|
accessModalTitle: "Projects & Rates",
|
|
accessModalDescription: "Manage project access for members and guests, and set project-specific rates for any workspace user.",
|
|
accessMemberLabel: "User",
|
|
accessNoMembers: "No workspace users were found.",
|
|
accessNoProjects: "No projects found.",
|
|
accessSelectVisible: "Select all visible",
|
|
accessClearSelection: "Clear selection",
|
|
accessSelectClientProjects: "Select all projects for client",
|
|
accessGrant: "Grant selected",
|
|
accessRevoke: "Revoke selected",
|
|
accessOn: "Has access",
|
|
accessOff: "No access",
|
|
accessGrantSuccess: "Project access granted.",
|
|
accessRevokeSuccess: "Project access revoked.",
|
|
accessLoadError: "Failed to load project access state.",
|
|
accessSaveError: "Failed to update project access.",
|
|
implicitAccessHint: "Owners and admins always have access to all projects. You can still set project-specific rate overrides here.",
|
|
creator: "Creator",
|
|
addUser: "Add user by mobile",
|
|
addFromWorkspace: "Add from workspace",
|
|
searchMembers: "Search members...",
|
|
addAllWorkspaceMembers: "Add all workspace members",
|
|
confirmDeleteTitle: "Remove Member",
|
|
confirmDeleteDesc: "Are you sure you want to remove this member from the project?",
|
|
createSuccess: "Project created successfully.",
|
|
createError: "Failed to create project.",
|
|
updateSuccess: "Project updated successfully.",
|
|
updateError: "Failed to update project.",
|
|
edit: "Edit Project",
|
|
memberAlreadyAdded: "This user is already on the project team.",
|
|
roles: {
|
|
member: "Member",
|
|
manager: "Manager"
|
|
},
|
|
projectMembers: "Project Members",
|
|
removeAllWorkspaceMembers: "Remove All",
|
|
searchWorkspaceMembers: "Search by name or enter mobile number...",
|
|
userNotFound: "No user found with this mobile number.",
|
|
alreadyInProject: "Already Added",
|
|
addToProject: "Add to Project",
|
|
noWorkspaceMembers: "No members found.",
|
|
},
|
|
|
|
tags: {
|
|
title: "Tags",
|
|
description: (workspaceName: string) => `Manage tags for ${workspaceName}`,
|
|
create: "Create Tag",
|
|
createTitle: "Create Tag",
|
|
editTitle: "Edit Tag",
|
|
deleteTitle: "Delete Tag",
|
|
deleteConfirmMessage: (name: string) => `Are you sure you want to delete ${name}?`,
|
|
searchPlaceholder: "Search tags...",
|
|
nameLabel: "Tag Name",
|
|
namePlaceholder: "e.g. Design",
|
|
colorLabel: "Color",
|
|
emptyState: "No tags found",
|
|
noTagsSearch: "Try adjusting your search query.",
|
|
selectWorkspace: "Please select a workspace first.",
|
|
fetchError: "Failed to load tags",
|
|
createSuccess: "Tag created successfully.",
|
|
updateSuccess: "Tag updated successfully.",
|
|
saveError: "Failed to save tag.",
|
|
deleteSuccess: "Tag deleted successfully.",
|
|
deleteError: "Failed to delete tag.",
|
|
},
|
|
|
|
rates: {
|
|
workspaceSectionTitle: "Workspace User Rates",
|
|
projectSectionTitle: "Project User Rates",
|
|
myRatesTitle: "My rates",
|
|
myRatesHint: "Project-specific rates override your workspace rate in the current workspace.",
|
|
workspaceRate: "Workspace rate",
|
|
workspaceRateHint: "This is your default rate unless a project-specific rate overrides it.",
|
|
projectOverride: "Project override",
|
|
projectOverrides: "Project overrides",
|
|
accessibleProjects: "Accessible projects",
|
|
workspaceFallbackProjects: "Using workspace rate",
|
|
projectOverrideHint: "Only projects with custom overrides are listed here. Other accessible projects use your workspace rate.",
|
|
projectOverrideEmpty: "You do not have any project-specific rate overrides in this workspace.",
|
|
myRatesEmpty: "No rates are available for this workspace yet.",
|
|
inheritsWorkspaceRate: "Inherits workspace rate",
|
|
noRate: "No rate",
|
|
hourlyRatePlaceholder: "0.00",
|
|
currencyPlaceholder: "USD",
|
|
searchUnitPlaceholder: "Search unit...",
|
|
removeRate: "Remove rate",
|
|
workspaceSaveSuccess: "Workspace user rate saved.",
|
|
workspaceSaveError: "Failed to save workspace user rate.",
|
|
workspaceRemoveSuccess: "Workspace user rate removed.",
|
|
workspaceRemoveError: "Failed to remove workspace user rate.",
|
|
projectSaveSuccess: "Project user rate saved.",
|
|
projectSaveError: "Failed to save project user rate.",
|
|
projectRemoveSuccess: "Project user rate removed.",
|
|
projectRemoveError: "Failed to remove project user rate.",
|
|
},
|
|
|
|
timesheet: {
|
|
title: "Timesheet",
|
|
description: (workspaceName: string) => `Track time inside ${workspaceName}`,
|
|
selectWorkspace: "Please select a workspace first.",
|
|
addEntry: "Add Entry",
|
|
startTimer: "Start Timer",
|
|
stopTimer: "Stop Timer",
|
|
timerRunning: "Timer Running",
|
|
runningLabel: "Current timer",
|
|
runningBadge: "Running",
|
|
noRunningEntry: "No running entry",
|
|
searchPlaceholder: "Search time entries...",
|
|
orderingNewest: "Newest first",
|
|
orderingOldest: "Oldest first",
|
|
emptyState: "No time entries found",
|
|
emptyStateDescription: "Start the timer or add a manual entry to get started.",
|
|
noEntriesSearch: "Try adjusting your search query or filters.",
|
|
emptyDescription: "No description",
|
|
createTitle: "Add Time Entry",
|
|
startTitle: "Start Timer",
|
|
editTitle: "Edit Time Entry",
|
|
createSuccess: "Time entry created successfully.",
|
|
startSuccess: "Timer started successfully.",
|
|
updateSuccess: "Time entry updated successfully.",
|
|
saveError: "Failed to save time entry.",
|
|
stopSuccess: "Timer stopped successfully.",
|
|
stopError: "Failed to stop timer.",
|
|
deleteSuccess: "Time entry deleted successfully.",
|
|
deleteError: "Failed to delete time entry.",
|
|
fetchError: "Failed to load time entries.",
|
|
optionsError: "Failed to load projects and tags.",
|
|
descriptionLabel: "Description",
|
|
descriptionPlaceholder: "What are you working on?",
|
|
projectLabel: "Project",
|
|
noProject: "No project",
|
|
startLabel: "Start",
|
|
endLabel: "End",
|
|
timeLabel: "Time",
|
|
billable: "Billable",
|
|
noTagsHint: "Create tags first from the Tags page.",
|
|
clearFilters: "Clear filters",
|
|
customFromLabel: "From date",
|
|
customToLabel: "To date",
|
|
allClientsLabel: "All clients",
|
|
allProjectsLabel: "All projects",
|
|
allTagsLabel: "All tags",
|
|
showFiltersLabel: "Show filters",
|
|
hideFiltersLabel: "Hide filters",
|
|
applyFiltersLabel: "Apply",
|
|
clientFilterPrefix: "Client",
|
|
projectFilterPrefix: "Project",
|
|
tagFilterPrefix: "Tag",
|
|
fromFilterPrefix: "From",
|
|
toFilterPrefix: "To",
|
|
deleteTitle: "Delete Time Entry",
|
|
deleteConfirmMessage: "Are you sure you want to delete this time entry?",
|
|
restartConfirmMessage: "Start a new running timer from this entry?",
|
|
discardConfirmMessage: "Are you sure you want to discard this running timer?",
|
|
searchTagsLabel: "Search tags...",
|
|
noTagsFoundLabel: "No tags found.",
|
|
searchProjectsLabel: "Search projects...",
|
|
noProjectsFoundLabel: "No projects found.",
|
|
deletedProjectLabel: "Deleted project",
|
|
deletedTagLabel: "Deleted tag",
|
|
},
|
|
|
|
reports: {
|
|
title: "Reports",
|
|
description: (workspaceName: string) => `Review activity reports for ${workspaceName}`,
|
|
selectWorkspace: "Please select a workspace first.",
|
|
chartTab: "Chart",
|
|
tableTab: "Table",
|
|
period: "Period",
|
|
periodThisWeek: "This week",
|
|
periodThisMonth: "This month",
|
|
periodThisYear: "This year",
|
|
periodFirstHalf: "First half of year",
|
|
periodSecondHalf: "Second half of year",
|
|
periodCustom: "Custom period",
|
|
fromDate: "From date",
|
|
toDate: "To date",
|
|
user: "User",
|
|
mobile: "Mobile",
|
|
allUsers: "All users",
|
|
searchUsers: "Search users...",
|
|
client: "Client",
|
|
allClients: "All clients",
|
|
searchClients: "Search clients...",
|
|
project: "Project",
|
|
allProjects: "All projects",
|
|
searchProjects: "Search projects...",
|
|
tags: "Tags",
|
|
allTags: "All tags",
|
|
searchTags: "Search tags...",
|
|
name: "Name",
|
|
clear: "Clear",
|
|
apply: "Apply",
|
|
totalHours: "Total hours",
|
|
billableHours: "Billable hours",
|
|
nonBillableHours: "Non-billable hours",
|
|
hourlyRate: "Hourly rate",
|
|
hourlyRates: "Hourly rates",
|
|
workingHours: "Working hours",
|
|
nonWorkingHours: "Non-working hours",
|
|
totalIncome: "Total income",
|
|
projectPercentages: "Project percentages",
|
|
clientPercentages: "Client percentages",
|
|
tagPercentages: "Tag percentages",
|
|
userSummaryTitle: "Summary by user",
|
|
userSummaryDetailsTitle: "User details: {name}",
|
|
userSummaryDetailsDescription: "Review the selected user's rate history and time distribution.",
|
|
rateHistory: "Rate history",
|
|
percentage: "Percentage",
|
|
hourPercentage: "Hour %",
|
|
incomePercentage: "Income %",
|
|
now: "Now",
|
|
chartTitle: "Activity chart",
|
|
totalSeconds: "Total seconds",
|
|
exportExcel: "Export Excel",
|
|
exportPdf: "Export PDF",
|
|
date: "Date",
|
|
details: "Details",
|
|
total: "Total",
|
|
noData: "No data",
|
|
clientsTable: "Clients",
|
|
projectsTable: "Projects",
|
|
tagsTable: "Tags",
|
|
loadError: "Failed to load reports.",
|
|
loadDayDetailsError: "Failed to load day details.",
|
|
loadFiltersError: "Failed to load report filters.",
|
|
exportQueued: "Export queued. You will receive a notification with the download link.",
|
|
exportError: "Failed to queue report export.",
|
|
},
|
|
|
|
logs: {
|
|
eyebrow: "Workspace activity",
|
|
title: "Activity logs",
|
|
description: (workspaceName: string) => `Review what has happened inside ${workspaceName}.`,
|
|
selectWorkspace: "Please select a workspace first.",
|
|
unauthorized: "Only owners and admins can access workspace activity logs.",
|
|
loading: "Loading logs...",
|
|
loadingUsers: "Loading users...",
|
|
loadingDetails: "Loading details...",
|
|
loadError: "Failed to load logs.",
|
|
loadDetailsError: "Failed to load log details.",
|
|
loadFiltersError: "Failed to load log filters.",
|
|
search: "Search",
|
|
searchPlaceholder: "Search logs...",
|
|
section: "Section",
|
|
allSections: "All sections",
|
|
event: "Event",
|
|
allEvents: "All events",
|
|
actor: "Actor",
|
|
allActors: "All actors",
|
|
searchActors: "Search users...",
|
|
ordering: "Ordering",
|
|
newestFirst: "Newest first",
|
|
oldestFirst: "Oldest first",
|
|
fromDate: "From date",
|
|
toDate: "To date",
|
|
clear: "Clear",
|
|
apply: "Apply",
|
|
loadMore: "Load more",
|
|
totalLogs: "Total logs",
|
|
activeFilters: "Active filters",
|
|
latestActivity: "Latest activity",
|
|
resultsCount: (count: number) => `${count} results`,
|
|
empty: "No activity logs found",
|
|
emptyHint: "Adjust your filters or wait for new workspace activity.",
|
|
detailsTitle: "Activity details",
|
|
detailsHint: "Select an activity item to inspect the exact field changes.",
|
|
selectLogHint: "Select a log entry to see its details.",
|
|
target: "Target",
|
|
timestamp: "Timestamp",
|
|
remoteAddress: "Remote address",
|
|
previousValue: "Previous",
|
|
currentValue: "Current",
|
|
changesTitle: "Changes",
|
|
noDetails: "No field-level details are available for this activity.",
|
|
snapshot: "Serialized snapshot",
|
|
unknownActor: "Unknown actor",
|
|
summary: (actor: string, event: string, section: string, target: string) =>
|
|
`${actor} ${event.toLowerCase()} ${target} in ${section.toLowerCase()}`,
|
|
sections: {
|
|
workspace: "Workspace",
|
|
workspace_members: "Workspace members",
|
|
clients: "Clients",
|
|
projects: "Projects",
|
|
tags: "Tags",
|
|
time_entries: "Time entries",
|
|
rates: "Rates",
|
|
report_exports: "Report exports",
|
|
},
|
|
events: {
|
|
create: "Created",
|
|
update: "Updated",
|
|
delete: "Deleted",
|
|
restore: "Restored",
|
|
archive: "Archived",
|
|
unarchive: "Unarchived",
|
|
activate: "Activated",
|
|
deactivate: "Deactivated",
|
|
},
|
|
},
|
|
|
|
notifications: {
|
|
title: "Notifications",
|
|
pageDescription: "Review all notifications and export updates.",
|
|
open: "Open notifications",
|
|
empty: "No notifications yet.",
|
|
emptyUnread: "No unread notifications.",
|
|
loading: "Loading notifications...",
|
|
loadingMore: "Loading more...",
|
|
loadMore: "Load more",
|
|
markAllRead: "Mark all as read",
|
|
viewAll: "View all notifications",
|
|
totalLabel: "Total notifications",
|
|
unreadLabel: "Unread notifications",
|
|
deleteLabel: "Delete notification",
|
|
markSeenError: "Failed to update notification",
|
|
markAllError: "Failed to update notifications",
|
|
deleteError: "Failed to delete notification",
|
|
loadError: "Failed to load notifications",
|
|
openError: "Failed to open notification",
|
|
newTitle: "New notification",
|
|
openAction: "Open",
|
|
summary: (total: number, unread: number) => `${total} total, ${unread} unread`,
|
|
workspaceMembershipAddedTitle: "Added to workspace",
|
|
workspaceMembershipAddedMessage: (actor: string, workspace: string, role: string) =>
|
|
`${actor} added you to ${workspace} as ${role}.`,
|
|
workspaceMembershipRoleChangedTitle: "Workspace role changed",
|
|
workspaceMembershipRoleChangedMessage: (actor: string, workspace: string, previousRole: string, newRole: string) =>
|
|
`${actor} changed your role in ${workspace} from ${previousRole} to ${newRole}.`,
|
|
workspaceMembershipDeactivatedTitle: "Workspace access deactivated",
|
|
workspaceMembershipDeactivatedMessage: (actor: string, workspace: string) =>
|
|
`${actor} deactivated your access to ${workspace}.`,
|
|
workspaceMembershipRemovedTitle: "Removed from workspace",
|
|
workspaceMembershipRemovedMessage: (actor: string, workspace: string) =>
|
|
`${actor} removed you from ${workspace}.`,
|
|
reportExportReadyTitle: "Report export is ready",
|
|
reportExportReadyMessage: (exportType: string, workspace: string, fileName?: string | null) =>
|
|
`Your ${exportType.toUpperCase()} report for ${workspace} is ready${fileName ? `: ${fileName}` : ""}.`,
|
|
reportExportFailedTitle: "Report export failed",
|
|
reportExportFailedMessage: (exportType: string, workspace: string) =>
|
|
`Your ${exportType.toUpperCase()} report for ${workspace} could not be generated.`,
|
|
},
|
|
}
|