All checks were successful
Build and Deploy (tool.xpcool.com) / build-and-deploy (push) Successful in 1m10s
主色青玉改宝石蓝,字号整体放大一档(正文 16px), 通过 --td-comp-* 与 --td-font-* 接管 TDesign 控件高度与文字, 修复 theme-mode 选择器权重不足导致深色变量被 UI 库覆盖的问题。
534 lines
18 KiB
TypeScript
534 lines
18 KiB
TypeScript
/**
|
|
* 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',
|
|
},
|
|
}
|