/** * English locale. * Key structure must stay identical to zh-CN.ts (see that file for the convention). */ export default { app: { name: 'Online Toolbox', short: 'Toolbox', tagline: 'Runs in your browser. Nothing leaves your device.', footer: { local: 'Runs entirely in the browser', privacy: 'No data uploaded', free: 'Free to use', icpTitle: 'Verify the ICP filing (Ministry of Industry and Information Technology)', }, home: 'Home', backHome: 'Back to home', }, nav: { home: 'Home', browse: 'Browse tools', searchPlaceholder: 'Search tools by name or purpose', searchAria: 'Search tools', commandHint: 'Shortcut', toolsCount: '{count} tools', noResult: 'No matching tools', noResultHint: 'Try another keyword, or browse the categories below.', clearSearch: 'Clear search', menuAria: 'Open navigation', skipToContent: 'Skip to main content', }, palette: { title: 'Quick jump', placeholder: 'Type a tool name, category, or keyword…', empty: 'No matching tools', emptyHint: 'Try keywords like "image", "JSON", or "time".', hintNavigate: 'Select', hintClose: 'Close', hintToggle: 'Toggle theme', groupTool: 'Tools', groupPage: 'Pages', }, theme: { label: 'Theme', light: 'Light', dark: 'Dark', auto: 'System', switchToLight: 'Switch to light mode', switchToDark: 'Switch to dark mode', switchToAuto: 'Follow system setting', current: 'Current theme: {mode}', }, locale: { label: 'Language', 'zh-CN': '简体中文', 'en-US': 'English', 'ja-JP': '日本語', 'ko-KR': '한국어', }, home: { title: 'A toolbox that lives in your browser', desc: '{count} everyday utilities. Every calculation and file operation happens on your own machine.', statTools: 'Available tools', statCategories: 'Categories', statUpload: 'Data uploaded to a server', statUploadValue: '0 bytes', statLocal: 'Processed locally', statLocalValue: 'Everything', statLanguages: 'Languages', statServer: 'Server endpoints', statServerValue: '{count}', searchPlaceholder: 'Search tools, or filter by purpose', resultCount: '{count} tools', filterAll: 'All', emptyTitle: 'No matching tools', emptyHint: 'Try a shorter keyword such as "image", "JSON", or "convert".', resetFilter: 'Reset filters', serverBadge: 'Online', localBadge: 'Local', }, category: { work: { label: 'Everyday work', desc: 'Programming, office text, and file handling', }, dev: { label: 'Developer tools', desc: 'Formatting, conversion, and diffing for developers', }, design: { label: 'Creative', desc: 'Gradients, placeholder images, and ASCII art', }, life: { label: 'Daily life', desc: 'Everyday calculators, lookups, and helpers', }, fun: { label: 'Just for fun', desc: 'Morse code and other small toys', }, online: { label: 'Server tools', desc: 'Powered by our own backend API, needs a network connection', }, }, tool: { 'image-compress': { name: 'Image compressor', desc: 'Compress JPG/PNG/WebP locally with adjustable quality, then download', }, 'image-to-ico': { name: 'Image to ICO', desc: 'Turn PNG/JPG/WebP/SVG into icons with multi-size output and size control', }, 'json-format': { name: 'JSON formatter', desc: 'Format, minify, and validate JSON, then copy the result in one click', }, timestamp: { name: 'Timestamp converter', desc: 'Convert between Unix timestamps and dates, in seconds or milliseconds', }, base64: { name: 'Base64 encoder', desc: 'Encode and decode Base64 text, or convert image files to and from Base64', }, 'jwt-parse': { name: 'JWT decoder', desc: 'Read the header and payload of a JWT, including its expiry', }, cron: { name: 'Cron expression', desc: 'Preview the next run times and build expressions visually', }, 'radix-convert': { name: 'Number base converter', desc: 'Convert between binary, octal, decimal, and hexadecimal', }, hash: { name: 'Hash calculator', desc: 'MD5, SHA1, SHA256, and SHA512 for text or files', }, 'url-parse': { name: 'URL parser', desc: 'Break a URL into protocol, host, path, and query, or build one', }, translate: { name: 'Translation', desc: 'Chinese, English, Japanese, and Korean translation', }, ocr: { name: 'Image OCR', desc: 'Extract text from images locally, Chinese and English supported', }, uuid: { name: 'UUID generator', desc: 'Batch UUID v4 generation, either in-browser or through the backend API', }, 'regex-test': { name: 'Regex tester', desc: 'Test matching, groups, and replacements live with highlighted hits', }, 'case-convert': { name: 'Case converter', desc: 'Switch between camelCase, snake_case, kebab-case, and more', }, 'color-convert': { name: 'Color converter', desc: 'Convert between HEX, RGB, HSL, and HSV with a picker and swatches', }, 'yaml-json': { name: 'YAML ↔ JSON', desc: 'Two-way conversion between YAML and JSON with clear error positions', }, 'word-count': { name: 'Word counter', desc: 'Count characters, CJK glyphs, words, and paragraphs, plus reading time', }, 'zh-convert': { name: 'Chinese converter', desc: 'Convert between Simplified and Traditional Chinese', }, 'image-cropper': { name: 'Image cropper', desc: 'Crop images to a fixed ratio with live preview, export as JPG or PNG', }, qrcode: { name: 'QR code reader', desc: 'Generate QR codes from text or links, and decode them from an image', }, idcard: { name: 'ID card parser', desc: 'Validate a Chinese ID number and read its birth date, gender, and region', }, 'address-parse': { name: 'Address parser', desc: 'Split a Chinese address into province, city, district, and street', }, 'unit-convert': { name: 'Unit converter', desc: 'Eight families of units including length, mass, temperature, and data', }, 'rmb-upper': { name: 'RMB in words', desc: 'Write an amount in formal Chinese capital numerals, including cents', }, 'date-calc': { name: 'Date calculator', desc: 'Date differences, offsets, plus age, zodiac, and constellation', }, 'password-gen': { name: 'Password generator', desc: 'Batch-generate strong random passwords with a strength estimate', }, bmi: { name: 'BMI calculator', desc: 'Body mass index with the Chinese classification and healthy weight range', }, mortgage: { name: 'Mortgage calculator', desc: 'Compare equal-installment and equal-principal loans: payment and total interest', }, 'bill-split': { name: 'Bill splitter', desc: 'Split a shared bill and get a minimal set of transfers to settle up', }, 'random-decision': { name: 'Random decision', desc: 'Draw lots, roll dice, or pick a number when you cannot decide', }, pomodoro: { name: 'Pomodoro timer', desc: 'Focus and break countdowns with a record of completed rounds', }, 'sql-format': { name: 'SQL formatter', desc: 'Beautify SQL with keyword line breaks and clause indentation, live', }, 'text-diff': { name: 'Text diff', desc: 'Compare two texts line by line with added and removed lines highlighted', }, 'json-to-code': { name: 'JSON to code', desc: 'Generate TypeScript interfaces, Go structs, or Python classes from JSON', }, 'gradient-generator': { name: 'Gradient generator', desc: 'Design CSS gradients visually with curated presets, ready to copy', }, 'placeholder-image': { name: 'Placeholder image', desc: 'Custom size and color placeholders, download as PNG or copy SVG', }, 'ascii-art': { name: 'Image to ASCII', desc: 'Turn a photo into ASCII art with adjustable density and inversion', }, 'morse-code': { name: 'Morse code', desc: 'Translate text to and from Morse, and play it back as real beeps', }, 'regex-visual': { name: 'Regex visualizer', desc: 'Break a regular expression into a structure tree with match testing', }, 'markdown-table': { name: 'Markdown table', desc: 'Paste data and get a Markdown or HTML table in one step', }, 'api-builder': { name: 'API request builder', desc: 'Compose a request visually and get ready-to-run fetch or curl code', }, 'gitignore-gen': { name: '.gitignore generator', desc: 'Pick your stack and get the ignore rules you actually need', }, 'code-to-image': { name: 'Code to image', desc: 'Render code as a shareable card image with syntax highlighting', }, 'color-namer': { name: 'Color namer', desc: 'Match a color value to the closest CSS color name', }, 'indent-convert': { name: 'Indent converter', desc: 'Convert between spaces and tabs, with 2, 4, or 8 space widths', }, 'code-stats': { name: 'Code statistics', desc: 'Count total, code, comment, and blank lines', }, 'hello-world': { name: 'Hello World collection', desc: 'Starter code for over 30 programming languages', }, 'json-diff': { name: 'JSON diff', desc: 'Compare two JSON documents key by key: added, removed, changed', }, 'env-parse': { name: 'Env file parser', desc: 'Convert between .env, JSON, and plain key-value pairs', }, 'random-string': { name: 'Random string', desc: 'Generate random strings by length and character set, locally or server-side', }, 'api-status': { name: 'API status', desc: 'Probe the backend endpoints for availability and response time', }, 'exchange-rate': { name: 'Currency converter', desc: 'Live exchange rates for major currencies', }, 'express-query': { name: 'Parcel tracking', desc: 'Look up delivery progress by tracking number', }, 'phone-locate': { name: 'Phone number lookup', desc: 'Find the region and carrier of a mobile number', }, 'ip-info': { name: 'IP information', desc: 'See the IP the server sees, whether it is private, plus your browser details', }, 'network-test': { name: 'Network test', desc: 'Check reachability with HTTP, Ping, TCP, and DNS probes', }, 'speed-test': { name: 'Speed test', desc: 'Measure download and upload throughput and latency', }, }, page: { common: { local: 'Local', server: 'Server', source: 'Compute on', localHint: 'Done inside this browser, no network request', serverHint: 'Calls the backend API, needs a network connection', serverUnavailable: 'Server unavailable: {message}', refresh: 'Refresh', copyResult: 'Copy result', }, 'ip-info': { title: 'IP information', desc: 'Ask the backend which IP it sees, check whether it is a private address, and inspect your local browser environment.', serverTitle: 'Source IP as seen by the server', ipLabel: 'IP address', internal: 'Private address', external: 'Public address', internalHint: 'A private address usually comes from a company or home network, so the server cannot resolve a public location from it.', externalHint: 'This is the public egress IP the server sees. It can differ from your local network if a proxy or NAT is involved.', browserTitle: 'Local environment', timezone: 'Time zone', language: 'Browser language', platform: 'Operating system', screen: 'Screen resolution', viewport: 'Viewport', userAgent: 'User agent', geoTitle: 'Location lookup', geoUnavailable: 'The current backend returns only the IP and the private-address flag, without geolocation data.', }, uuid: { title: 'UUID generator', desc: 'Generate UUIDs in batches, either locally with the browser CSPRNG or through the backend API.', count: 'Count', uppercase: 'Uppercase', noHyphen: 'No hyphens', modeLabel: 'Generation mode', modeLocal: 'Local (UUID v4)', modeServer: 'Server (GoFrame guid)', serverHint: 'The server returns a 32-character ID, or an 8-character short code when requested.', short: 'Short code (8 chars)', resultTitle: 'Results', regenerate: 'Regenerate', copyAll: 'Copy all', }, hash: { title: 'Hash calculator', desc: 'Compute MD5, SHA1, SHA256, and SHA512 for text or files, locally by default.', tabText: 'Text', tabFile: 'File', inputTitle: 'Input text', inputPlaceholder: 'Enter the text to hash', uppercase: 'Uppercase output', compute: 'Compute', clear: 'Clear', uploadTitle: 'Upload a file', uploadTip: 'Drop any file and the hashes are computed automatically', resultTitle: 'Hash results', serverMd5: 'Also compute MD5 on the server', serverMd5Hint: 'Runs MD5 once more through the backend so you can check both implementations agree.', compareTitle: 'Side-by-side comparison', compareSame: 'Both sides match', compareDiff: 'The two sides disagree, check the source', compareServerFailed: 'Server-side MD5 failed: {message}', errEmpty: 'Enter some text to hash first', errCompute: 'Computation failed, please try again', errFile: 'Could not read the file, please try again', }, timestamp: { title: 'Timestamp converter', desc: 'Convert between timestamps and Beijing time (UTC+8), in seconds or milliseconds, and read the server clock.', tabTs2Date: 'Timestamp → date', tabDate2Ts: 'Date → timestamp', tabBatch: 'Bulk convert', convertTitle: 'Convert', tsPlaceholder: 'Enter a timestamp, e.g. 1704067200', unit: 'Unit', unitSecond: 'Seconds', unitMillisecond: 'Milliseconds', now: 'Now', convert: 'Convert', batchConvert: 'Convert all', resultTitle: 'Result', pickTitle: 'Pick a Beijing time', pickPlaceholder: 'Select date and time', batchInputTitle: 'Bulk timestamps → Beijing time', batchInputPlaceholder: 'One timestamp per line, e.g.:\n1704067200\n1704067200000', batchResultTitle: 'Bulk results', download: 'Download', beijing: 'Beijing time', localTime: 'Local time', secondSuffix: ' (seconds)', millisecondSuffix: ' (milliseconds)', errInvalidTs: 'Enter a valid numeric timestamp', errOutOfRange: 'Timestamp is outside the representable range', errInvalidDate: 'Choose a valid date and time', invalidTs: '[invalid timestamp]', outOfRange: '[out of range]', serverNow: 'Read server time', serverTimeLabel: 'Server time', serverOffset: 'Difference from local clock', clockSkewOk: 'Local clock matches the server', clockSkewWarn: 'Local clock may be off by {seconds} seconds', serverFailed: 'Request failed: {message}', }, 'random-string': { title: 'Random string', desc: 'Generate random strings by length and character set, optionally from the server CSPRNG.', length: 'Length', type: 'Character set', typeAlnum: 'Letters + digits', typeDigits: 'Digits only', typeLetters: 'Letters only', count: 'How many', modeLocal: 'Local (Web Crypto)', modeServer: 'Server (crypto/rand)', generate: 'Generate', resultTitle: 'Results', serverRangeHint: 'The server accepts lengths from 1 to 128; anything else falls back to local generation.', strengthHint: 'Longer strings from a larger character set are harder to guess.', }, 'api-status': { title: 'API status', desc: 'Probe each backend endpoint for availability and response time to confirm the frontend and backend are talking.', endpoint: 'Endpoint', method: 'Method', status: 'Status', latency: 'Latency', summary: '{ok} of {total} endpoints healthy', allOk: 'All endpoints healthy', partial: 'Some endpoints failed', probe: 'Run probe', probing: 'Probing…', lastChecked: 'Last checked: {time}', baseUrlLabel: 'API base URL', sampleTitle: 'Sample response', notConfigured: 'No API base URL configured, cannot probe.', failed: 'Request failed', endpointIp: 'Client IP', endpointMd5: 'MD5 digest', endpointRandom: 'Random string', endpointTime: 'Server time', endpointUuid: 'Unique ID', ok: 'Healthy', error: 'Failed', }, }, pending: { title: 'This endpoint is not live yet', hint: 'The page is ready. Once the backend implements the endpoint it starts working automatically, with no frontend change.', networkTest: 'The HTTP reachability check works today. Ping, TCP, and DNS probes turn on once the backend implements them.', speedTest: 'Download testing can use a public source (subject to its CORS policy). Upload testing turns on once the backend implements the upload endpoint.', contactHint: 'The endpoint contract lives in docs/api-contract.md inside the project.', }, common: { copy: 'Copy', copied: 'Copied to clipboard', copyAll: 'Copy all', clear: 'Clear', download: 'Download', loading: 'Working…', query: 'Search', querying: 'Searching…', convert: 'Convert', generate: 'Generate', compute: 'Compute', history: 'History', historyEmpty: 'No history yet', empty: 'Nothing here yet', error: 'Something went wrong', retry: 'Retry', close: 'Close', confirm: 'Confirm', cancel: 'Cancel', unitSeconds: 'Seconds', unitMilliseconds: 'Milliseconds', yes: 'Yes', no: 'No', notProvided: 'Not provided', }, }