/* * Lightweight i18n module. All user-facing strings are collected here so the app * can be translated by swapping or extending the locale object. The current * implementation is English-only; a future iteration could load locale files * dynamically based on a user preference. */ const en = { /* General */ appTitle: 'Check List', appTagline: 'Offline-first proof of concept for template-driven quality reports.', checkingConnection: 'Checking connection', online: 'Online', offline: 'Offline', noChanges: 'No changes', /* Sync */ syncingTemplates: 'Syncing templates', templatesSynced: 'Templates synced', syncFailed: 'Sync failed, using cache', offlineMode: 'Offline mode', /* Reports */ noReportSelected: 'No report selected', noReportSelectedHint: 'Start by syncing templates and creating a local draft.', noLocalReports: 'No local reports yet.', selectTemplate: 'Select a template first', templateNotAvailable: 'Template not available locally', newReportCreated: 'New report created', reportDeleted: 'Report deleted', deleteReportConfirm: 'Delete local report {0}?', draftUpdated: 'Draft updated', statusChanged: 'Status changed', saved: 'Saved {0}', /* Submission */ submitting: 'Submitting report…', submitted: 'Report submitted to server', submitFailed: 'Submission failed', goOnlineToSubmit: 'Go online to submit a report', /* Validation */ readyForExport: 'Ready for export validation', noBlockingIssues: 'No blocking validation issues detected for the current draft.', noValidationIssues: 'No validation issues.', issueCount: '{0} issue(s) to resolve', issueReadyWarning: 'The report is marked ready, but validation still has blocking items.', issueDraftHint: 'Draft save is still allowed, but export should be blocked until these issues are fixed.', templateUnavailable: 'Template unavailable', validationNeedsTemplate: 'Validation cannot run until the template is cached again.', required: 'value is required.', numberInvalid: 'number is invalid.', numberMin: 'must be at least {0}.', imageRequired: 'at least one image is required.', templateMissing: 'Template definition missing for this report version.', /* Attachments */ noImagesAttached: 'No images attached yet.', maxAttachments: 'Only {0} attachment(s) allowed', imageSkipped: 'Image skipped: {0}', imagesUpdated: 'Images updated', attachmentRemoved: 'Attachment removed', unsupportedFileType: 'Unsupported file type: {0}', fileExceedsLimit: 'File exceeds limit: {0}', optimizeFailed: 'Failed to optimize image: {0}', optimizedStillExceeds: 'Optimized image still exceeds limit: {0}', /* Admin */ savingImagePolicy: 'Saving image policy', imagePolicySaved: 'Image policy saved', goOnlineToSave: 'Go online to save admin settings', policyNameRequired: 'Policy name is required', addMimeType: 'Add at least one MIME type', maxFileSizePositive: 'Max file size must be greater than 0', maxWidthPositive: 'Max width must be a positive number', maxHeightPositive: 'Max height must be a positive number', jpegQualityRange: 'JPEG quality must be between 1 and 100', maxAttachmentsPositive: 'Max attachments must be a positive number', /* Template management */ publishingVersion: 'Publishing version…', versionPublished: 'Template version published', publishFailed: 'Failed to publish version', /* Export */ exportStarted: 'Preparing export…', exportComplete: 'Export ready — file downloaded', exportFailed: 'Export failed', noReportToExport: 'Open a report before exporting', noTemplateForExport: 'Template definition needed for export', /* Search */ searchPlaceholder: 'Search reports…', /* Misc */ noTemplatesCached: 'No cached templates available', liveConfig: 'Live server configuration', offlineCachedConfig: 'Offline cached configuration', noImageRulesLoaded: 'No image rules loaded', imagePolicyHint: 'Load server configuration to see image limits and optimization rules.' }; let currentLocale = en; /* * Retrieve a translated string by key. Optional positional parameters replace * {0}, {1}, etc. placeholders. */ export function t(key, ...params) { let text = currentLocale[key] ?? key; for (let i = 0; i < params.length; i++) { text = text.replace(`{${i}}`, String(params[i])); } return text; } export function setLocale(locale) { currentLocale = { ...en, ...locale }; }