Merge branch 'develop'

# Conflicts:
#	src/plugins/i18n.plugin.ts
#	src/tools/base64-file-converter/index.ts
#	src/tools/base64-string-converter/index.ts
#	src/tools/basic-auth-generator/index.ts
#	src/tools/bcrypt/index.ts
#	src/tools/benchmark-builder/index.ts
#	src/tools/bip39-generator/index.ts
#	src/tools/camera-recorder/index.ts
#	src/tools/case-converter/index.ts
#	src/tools/chmod-calculator/index.ts
#	src/tools/chronometer/index.ts
#	src/tools/color-converter/index.ts
#	src/tools/crontab-generator/index.ts
#	src/tools/date-time-converter/index.ts
#	src/tools/device-information/index.ts
#	src/tools/docker-run-to-docker-compose-converter/index.ts
#	src/tools/emoji-picker/index.ts
#	src/tools/encryption/index.ts
#	src/tools/eta-calculator/index.ts
#	src/tools/git-memo/index.ts
#	src/tools/hash-text/index.ts
#	src/tools/hmac-generator/index.ts
#	src/tools/html-entities/index.ts
#	src/tools/html-wysiwyg-editor/index.ts
#	src/tools/http-status-codes/index.ts
#	src/tools/iban-validator-and-parser/index.ts
#	src/tools/index.ts
#	src/tools/integer-base-converter/index.ts
#	src/tools/ipv4-address-converter/index.ts
#	src/tools/ipv4-range-expander/index.ts
#	src/tools/ipv4-subnet-calculator/index.ts
#	src/tools/ipv6-ula-generator/index.ts
#	src/tools/json-diff/index.ts
#	src/tools/json-minify/index.ts
#	src/tools/json-to-csv/index.ts
#	src/tools/json-to-toml/index.ts
#	src/tools/json-to-yaml-converter/index.ts
#	src/tools/json-viewer/index.ts
#	src/tools/jwt-parser/index.ts
#	src/tools/keycode-info/index.ts
#	src/tools/list-converter/index.ts
#	src/tools/lorem-ipsum-generator/index.ts
#	src/tools/mac-address-generator/index.ts
#	src/tools/mac-address-lookup/index.ts
#	src/tools/math-evaluator/index.ts
#	src/tools/meta-tag-generator/index.ts
#	src/tools/mime-types/index.ts
#	src/tools/numeronym-generator/index.ts
#	src/tools/otp-code-generator-and-validator/index.ts
#	src/tools/password-strength-analyser/index.ts
#	src/tools/pdf-signature-checker/index.ts
#	src/tools/percentage-calculator/index.ts
#	src/tools/phone-parser-and-formatter/index.ts
#	src/tools/qr-code-generator/index.ts
#	src/tools/random-port-generator/index.ts
#	src/tools/roman-numeral-converter/index.ts
#	src/tools/rsa-key-pair-generator/index.ts
#	src/tools/slugify-string/index.ts
#	src/tools/sql-prettify/index.ts
#	src/tools/string-obfuscator/index.ts
#	src/tools/svg-placeholder-generator/index.ts
#	src/tools/temperature-converter/index.ts
#	src/tools/text-diff/index.ts
#	src/tools/text-statistics/index.ts
#	src/tools/text-to-binary/index.ts
#	src/tools/text-to-nato-alphabet/index.ts
#	src/tools/token-generator/locales/en.yml
#	src/tools/toml-to-json/index.ts
#	src/tools/toml-to-yaml/index.ts
#	src/tools/ulid-generator/index.ts
#	src/tools/url-encoder/index.ts
#	src/tools/url-parser/index.ts
#	src/tools/user-agent-parser/index.ts
#	src/tools/uuid-generator/index.ts
#	src/tools/wifi-qr-code-generator/index.ts
#	src/tools/xml-formatter/index.ts
#	src/tools/yaml-to-json-converter/index.ts
#	src/tools/yaml-to-toml/index.ts
This commit is contained in:
Amery2010 2024-02-21 17:58:57 +08:00
commit ac058ac87f
354 changed files with 5105 additions and 2325 deletions

1
components.d.ts vendored
View file

@ -80,6 +80,7 @@ declare module '@vue/runtime-core' {
FormatTransformer: typeof import('./src/components/FormatTransformer.vue')['default']
GitMemo: typeof import('./src/tools/git-memo/git-memo.vue')['default']
'GitMemo.content': typeof import('./src/tools/git-memo/git-memo.content.md')['default']
'GitMemo.content.zh': typeof import('./src/tools/git-memo/git-memo.content.zh.md')['default']
HashText: typeof import('./src/tools/hash-text/hash-text.vue')['default']
HmacGenerator: typeof import('./src/tools/hmac-generator/hmac-generator.vue')['default']
'Home.page': typeof import('./src/pages/Home.page.vue')['default']

View file

@ -56,6 +56,26 @@ toolCard:
new: New
search:
label: Search
ui:
fileUpload:
tips: Drag and drop files here, or click to select files
or: or
browseFileBtn: Browse files
inputText:
placeholder: Input text
modalValue:
copied: Copied!
copy: Copy
select:
placeholder: Select an option
empty: No results found
table:
description: Data table
textCopyable:
copied: Copied!
copyToClipboard: Copy to clipboard
color:
invalidHexColor: Invalid hex color
tools:
categories:
favorite-tools: 'Your favorite tools'
@ -69,325 +89,3 @@ tools:
measurement: Measurement
text: Text
data: Data
password-strength-analyser:
title: Password strength analyser
description: Discover the strength of your password with this client side only password strength analyser and crack time estimation tool.
chronometer:
title: Chronometer
description: Monitor the duration of a thing. Basically a chronometer with simple chronometer features.
token-generator:
title: Token generator
description: Generate random string with the chars you want, uppercase or lowercase letters, numbers and/or symbols.
uppercase: Uppercase (ABC...)
lowercase: Lowercase (abc...)
numbers: Numbers (123...)
symbols: Symbols (!-;...)
length: Length
tokenPlaceholder: 'The token...'
copied: Token copied to the clipboard
button:
copy: Copy
refresh: Refresh
percentage-calculator:
title: Percentage calculator
description: Easily calculate percentages from a value to another value, or from a percentage to a value.
svg-placeholder-generator:
title: SVG placeholder generator
description: Generate svg images to use as placeholder in your applications.
json-to-csv:
title: JSON to CSV
description: Convert JSON to CSV with automatic header detection.
camera-recorder:
title: Camera recorder
description: Take a picture or record a video from your webcam or camera.
keycode-info:
title: Keycode info
description: Find the javascript keycode, code, location and modifiers of any pressed key.
emoji-picker:
title: Emoji picker
description: Copy and paste emojis easily and get the unicode and code points value of each emoji.
color-converter:
title: Color converter
description: Convert color between the different formats (hex, rgb, hsl and css name)
bcrypt:
title: Bcrypt
description: Hash and compare text string using bcrypt. Bcrypt is a password-hashing function based on the Blowfish cipher.
crontab-generator:
title: Crontab generator
description: Validate and generate crontab and get the human readable description of the cron schedule.
http-status-codes:
title: HTTP status codes
description: The list of all HTTP status codes their name and their meaning.
sql-prettify:
title: SQL prettify and format
description: Format and prettify your SQL queries online (it supports various SQL dialects).
benchmark-builder:
title: Benchmark builder
description: Easily compare execution time of tasks with this very simple online benchmark builder.
git-memo:
title: Git cheatsheet
description: Git is a decentralized version management software. With this cheatsheet you will have a quick access to the most common git commands.
slugify-string:
title: Slugify string
description: Make a string url, filename and id safe.
encryption:
title: Encrypt / decrypt text
description: Encrypt and decrypt text clear text using crypto algorithm like AES, TripleDES, Rabbit or RC4.
random-port-generator:
title: Random port generator
description: Generate random port numbers outside of the range of "known" ports (0-1023).
yaml-prettify:
title: YAML prettify and format
description: Prettify your YAML string to a human friendly readable format.
eta-calculator:
title: ETA calculator
description: An ETA (Estimated Time of Arrival) calculator to know the approximate end time of a task, for example the moment of ending of a download.
roman-numeral-converter:
title: Roman numeral converter
description: Convert Roman numerals to numbers and convert numbers to Roman numerals.
hmac-generator:
title: Hmac generator
description: Computes a hash-based message authentication code (HMAC) using a secret key and your favorite hashing function.
bip39-generator:
title: BIP39 passphrase generator
description: Generate BIP39 passphrase from existing or random mnemonic, or get the mnemonic from the passphrase.
base64-file-converter:
title: Base64 file converter
description: Convert string, files or images into a it\'s base64 representation.
list-converter:
title: List converter
description: This tool can process column-based data and apply various changes (transpose, add prefix and suffix, reverse list, sort list, lowercase values, truncate values) to each row.
base64-string-converter:
title: Base64 string encoder/decoder
description: Simply encode and decode string into a their base64 representation.
toml-to-yaml:
title: TOML to YAML
description: Parse and convert TOML to YAML.
math-evaluator:
title: Math evaluator
description: A calculator for evaluating mathematical expressions. You can use functions like sqrt, cos, sin, abs, etc.
json-to-yaml-converter:
title: JSON to YAML converter
description: Simply convert JSON to YAML with this live online converter.
url-parser:
title: Url parser
description: Parse an url string to get all the different parts (protocol, origin, params, port, username-password, ...)
iban-validator-and-parser:
title: IBAN validator and parser
description: Validate and parse IBAN numbers. Check if IBAN is valid and get the country, BBAN, if it is a QR-IBAN and the IBAN friendly format.
user-agent-parser:
title: User-agent parser
description: Detect and parse Browser, Engine, OS, CPU, and Device type/model from an user-agent string.
numeronym-generator:
title: Numeronym generator
description: A numeronym is a word where a number is used to form an abbreviation. For example, "i18n" is a numeronym of "internationalization" where 18 stands for the number of letters between the first i and the last n in the word.
case-converter:
title: Case converter
description: Change the case of a string and chose between different formats
html-entities:
title: Escape html entities
description: Escape or unescape html entities (replace <,>, &, " and \' to their html version)
json-prettify:
title: JSON prettify and format
description: Prettify your JSON string to a human friendly readable format.
docker-run-to-docker-compose-converter:
title: Docker run to Docker compose converter
description: Turns docker run commands into docker-compose files!
mac-address-lookup:
title: MAC address lookup
description: Find the vendor and manufacturer of a device by its MAC address.
mime-types:
title: Mime types
description: Convert mime types to extensions and vice-versa.
toml-to-json:
title: TOML to JSON
description: Parse and convert TOML to JSON.
lorem-ipsum-generator:
title: Lorem ipsum generator
description: Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content
qrcode-generator:
title: QR Code generator
description: Generate and download QR-code for an url or just a text and customize the background and foreground colors.
wifi-qrcode-generator:
title: WiFi QR Code generator
description: Generate and download QR-codes for quick connections to WiFi networks.
xml-formatter:
title: XML formatter
description: Prettify your XML string to a human friendly readable format.
temperature-converter:
title: Temperature converter
description: Temperature degrees conversions for Kelvin, Celsius, Fahrenheit, Rankine, Delisle, Newton, Réaumur and Rømer.
chmod-calculator:
title: Chmod calculator
description: Compute your chmod permissions and commands with this online chmod calculator.
rsa-key-pair-generator:
title: RSA key pair generator
description: Generate new random RSA private and public key pem certificates.
html-wysiwyg-editor:
title: HTML WYSIWYG editor
description: Online HTML editor with feature-rich WYSIWYG editor, get the source code of the content immediately.
yaml-to-toml:
title: YAML to TOML
description: Parse and convert YAML to TOML.
mac-address-generator:
title: MAC address generator
description: Enter the quantity and prefix. MAC addresses will be generated in your chosen case (uppercase or lowercase)
json-diff:
title: JSON diff
description: Compare two JSON objects and get the differences between them.
jwt-parser:
title: JWT parser
description: Parse and decode your JSON Web Token (jwt) and display its content.
date-converter:
title: Date-time converter
description: Convert date and time into the various different formats
phone-parser-and-formatter:
title: Phone parser and formatter
description: Parse, validate and format phone numbers. Get information about the phone number, like the country code, type, etc.
ipv4-subnet-calculator:
title: IPv4 subnet calculator
description: Parse your IPv4 CIDR blocks and get all the info you need about your sub network.
og-meta-generator:
title: Open graph meta generator
description: Generate open-graph and socials html meta tags for your website.
ipv6-ula-generator:
title: IPv6 ULA generator
description: Generate your own local, non-routable IP addresses on your network according to RFC4193.
hash-text:
title: Hash text
description: 'Hash a text string using the function you need : MD5, SHA1, SHA256, SHA224, SHA512, SHA384, SHA3 or RIPEMD160'
json-to-toml:
title: JSON to TOML
description: Parse and convert JSON to TOML.
device-information:
title: Device information
description: Get information about your current device (screen size, pixel-ratio, user agent, ...)
pdf-signature-checker:
title: PDF signature checker
description: Verify the signatures of a PDF file. A signed PDF file contains one or more signatures that may be used to determine whether the contents of the file have been altered since the file was signed.
json-minify:
title: JSON minify
description: Minify and compress your JSON by removing unnecessary white spaces.
ulid-generator:
title: ULID generator
description: Generate random Universally Unique Lexicographically Sortable Identifier (ULID).
string-obfuscator:
title: String obfuscator
description: Obfuscate a string (like a secret, an IBAN, or a token) to make it shareable and identifiable without revealing its content.
base-converter:
title: Integer base converter
description: Convert number between different bases (decimal, hexadecimal, binary, octal, base64, ...)
yaml-to-json-converter:
title: YAML to JSON converter
description: Simply convert YAML to JSON with this live online converter.
uuid-generator:
title: UUIDs generator
description: A Universally Unique Identifier (UUID) is a 128-bit number used to identify information in computer systems. The number of possible UUIDs is 16^32, which is 2^128 or about 3.4x10^38 (which is a lot!).
ipv4-address-converter:
title: Ipv4 address converter
description: Convert an ip address into decimal, binary, hexadecimal or event in ipv6
text-statistics:
title: Text statistics
description: Get information about a text, the amount of characters, the amount of words, it\'s size, ...
text-to-nato-alphabet:
title: Text to NATO alphabet
description: Transform text into NATO phonetic alphabet for oral transmission.
basic-auth-generator:
title: Basic auth generator
description: Generate a base64 basic auth header from an username and a password.
text-to-unicode:
title: Text to Unicode
description: Parse and convert text to unicode and vice-versa
ipv4-range-expander:
title: IPv4 range expander
description: Given a start and an end IPv4 address this tool calculates a valid IPv4 network with its CIDR notation.
text-diff:
title: Text diff
description: Compare two texts and see the differences between them.
otp-generator:
title: OTP code generator
description: Generate and validate time-based OTP (one time password) for multi-factor authentication.
url-encoder:
title: Encode/decode url formatted strings
description: Encode to url-encoded format (also known as "percent-encoded") or decode from it.
text-to-binary:
title: Text to ASCII binary
description: Convert text to its ASCII binary representation and vice versa.

View file

@ -63,19 +63,3 @@ tools:
measurement: Mesure
text: Texte
data: Données
token-generator:
title: Générateur de token
description: >-
Génère une chaîne aléatoire avec les caractères que vous voulez, lettres
majuscules ou minuscules, chiffres et/ou symboles.
uppercase: Majuscules (ABC...)
lowercase: Minuscules (abc...)
numbers: Chiffres (123...)
symbols: Symboles (!-;...)
button:
copy: Copier
refresh: Rafraichir
copied: Le token a été copié
length: Longueur
tokenPlaceholder: Le token...

View file

@ -69,314 +69,3 @@ tools:
measurement: Đo lường
text: Văn bản
data: Dữ liệu
password-strength-analyser:
title: Bộ phân tích độ mạnh mật khẩu
description: Khám phá độ mạnh của mật khẩu của bạn với công cụ phân tích độ mạnh mật khẩu chỉ chạy trên phía máy khách và ước tính thời gian phá mật khẩu.
chronometer:
title: Đồng hồ bấm giờ
description: Giám sát thời gian của một sự việc. Cơ bản là một đồng hồ bấm giờ với các tính năng đơn giản.
token-generator:
title: Trình tạo mã thông báo
description: Tạo chuỗi ngẫu nhiên với các ký tự bạn muốn, chữ hoa hoặc chữ thường, số và/hoặc ký tự đặc biệt.
uppercase: Chữ hoa (ABC...)
lowercase: Chữ thường (abc...)
numbers: Số (123...)
symbols: Ký tự đặc biệt (!-;...)
length: Độ dài
tokenPlaceholder: 'Mã thông báo...'
copied: Mã thông báo đã được sao chép vào clipboard
button:
copy: Sao chép
refresh: Làm mới
percentage-calculator:
title: Máy tính phần trăm
description: Dễ dàng tính toán phần trăm từ một giá trị đến giá trị khác, hoặc từ một phần trăm đến một giá trị.
svg-placeholder-generator:
title: Trình tạo hình ảnh SVG giả định
description: Tạo hình ảnh svg để sử dụng làm giả định trong ứng dụng của bạn.
json-to-csv:
title: Chuyển đổi JSON thành CSV
description: Chuyển đổi JSON thành CSV với việc tự động phát hiện tiêu đề.
camera-recorder:
title: Ghi lại camera
description: Chụp ảnh hoặc quay video từ webcam hoặc máy ảnh của bạn.
keycode-info:
title: Thông tin Keycode
description: Tìm mã keycode, mã, vị trí và các phím điều khiển của bất kỳ phím nào được nhấn.
emoji-picker:
title: Bộ chọn biểu tượng cảm xúc
description: Sao chép và dán biểu tượng cảm xúc một cách dễ dàng và nhận giá trị unicode và mã điểm của mỗi biểu tượng cảm xúc.
color-converter:
title: Trình chuyển đổi màu
description: Chuyển đổi màu giữa các định dạng khác nhau (hex, rgb, hsl và tên css)
bcrypt:
title: Bcrypt
description: Mã hóa và so sánh chuỗi văn bản sử dụng bcrypt. Bcrypt là một hàm mã hóa mật khẩu dựa trên thuật toán Blowfish.
crontab-generator:
title: Trình tạo Crontab
description: Xác thực và tạo crontab và lấy mô tả đọc được của lịch trình cron.
http-status-codes:
title: Mã trạng thái HTTP
description: Danh sách tất cả các mã trạng thái HTTP, tên và ý nghĩa của chúng.
sql-prettify:
title: Định dạng và làm đẹp SQL
description: Định dạng và làm đẹp các truy vấn SQL của bạn trực tuyến (hỗ trợ nhiều ngôn ngữ SQL khác nhau).
benchmark-builder:
title: Trình tạo bảng đánh giá
description: Dễ dàng so sánh thời gian thực thi của các nhiệm vụ với trình tạo bảng đánh giá trực tuyến đơn giản này.
git-memo:
title: Lệnh Git
description: Git là một phần mềm quản lý phiên bản phân tán. Với bảng ghi chú này, bạn sẽ có thể truy cập nhanh vào các lệnh Git phổ biến nhất.
slugify-string:
title: Chuyển đổi chuỗi thành slug
description: Biến đổi chuỗi thành dạng an toàn để sử dụng trong URL, tên file và ID.
encryption:
title: Mã hóa / giải mã văn bản
description: Mã hóa và giải mã văn bản rõ bằng cách sử dụng thuật toán mã hóa như AES, TripleDES, Rabbit hoặc RC4.
random-port-generator:
title: Trình tạo số cổng ngẫu nhiên
description: Tạo số cổng ngẫu nhiên nằm ngoài phạm vi của các cổng "biết được" (0-1023).
yaml-prettify:
title: Định dạng và làm đẹp YAML
description: Định dạng chuỗi YAML của bạn thành một định dạng dễ đọc và thân thiện với con người.
eta-calculator:
title: Máy tính ETA
description: Một máy tính ETA (Thời gian dự kiến đến) để biết thời gian kết thúc xấp xỉ của một nhiệm vụ, ví dụ như thời điểm kết thúc của một quá trình tải xuống.
roman-numeral-converter:
title: Bộ chuyển đổi số La Mã
description: Chuyển đổi số La Mã thành số và chuyển đổi số thành số La Mã.
hmac-generator:
title: Máy tạo HMAC
description: Tính toán mã xác thực thông điệp dựa trên hash (HMAC) sử dụng một khóa bí mật và hàm băm yêu thích của bạn.
bip39-generator:
title: Trình tạo BIP39 passphrase
description: Tạo BIP39 passphrase từ mnemonic hiện có hoặc ngẫu nhiên, hoặc lấy mnemonic từ passphrase.
base64-file-converter:
title: Trình chuyển đổi tệp Base64
description: Chuyển đổi chuỗi, tệp hoặc hình ảnh thành mã Base64.
list-converter:
title: Trình chuyển đổi danh sách
description: Công cụ này có thể xử lý dữ liệu dựa trên cột và áp dụng các thay đổi khác nhau (đảo ngược, thêm tiền tố và hậu tố, đảo danh sách, sắp xếp danh sách, giảm giá trị thành chữ thường, cắt giá trị) cho mỗi hàng.
base64-string-converter:
title: Trình mã hóa/giải mã chuỗi Base64
description: Đơn giản mã hóa và giải mã chuỗi thành mã Base64.
toml-to-yaml:
title: Chuyển đổi TOML thành YAML
description: Phân tích và chuyển đổi TOML thành YAML.
math-evaluator:
title: Trình đánh giá toán học
description: Một máy tính để tính toán biểu thức toán học. Bạn có thể sử dụng các hàm như sqrt, cos, sin, abs, v.v.
json-to-yaml-converter:
title: Chuyển đổi JSON sang YAML
description: Chuyển đổi đơn giản JSON sang YAML với công cụ chuyển đổi trực tuyến này.
url-parser:
title: Trình phân tích URL
description: Phân tích một chuỗi URL để lấy tất cả các phần khác nhau (giao thức, nguồn gốc, tham số, cổng, tên người dùng-mật khẩu, ...)
iban-validator-and-parser:
title: Kiểm tra và phân tích số IBAN
description: Xác thực và phân tích số IBAN. Kiểm tra tính hợp lệ của IBAN và lấy thông tin về quốc gia, BBAN, xem có phải là QR-IBAN và định dạng thân thiện của IBAN.
user-agent-parser:
title: Trình phân tích User-agent
description: Phát hiện và phân tích trình duyệt, engine, hệ điều hành, CPU và kiểu/mô hình thiết bị từ chuỗi user-agent.
numeronym-generator:
title: Trình tạo Numeronym
description: Numeronym là một từ mà một số được sử dụng để tạo thành một từ viết tắt. Ví dụ, "i18n" là một numeronym của "internationalization" trong đó số 18 đại diện cho số chữ cái giữa chữ i đầu tiên và chữ n cuối cùng trong từ.
case-converter:
title: Chuyển đổi chữ hoa/chữ thường
description: Thay đổi kiểu chữ của một chuỗi và chọn giữa các định dạng khác nhau
html-entities:
title: Thay thế các ký tự HTML
description: Thay thế hoặc bỏ thẻ các ký tự HTML (thay thế <,>, &, " và \' thành phiên bản HTML tương ứng)
json-prettify:
title: Định dạng và làm đẹp JSON
description: Định dạng chuỗi JSON của bạn thành một định dạng dễ đọc và thân thiện với con người.
docker-run-to-docker-compose-converter:
title: Chuyển đổi lệnh docker run thành tệp docker-compose
description: Chuyển đổi các lệnh docker run thành tệp docker-compose!
mac-address-lookup:
title: Tra cứu địa chỉ MAC
description: Tìm nhà sản xuất và nhà cung cấp của thiết bị dựa trên địa chỉ MAC.
mime-types:
title: Loại Mime
description: Chuyển đổi loại mime thành phần mở rộng và ngược lại.
toml-to-json:
title: Chuyển đổi TOML thành JSON
description: Phân tích và chuyển đổi TOML thành JSON.
lorem-ipsum-generator:
title: Máy tạo văn bản Lorem ipsum
description: Lorem ipsum là một đoạn văn bản giả được sử dụng phổ biến để thể hiện hình thức của một tài liệu hoặc một kiểu chữ mà không cần dựa vào nội dung có ý nghĩa
qrcode-generator:
title: Tạo mã QR
description: Tạo và tải xuống mã QR cho một URL hoặc chỉ một đoạn văn bản và tùy chỉnh màu nền và màu chữ.
wifi-qrcode-generator:
title: Tạo mã QR WiFi
description: Tạo và tải xuống mã QR để kết nối nhanh đến mạng WiFi.
xml-formatter:
title: Định dạng XML
description: Định dạng chuỗi XML của bạn thành một định dạng dễ đọc và thân thiện với con người.
temperature-converter:
title: Bộ chuyển đổi nhiệt độ
description: Chuyển đổi độ nhiệt độ cho Kelvin, Celsius, Fahrenheit, Rankine, Delisle, Newton, Réaumur và Rømer.
chmod-calculator:
title: Máy tính Chmod
description: Tính toán quyền và lệnh chmod của bạn với máy tính Chmod trực tuyến này.
rsa-key-pair-generator:
title: Trình tạo cặp khóa RSA
description: Tạo các chứng chỉ pem khóa riêng tư và khóa công khai RSA ngẫu nhiên mới.
html-wysiwyg-editor:
title: Trình soạn thảo HTML WYSIWYG
description: Trình soạn thảo HTML trực tuyến với trình soạn thảo WYSIWYG đa chức năng, lấy mã nguồn của nội dung ngay lập tức.
yaml-to-toml:
title: YAML sang TOML
description: Phân tích và chuyển đổi YAML sang TOML.
mac-address-generator:
title: Trình tạo địa chỉ MAC
description: Nhập số lượng và tiền tố. Địa chỉ MAC sẽ được tạo ra theo kiểu chữ hoa hoặc chữ thường theo lựa chọn của bạn
json-diff:
title: So sánh JSON
description: So sánh hai đối tượng JSON và lấy ra sự khác biệt giữa chúng.
jwt-parser:
title: Giải mã JWT
description: Giải mã và hiển thị nội dung của JSON Web Token (jwt).
date-converter:
title: Chuyển đổi ngày-tháng
description: Chuyển đổi ngày và thời gian sang các định dạng khác nhau
phone-parser-and-formatter:
title: Trình phân tích và định dạng số điện thoại
description: Phân tích, xác thực và định dạng số điện thoại. Lấy thông tin về số điện thoại, như mã quốc gia, loại, v.v.
ipv4-subnet-calculator:
title: Máy tính mạng con IPv4
description: Phân tích các khối CIDR IPv4 của bạn và nhận thông tin về mạng con của bạn.
og-meta-generator:
title: Trình tạo meta Open Graph
description: Tạo các thẻ meta HTML Open Graph và mạng xã hội cho trang web của bạn.
ipv6-ula-generator:
title: Trình tạo địa chỉ IPv6 ULA
description: Tạo địa chỉ IP cục bộ, không thể định tuyến trên mạng của bạn theo RFC4193.
hash-text:
title: Mã hóa văn bản
description: 'Mã hóa một chuỗi văn bản bằng cách sử dụng các hàm bạn cần: MD5, SHA1, SHA256, SHA224, SHA512, SHA384, SHA3 hoặc RIPEMD160'
json-to-toml:
title: Chuyển đổi JSON sang TOML
description: Phân tích và chuyển đổi JSON sang TOML.
device-information:
title: Thông tin thiết bị
description: Lấy thông tin về thiết bị hiện tại của bạn (kích thước màn hình, tỷ lệ pixel, user agent, ...)
pdf-signature-checker:
title: Kiểm tra chữ ký PDF
description: Xác minh chữ ký của một tệp PDF. Một tệp PDF đã được ký có chứa một hoặc nhiều chữ ký có thể được sử dụng để xác định xem nội dung của tệp đã được thay đổi kể từ khi tệp được ký.
json-minify:
title: Giảm kích thước JSON
description: Giảm kích thước và nén JSON của bạn bằng cách loại bỏ khoảng trắng không cần thiết.
ulid-generator:
title: Tạo ULID
description: Tạo ngẫu nhiên mã định danh duy nhất có thể sắp xếp theo thứ tự từ điển (ULID).
string-obfuscator:
title: Mã hóa chuỗi
description: Mã hóa một chuỗi (như một bí mật, một IBAN hoặc một mã thông báo) để có thể chia sẻ và nhận dạng mà không tiết lộ nội dung.
base-converter:
title: Chuyển đổi cơ số số nguyên
description: Chuyển đổi số giữa các cơ số khác nhau (thập phân, thập lục phân, nhị phân, bát phân, base64, ...)
yaml-to-json-converter:
title: Trình chuyển đổi YAML sang JSON
description: Chuyển đổi YAML sang JSON một cách đơn giản với công cụ chuyển đổi trực tuyến này.
uuid-generator:
title: Trình tạo UUID
description: Một UUID (Universally Unique Identifier) là một số 128 bit được sử dụng để xác định thông tin trong hệ thống máy tính. Số lượng UUID có thể có là 16^32, tương đương với 2^128 hoặc khoảng 3.4x10^38 (rất lớn!).
ipv4-address-converter:
title: Chuyển đổi địa chỉ Ipv4
description: Chuyển đổi địa chỉ ip thành số thập phân, nhị phân, thập lục phân hoặc thậm chí thành ipv6
text-statistics:
title: Thống kê văn bản
description: Lấy thông tin về một văn bản, số ký tự, số từ, kích thước của nó, ...
text-to-nato-alphabet:
title: Chuyển đổi văn bản thành bảng chữ cái NATO
description: Chuyển đổi văn bản thành bảng chữ cái phiên âm NATO để truyền tải bằng miệng.
basic-auth-generator:
title: Tạo mã xác thực cơ bản
description: Tạo một tiêu đề xác thực cơ bản base64 từ tên người dùng và mật khẩu.
text-to-unicode:
title: Chuyển đổi văn bản thành Unicode
description: Phân tích và chuyển đổi văn bản thành Unicode và ngược lại
ipv4-range-expander:
title: Mở rộng dải IPv4
description: Cho một địa chỉ IPv4 bắt đầu và kết thúc, công cụ này tính toán một mạng IPv4 hợp lệ với ký hiệu CIDR của nó.
text-diff:
title: So sánh văn bản
description: So sánh hai văn bản và xem sự khác biệt giữa chúng.
otp-generator:
title: Tạo mã OTP
description: Tạo và xác thực mã OTP (mật khẩu một lần) dựa trên thời gian cho xác thực đa yếu tố.
url-encoder:
title: Mã hóa/giải mã chuỗi định dạng URL
description: Mã hóa thành định dạng URL (còn được gọi là "percent-encoded") hoặc giải mã từ đó.
text-to-binary:
title: Chuyển đổi văn bản thành nhị phân ASCII
description: Chuyển đổi văn bản thành biểu diễn nhị phân ASCII của nó và ngược lại.

View file

@ -56,6 +56,26 @@ toolCard:
new: '新'
search:
label: '搜索'
ui:
fileUpload:
tips: 拖放文件到此处,或点击选择文件
or:
browseFileBtn: 浏览文件
inputText:
placeholder: 输入文本
modalValue:
copied: 已复制!
copy: 复制
select:
placeholder: 选择一个选项
empty: 未找到结果
table:
description: 数据表格
textCopyable:
copied: 已复制!
copyToClipboard: 复制到剪贴板
color:
invalidHexColor: 无效的十六进制颜色
tools:
categories:
favorite-tools: '我的收藏'
@ -69,321 +89,3 @@ tools:
measurement: '测量'
text: '文本'
data: '数据'
password-strength-analyser:
title: 密码强度分析仪
description: 使用此密码强度分析器和破解时间估计工具来发现密码的强度。
chronometer:
title: 计时器
description: 监控事物的持续时间。基本上是一种具有简单计时器功能的计时器。
token-generator:
title: Token 生成器
description: 使用您想要的字符、大写或小写字母、数字和/或符号生成随机字符串。
uppercase: '大写 (ABC...)'
lowercase: '小写 (abc...)'
numbers: '数字 (123...)'
symbols: '符号 (!-;...)'
length: '长度'
tokenPlaceholder: '令牌...'
copied: 复制到剪贴板
button:
copy: 复制
refresh: 刷新
percentage-calculator:
title: 百分比计算器
description: 轻松计算从一个值到另一个值的百分比,或从百分比到值的百分比。
svg-placeholder-generator:
title: SVG 占位符生成器
description: 生成 svg 图像以用作应用程序中的占位符。
json-to-csv:
title: JSON 转 CSV
description: 使用自动标头检测将JSON转换为CSV。
camera-recorder:
title: 摄像机记录器
description: 从网络摄像头或照相机拍摄照片或录制视频。
keycode-info:
title: Keycode 信息
description: 查找任何按下的键的javascript键代码、代码、位置和修饰符。
emoji-picker:
title: Emoji 选择器
description: 轻松复制和粘贴Emoji表情符号并获得每个表情符号的unicode和code points值.
color-converter:
title: Color 选择器
description: 在不同格式十六进制、rgb、hsl和css名称之间转换颜色
bcrypt:
title: 加密
description: 使用bcrypt对文本字符串进行哈希和比较。Bcrypt是一个基于Blowfish密码的密码哈希函数。
crontab-generator:
title: Crontab 表达式生成
description: 验证并生成crontab并获取cron调度的可读描述。
http-status-codes:
title: HTTP 状态码
description: 所有HTTP状态的列表对其名称和含义解释。
sql-prettify:
title: SQL 美化和格式化
description: 在线格式化和美化您的 SQL 查询(它支持各种 SQL 方言)。
benchmark-builder:
title: 基准生成器
description: 简单的在线基准构建器可以轻松比较任务的执行时间。
git-memo:
title: Git 备忘录
description: Git是一种去中心化的版本管理软件。使用此备忘单您可以快速访问最常见的git命令.
slugify-string:
title: 打乱字符串
description: 确保字符串 url、文件名和 id 安全。
encryption:
title: 加密/解密文本
description: 使用加密算法如AES、TripleDES、Rabbit或RC4加密和解密文本明文。
random-port-generator:
title: 随机端口生成
description: 生成“已知”端口范围0-1023之外的随机端口号。
yaml-prettify:
title: YAML美化和格式化
description: 将YAML字符串修饰为友好的可读格式。
eta-calculator:
title: ETA 计算器
description: ETA估计到达时间计算器用于知道任务的近似结束时间例如下载的结束时刻。
roman-numeral-converter:
title: 罗马数字转换器
description: 将罗马数字转换为数字,并将数字转换为罗马数字。
hmac-generator:
title: Hmac 生成器
description: 使用密钥和您喜欢的哈希函数计算基于哈希的消息身份验证代码HMAC
bip39-generator:
title: BIP39密码生成器
description: 从现有或随机助记符生成BIP39密码短语或从密码短语获取助记符。
base64-file-converter:
title: Base64 文件转换器
description: 将字符串、文件或图像转换为其 Base64 表示形式。
list-converter:
title: List 转换器
description: 该工具可以处理基于数组的数据,并将各种更改(转置、添加前缀和后缀、反向列表、排序列表、小写值、截断值)应用于每一行。
base64-string-converter:
title: Base64 字符串编码/解码
description: 将字符串编码和解码为其 Base64 格式表示形式即可。
toml-to-yaml:
title: TOML 到 YAML
description: Parse and convert TOML to YAML.
math-evaluator:
title: 数学计算器
description: 计算数学表达式的计算器。您可以使用sqrt、cos、sin、abs等函数。
json-to-yaml-converter:
title: JSON到YAML转换器
description: 在线转换将JSON转换为YAML。
url-parser:
title: Url分析器
description: 解析url字符串以获取所有不同的部分协议、来源、参数、端口、用户名密码…
iban-validator-and-parser:
title: IBAN验证器和解析器
description: 验证和分析IBAN编号。检查IBAN是否有效并获取国家BBAN如果它是QR-IBAN和IBAN友好格式。
user-agent-parser:
title: 用户代理分析器
description: 从用户代理字符串中检测和分析浏览器、引擎、操作系统、CPU和设备类型/型号。
numeronym-generator:
title: 数字名称生成器
description: 数字名是一个用数字构成缩写的词。例如“i18n”是“国际化”的名词其中18表示单词中第一个i和最后一个n之间的字母数。
case-converter:
title: 大小写转换
description: 更改字符串的大小写并在不同格式之间进行选择
html-entities:
title: 转义html实体
description: 转义或unescape html实体将<、>、&、“和\'替换为其html版本
json-prettify:
title: JSON美化和格式化
description: 将JSON字符串修饰为友好的可读格式。
docker-run-to-docker-compose-converter:
title: Docker Run 到 docker-compose 转换器
description: 将 docker run 命令行转换为 docker-compose 文件!
mac-address-lookup:
title: MAC地址查找
description: 通过设备的MAC地址查找设备的供应商和制造商。
mime-types:
title: mime类型
description: 将mime类型转换为扩展反之亦然。
toml-to-json:
title: TOML 到 JSON
description: 解析TOML并将其转换为JSON。
lorem-ipsum-generator:
title: Lorem ipsum生成器
description: Lorem ipsum是一种占位符文本通常用于演示文档或字体的视觉形式而不依赖于有意义的内容
qrcode-generator:
title: 二维码生成器
description: 生成并下载url或文本的QR代码并自定义背景和前景颜色。
wifi-qrcode-generator:
title: WiFi 二维码生成器
description: 生成和下载QR码以快速连接到WiFi网络。
xml-formatter:
title: XML 格式化
description: 将XML字符串修饰为友好的可读格式。
temperature-converter:
title: 温度转换器
description: 开尔文、摄氏度、华氏度、兰金、德莱尔、牛顿、雷奥穆尔和罗默温度度数转换。
chmod-calculator:
title: Chmod 计算器
description: 使用此在线的chmod计算器计算chmod权限和命令。
rsa-key-pair-generator:
title: RSA密钥对生成器
description: 生成新的随机RSA私钥和公钥pem证书。
html-wysiwyg-editor:
title: HTML所见即所得编辑器
description: 在线HTML编辑器具有功能丰富的所见即所得编辑器立即获得内容的源代码。
yaml-to-toml:
title: YAML 到 TOML
description: 解析YAML并将其转换为TOML。
mac-address-generator:
title: MAC 地址生成器
description: 输入数量和前缀。MAC地址将以您选择的大小写大写或小写生成
json-diff:
title: JSON 差异比较
description: 比较两个JSON对象并获得它们之间的差异。
jwt-parser:
title: JWT 解析器
description: 解析和解码JSON Web Tokenjwt并显示其内容。
date-converter:
title: 日期时间转换器
description: 将日期和时间转换为各种不同的格式
phone-parser-and-formatter:
title: 电话分析器和格式化程序
description: 解析、验证和格式化电话号码。获取有关电话号码的信息,如国家/地区代码、类型等。
ipv4-subnet-calculator:
title: IPv4子网计算器
description: 解析IPv4 CIDR块并获取有关子网络的所有所需信息。
og-meta-generator:
title: 开放式图形元生成器
description: 为您的网站生成开放式图形和社交html元标记。
ipv6-ula-generator:
title: IPv6 ULA生成器
description: 根据RFC4193在网络上生成您自己的本地不可路由IP地址。
hash-text:
title: Hash 文本
description: '使用所需的函数哈希文本字符串MD5、SHA1、SHA256、SHA224、SHA512、SHA384、SHA3或RIPEMD160'
json-to-toml:
title: JSON 转 TOML
description: 解析JSON并将其转换为TOML。
device-information:
title: 设备信息
description: 获取有关当前设备的信息(屏幕大小、像素比率、用户代理…)
pdf-signature-checker:
title: PDF签名检查器
description: '验证PDF文件的签名。签名的PDF文件包含一个或多个签名可用于确定文件的内容在签名后是否已被更改。'
json-minify:
title: JSON 压缩
description: 通过删除不必要的空白来缩小和压缩JSON。
ulid-generator:
title: ULID 生成器
description: 生成随机的通用唯一词典可排序标识符ULID
string-obfuscator:
title: 字符串混淆器
description: 混淆字符串如秘密、IBAN 或令牌),使其可共享和可识别,而不泄露其内容。
base-converter:
title: 整数基转换器
description: 在不同的基数十进制、十六进制、二进制、八进制、base64…之间转换数字
yaml-to-json-converter:
title: YAML到JSON转换器
description: 使用此在线转换器将YAML转换为JSON。
uuid-generator:
title: UUIDs 生成器
description: 通用唯一标识符UUID是一个128位数字用于标识计算机系统中的信息。可能的UUID数量为16^32即2^128或约3.4x10^38这是一个很大的数字
ipv4-address-converter:
title: Ipv4地址转换器
description: 在ipv6中将ip地址转换为十进制、二进制、十六进制或事件
text-statistics:
title: 文本统计
description: 获取有关文本、字符数、字数、大小等的信息
text-to-nato-alphabet:
title: 文本转北约字母表
description: 将文本转换为北约拼音字母以进行口头传播。
basic-auth-generator:
title: 基本身份验证生成器
description: 从用户名和密码生成 base64 基本身份验证标头。
text-to-unicode:
title: 文本转 Unicode
description: 解析文本并将其转换为 unicode反之亦然
ipv4-range-expander:
title: IPv4范围扩展器
description: 给定起始和结束IPv4地址此工具使用其CIDR表示法计算有效的IPv4网络。
text-diff:
title: 文本比较
description: 比较两个文本并查看它们之间的差异。
otp-generator:
title: OTP代码生成器
description: 为多因素身份验证生成和验证基于时间的OTP一次性密码
url-encoder:
title: 编码/解码url格式的字符串
description: 编码为url编码格式也称为“百分比编码”或从中解码。
text-to-binary:
title: 文本到 ASCII 二进制
description: 将文本转换为其 ASCII 二进制表示形式,反之亦然。

View file

@ -7,14 +7,17 @@ import BaseLayout from './base.layout.vue';
import FavoriteButton from '@/components/FavoriteButton.vue';
import type { Tool } from '@/tools/tools.types';
const { t } = useI18n();
const route = useRoute();
const i18nKey = computed<string>(() => route.path.trim().replace('/', ''));
const head = computed<HeadObject>(() => ({
title: `${route.meta.name} - IT Tools`,
title: `${t(`tools.${i18nKey.value}.title`)} - IT Tools`,
meta: [
{
name: 'description',
content: route.meta?.description as string,
content: t(`tools.${i18nKey.value}.description`),
},
{
name: 'keywords',
@ -23,9 +26,7 @@ const head = computed<HeadObject>(() => ({
],
}));
useHead(head);
const { t } = useI18n();
const i18nKey = computed<string>(() => route.path.trim().replace('/', ''));
const toolTitle = computed<string>(() => t(`tools.${i18nKey.value}.title`, String(route.meta.name)));
const toolDescription = computed<string>(() => t(`tools.${i18nKey.value}.description`, String(route.meta.description)));
</script>

View file

@ -6,6 +6,7 @@ import { createI18n } from 'vue-i18n';
const i18n = createI18n({
legacy: false,
locale: 'en',
fallbackLocale: 'en',
messages,
});
@ -15,7 +16,7 @@ export const i18nPlugin: Plugin = {
},
};
export const translate = function (localeKey: string) {
export const translate = function (localeKey: string, named: Record<string, unknown> = {}) {
const hasKey = i18n.global.te(localeKey, get(i18n.global.locale));
return hasKey ? i18n.global.t(localeKey) : localeKey;
return hasKey ? i18n.global.t(localeKey, named) : localeKey;
};

View file

@ -6,13 +6,15 @@ import { useDownloadFileFromBase64 } from '@/composable/downloadBase64';
import { useValidation } from '@/composable/validation';
import { isValidBase64 } from '@/utils/base64';
const { t } = useI18n();
const base64Input = ref('');
const { download } = useDownloadFileFromBase64({ source: base64Input });
const base64InputValidation = useValidation({
source: base64Input,
rules: [
{
message: 'Invalid base 64 string',
message: t('tools.base64-file-converter.invalidMessage'),
validator: value => isValidBase64(value.trim()),
},
],
@ -33,7 +35,7 @@ function downloadFile() {
const fileInput = ref() as Ref<File>;
const { base64: fileBase64 } = useBase64(fileInput);
const { copy: copyFileBase64 } = useCopy({ source: fileBase64, text: 'Base64 string copied to the clipboard' });
const { copy: copyFileBase64 } = useCopy({ source: fileBase64, text: t('tools.base64-file-converter.copied') });
async function onUpload(file: File) {
if (file) {
@ -43,11 +45,11 @@ async function onUpload(file: File) {
</script>
<template>
<c-card title="Base64 to file">
<c-card :title="t('tools.base64-file-converter.base64ToFile.title')">
<c-input-text
v-model:value="base64Input"
multiline
placeholder="Put your base64 file string here..."
:placeholder="t('tools.base64-file-converter.base64ToFile.placeholder')"
rows="5"
:validation="base64InputValidation"
mb-2
@ -55,18 +57,18 @@ async function onUpload(file: File) {
<div flex justify-center>
<c-button :disabled="base64Input === '' || !base64InputValidation.isValid" @click="downloadFile()">
Download file
{{ t('tools.base64-file-converter.buttons.downloadFile') }}
</c-button>
</div>
</c-card>
<c-card title="File to base64">
<c-file-upload title="Drag and drop a file here, or click to select a file" @file-upload="onUpload" />
<c-input-text :value="fileBase64" multiline readonly placeholder="File in base64 will be here" rows="5" my-2 />
<c-card :title="t('tools.base64-file-converter.fileToBase64.title')">
<c-file-upload :title="t('tools.base64-file-converter.fileToBase64.uploadTip')" @file-upload="onUpload" />
<c-input-text :value="fileBase64" multiline readonly :placeholder="t('tools.base64-file-converter.fileToBase64.placeholder')" rows="5" my-2 />
<div flex justify-center>
<c-button @click="copyFileBase64()">
Copy
{{ t('tools.base64-file-converter.buttons.copy') }}
</c-button>
</div>
</c-card>

View file

@ -1,11 +1,11 @@
import { FileDigit } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.base64-file-converter.title'),
name: t('tools.base64-file-converter.title'),
path: '/base64-file-converter',
description: translate('tools.base64-file-converter.description'),
description: t('tools.base64-file-converter.description'),
keywords: ['base64', 'converter', 'upload', 'image', 'file', 'conversion', 'web', 'data', 'format'],
component: () => import('./base64-file-converter.vue'),
icon: FileDigit,

View file

@ -0,0 +1,18 @@
tools:
base64-file-converter:
title: Base64 file converter
description: Convert string, files or images into a it's base64 representation.
base64ToFile:
title: Base64 to file
placeholder: Put your base64 file string here...
fileToBase64:
title: File to base64
placeholder: File in base64 will be here
uploadTip: Drag and drop a file here, or click to select a file
buttons:
downloadFile: Download file
copy: Copy
copied: Base64 string copied to the clipboard
invalidMessage: Invalid base 64 string

View file

@ -0,0 +1,18 @@
tools:
base64-file-converter:
title: Base64 文件转换器
description: 将字符串、文件或图像转换为其 base64 表示形式。
base64ToFile:
title: Base64 转文件
placeholder: 在此处放置您的 base64 文件字符串...
fileToBase64:
title: 文件转 base64
placeholder: base64 文件将在此处
uploadTip: 拖放文件到此处,或点击选择文件
buttons:
downloadFile: 下载文件
copy: 复制
copied: 已复制 base64 字符串到剪贴板
invalidMessage: 无效的 base 64 字符串

View file

@ -6,18 +6,20 @@ import { withDefaultOnError } from '@/utils/defaults';
const encodeUrlSafe = useStorage('base64-string-converter--encode-url-safe', false);
const decodeUrlSafe = useStorage('base64-string-converter--decode-url-safe', false);
const { t } = useI18n();
const textInput = ref('');
const base64Output = computed(() => textToBase64(textInput.value, { makeUrlSafe: encodeUrlSafe.value }));
const { copy: copyTextBase64 } = useCopy({ source: base64Output, text: 'Base64 string copied to the clipboard' });
const { copy: copyTextBase64 } = useCopy({ source: base64Output, text: t('tools.base64-string-converter.base64Copied') });
const base64Input = ref('');
const textOutput = computed(() =>
withDefaultOnError(() => base64ToText(base64Input.value.trim(), { makeUrlSafe: decodeUrlSafe.value }), ''),
);
const { copy: copyText } = useCopy({ source: textOutput, text: 'String copied to the clipboard' });
const { copy: copyText } = useCopy({ source: textOutput, text: t('tools.base64-string-converter.stringCopied') });
const b64ValidationRules = [
{
message: 'Invalid base64 string',
message: t('tools.base64-string-converter.base64InvalidMessage'),
validator: (value: string) => isValidBase64(value.trim(), { makeUrlSafe: decodeUrlSafe.value }),
},
];
@ -25,56 +27,56 @@ const b64ValidationWatch = [decodeUrlSafe];
</script>
<template>
<c-card title="String to base64">
<n-form-item label="Encode URL safe" label-placement="left">
<c-card :title="t('tools.base64-string-converter.stringToBase64.title')">
<n-form-item :label="t('tools.base64-string-converter.stringToBase64.encodeUrl')" label-placement="left">
<n-switch v-model:value="encodeUrlSafe" />
</n-form-item>
<c-input-text
v-model:value="textInput"
multiline
placeholder="Put your string here..."
:placeholder="t('tools.base64-string-converter.stringToBase64.inputPlaceholder')"
rows="5"
label="String to encode"
:label="t('tools.base64-string-converter.stringToBase64.inputLabel')"
raw-text
mb-5
/>
<c-input-text
label="Base64 of string"
:label="t('tools.base64-string-converter.stringToBase64.outputLabel')"
:value="base64Output"
multiline
readonly
placeholder="The base64 encoding of your string will be here"
:placeholder="t('tools.base64-string-converter.stringToBase64.outputPlaceholder')"
rows="5"
mb-5
/>
<div flex justify-center>
<c-button @click="copyTextBase64()">
Copy base64
{{ t('tools.base64-string-converter.buttons.copyBase64') }}
</c-button>
</div>
</c-card>
<c-card title="Base64 to string">
<n-form-item label="Decode URL safe" label-placement="left">
<c-card :title="t('tools.base64-string-converter.base64ToString.title')">
<n-form-item :label="t('tools.base64-string-converter.base64ToString.decodeUrl')" label-placement="left">
<n-switch v-model:value="decodeUrlSafe" />
</n-form-item>
<c-input-text
v-model:value="base64Input"
multiline
placeholder="Your base64 string..."
:placeholder="t('tools.base64-string-converter.base64ToString.inputPlaceholder')"
rows="5"
:validation-rules="b64ValidationRules"
:validation-watch="b64ValidationWatch"
label="Base64 string to decode"
:label="t('tools.base64-string-converter.base64ToString.inputPlaceholder')"
mb-5
/>
<c-input-text
v-model:value="textOutput"
label="Decoded string"
placeholder="The decoded string will be here"
:label="t('tools.base64-string-converter.base64ToString.outputLabel')"
:placeholder="t('tools.base64-string-converter.base64ToString.outputPlaceholder')"
multiline
rows="5"
readonly
@ -83,7 +85,7 @@ const b64ValidationWatch = [decodeUrlSafe];
<div flex justify-center>
<c-button @click="copyText()">
Copy decoded string
{{ t('tools.base64-string-converter.buttons.copyDecodedString') }}
</c-button>
</div>
</c-card>

View file

@ -1,11 +1,11 @@
import { FileDigit } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.base64-string-converter.title'),
name: t('tools.base64-string-converter.title'),
path: '/base64-string-converter',
description: translate('tools.base64-string-converter.description'),
description: t('tools.base64-string-converter.description'),
keywords: ['base64', 'converter', 'conversion', 'web', 'data', 'format', 'atob', 'btoa'],
component: () => import('./base64-string-converter.vue'),
icon: FileDigit,

View file

@ -0,0 +1,26 @@
tools:
base64-string-converter:
title: Base64 string encoder/decoder
description: Simply encode and decode string into a their base64 representation.
stringToBase64:
title: String to base64
encodeUrl: Encode URL safe
inputLabel: String to encode
inputPlaceholder: Put your string here...
outputLabel: Base64 of string
outputPlaceholder: The base64 encoding of your string will be here
base64ToString:
title: Base64 to string
decodeUrl: Decode URL safe
inputLabel: Base64 string to decode
inputPlaceholder: Your base64 string...
outputLabel: Decoded string
outputPlaceholder: The decoded string will be here
buttons:
copyBase64: Copy base64
copyDecodedString: Copy decoded string
base64Copied: Base64 string copied to the clipboard
stringCopied: String copied to the clipboard
base64InvalidMessage: Invalid base64 string

View file

@ -0,0 +1,26 @@
tools:
base64-string-converter:
title: Base64 字符串编码器/解码器
description: 简单地将字符串编码和解码为它们的 base64 表示形式。
stringToBase64:
title: 字符串转 base64
encodeUrl: URL 安全编码
inputLabel: 要编码的字符串
inputPlaceholder: 在此处放置您的字符串...
outputLabel: 字符串的 base64 编码
outputPlaceholder: 您的字符串的 base64 编码将在此处
base64ToString:
title: Base64 转字符串
decodeUrl: URL 安全解码
inputLabel: 要解码的 base64 字符串
inputPlaceholder: 您的 base64 字符串...
outputLabel: 解码后的字符串
outputPlaceholder: 解码后的字符串将在此处
buttons:
copyBase64: 复制 base64
copyDecodedString: 复制解码后的字符串
base64Copied: 已复制 base64 字符串到剪贴板
stringCopied: 字符串已复制到剪贴板
base64InvalidMessage: 无效的 base64 字符串

View file

@ -2,20 +2,21 @@
import { useCopy } from '@/composable/copy';
import { textToBase64 } from '@/utils/base64';
const { t } = useI18n();
const username = ref('');
const password = ref('');
const header = computed(() => `Authorization: Basic ${textToBase64(`${username.value}:${password.value}`)}`);
const { copy } = useCopy({ source: header, text: 'Header copied to the clipboard' });
const { copy } = useCopy({ source: header, text: t('tools.basic-auth-generator.copied') });
</script>
<template>
<div>
<c-input-text v-model:value="username" label="Username" placeholder="Your username..." clearable raw-text mb-5 />
<c-input-text v-model:value="username" :label="t('tools.basic-auth-generator.username.inputLabel')" :placeholder="t('tools.basic-auth-generator.username.inputPlaceholder')" clearable raw-text mb-5 />
<c-input-text
v-model:value="password"
label="Password"
placeholder="Your password..."
:label="t('tools.basic-auth-generator.password.inputLabel')"
:placeholder="t('tools.basic-auth-generator.password.inputPlaceholder')"
clearable
raw-text
mb-2
@ -23,7 +24,7 @@ const { copy } = useCopy({ source: header, text: 'Header copied to the clipboard
/>
<c-card>
<n-statistic label="Authorization header:" class="header">
<n-statistic :label="t('tools.basic-auth-generator.outputTitle')" class="header">
<n-scrollbar x-scrollable style="max-width: 550px; margin-bottom: -10px; padding-bottom: 10px" trigger="none">
{{ header }}
</n-scrollbar>
@ -31,7 +32,7 @@ const { copy } = useCopy({ source: header, text: 'Header copied to the clipboard
</c-card>
<div mt-5 flex justify-center>
<c-button @click="copy()">
Copy header
{{ t('tools.basic-auth-generator.copyHeader') }}
</c-button>
</div>
</div>

View file

@ -1,11 +1,11 @@
import { PasswordRound } from '@vicons/material';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.basic-auth-generator.title'),
name: t('tools.basic-auth-generator.title'),
path: '/basic-auth-generator',
description: translate('tools.basic-auth-generator.description'),
description: t('tools.basic-auth-generator.description'),
keywords: [
'basic',
'auth',

View file

@ -0,0 +1,15 @@
tools:
basic-auth-generator:
title: Basic auth generator
description: Generate a base64 basic auth header from an username and a password.
username:
inputLabel: Username
inputPlaceholder: Your username...
password:
inputLabel: Password
inputPlaceholder: Your password...
outputTitle: 'Authorization header:'
copyHeader: Copy header
copied: Header copied to the clipboard

View file

@ -0,0 +1,15 @@
tools:
basic-auth-generator:
title: Basic auth 生成器
description: 从用户名和密码生成一个 base64 基本授权头。
username:
inputLabel: 用户名
inputPlaceholder: 您的用户名...
password:
inputLabel: 密码
inputPlaceholder: 您的密码...
outputTitle: '授权头:'
copyHeader: 复制授权头
copied: 授权头已复制到剪贴板

View file

@ -4,11 +4,12 @@ import { useThemeVars } from 'naive-ui';
import { useCopy } from '@/composable/copy';
const themeVars = useThemeVars();
const { t } = useI18n();
const input = ref('');
const saltCount = ref(10);
const hashed = computed(() => hashSync(input.value, saltCount.value));
const { copy } = useCopy({ source: hashed, text: 'Hashed string copied to the clipboard' });
const { copy } = useCopy({ source: hashed, text: t('tools.bcrypt.copied') });
const compareString = ref('');
const compareHash = ref('');
@ -16,41 +17,51 @@ const compareMatch = computed(() => compareSync(compareString.value, compareHash
</script>
<template>
<c-card title="Hash">
<c-card :title="t('tools.bcrypt.hash.title')">
<c-input-text
v-model:value="input"
placeholder="Your string to bcrypt..."
:placeholder="t('tools.bcrypt.hash.placeholder')"
raw-text
label="Your string: "
:label="t('tools.bcrypt.hash.label')"
label-position="left"
label-align="right"
label-width="120px"
mb-2
/>
<n-form-item label="Salt count: " label-placement="left" label-width="120">
<n-input-number v-model:value="saltCount" placeholder="Salt rounds..." :max="10" :min="0" w-full />
<n-form-item :label="t('tools.bcrypt.hash.saltCount')" label-placement="left" label-width="120">
<n-input-number
v-model:value="saltCount"
:placeholder="t('tools.bcrypt.hash.saltCountPlaceholder')"
:max="10"
:min="0"
w-full
/>
</n-form-item>
<c-input-text :value="hashed" readonly text-center />
<div mt-5 flex justify-center>
<c-button @click="copy()">
Copy hash
{{ t('tools.bcrypt.hash.copy') }}
</c-button>
</div>
</c-card>
<c-card title="Compare string with hash">
<c-card :title="t('tools.bcrypt.compare.title')">
<n-form label-width="120">
<n-form-item label="Your string: " label-placement="left">
<c-input-text v-model:value="compareString" placeholder="Your string to compare..." raw-text />
<n-form-item :label="t('tools.bcrypt.compare.stringLabel')" label-placement="left">
<c-input-text
v-model:value="compareString"
:placeholder="t('tools.bcrypt.compare.stringPlaceholder')"
raw-text
/>
</n-form-item>
<n-form-item label="Your hash: " label-placement="left">
<c-input-text v-model:value="compareHash" placeholder="Your hash to compare..." raw-text />
<n-form-item :label="t('tools.bcrypt.compare.hashLabel')" label-placement="left">
<c-input-text v-model:value="compareHash" :placeholder="t('tools.bcrypt.compare.hashPlaceholder')" raw-text />
</n-form-item>
<n-form-item label="Do they match ? " label-placement="left" :show-feedback="false">
<n-form-item :label="t('tools.bcrypt.compare.match')" label-placement="left" :show-feedback="false">
<div class="compare-result" :class="{ positive: compareMatch }">
{{ compareMatch ? 'Yes' : 'No' }}
{{ compareMatch ? t('tools.bcrypt.compare.yes') : t('tools.bcrypt.compare.no') }}
</div>
</n-form-item>
</n-form>

View file

@ -1,11 +1,11 @@
import { LockSquare } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.bcrypt.title'),
name: t('tools.bcrypt.title'),
path: '/bcrypt',
description: translate('tools.bcrypt.description'),
description: t('tools.bcrypt.description'),
keywords: ['bcrypt', 'hash', 'compare', 'password', 'salt', 'round', 'storage', 'crypto'],
component: () => import('./bcrypt.vue'),
icon: LockSquare,

View file

@ -0,0 +1,22 @@
tools:
bcrypt:
title: Bcrypt
description: Hash and compare text string using bcrypt. Bcrypt is a password-hashing function based on the Blowfish cipher.
copied: Hashed string copied to the clipboard
hash:
title: Hash
placeholder: Your string to bcrypt...
label: 'Your string: '
saltCount: 'Salt count: '
saltCountPlaceholder: Salt rounds...
copy: Copy hash
compare:
title: Compare string with hash
stringLabel: 'Your string: '
stringPlaceholder: Your string to compare...
hashLabel: 'Your hash: '
hashPlaceholder: Your hash to compare...
match: Do they match ?
yes: Yes
no: No

View file

@ -0,0 +1,22 @@
tools:
bcrypt:
title: Bcrypt 加密
description: 使用 bcrypt 对文本字符串进行哈希计算和比较。Bcrypt 是基于 Blowfish 密码算法的密码哈希函数。
copied: 哈希字符串已复制到剪贴板
hash:
title: 哈希
placeholder: 要加密的字符串...
label: '您的字符串:'
saltCount: '盐计数:'
saltCountPlaceholder: 盐轮数...
copy: 复制哈希
compare:
title: 与哈希值比较字符串
stringLabel: '您的字符串:'
stringPlaceholder: 要比较的字符串...
hashLabel: '您的哈希值:'
hashPlaceholder: 要比较的哈希值...
match: 它们是否匹配?
yes:
no:

View file

@ -7,6 +7,7 @@ import { arrayToMarkdownTable, computeAverage, computeVariance } from './benchma
import DynamicValues from './dynamic-values.vue';
import { useCopy } from '@/composable/copy';
const { t } = useI18n();
const suites = useStorage('benchmark-builder:suites', [
{ title: 'Suite 1', data: [5, 10] },
{ title: 'Suite 2', data: [8, 12] },
@ -51,11 +52,11 @@ const results = computed(() => {
const { copy } = useCopy({ createToast: false });
const header = {
position: 'Position',
title: 'Suite',
size: 'Samples',
mean: 'Mean',
variance: 'Variance',
position: t('tools.benchmark-builder.header.position'),
title: t('tools.benchmark-builder.header.title'),
size: t('tools.benchmark-builder.header.size'),
mean: t('tools.benchmark-builder.header.mean'),
variance: t('tools.benchmark-builder.header.variance'),
};
function copyAsMarkdown() {
@ -86,13 +87,13 @@ function copyAsBulletList() {
<c-input-text
v-model:value="suite.title"
label-position="left"
label="Suite name"
placeholder="Suite name..."
:label="t('tools.benchmark-builder.suiteNameLabel')"
:placeholder="t('tools.benchmark-builder.suiteNamePlaceholder')"
clearable
/>
<n-divider />
<n-form-item label="Suite values" :show-feedback="false">
<n-form-item :label="t('tools.benchmark-builder.suiteValues')" :show-feedback="false">
<DynamicValues v-model:values="suite.data" />
</n-form-item>
</c-card>
@ -100,14 +101,14 @@ function copyAsBulletList() {
<div flex justify-center>
<c-button v-if="suites.length > 1" variant="text" @click="suites.splice(index, 1)">
<n-icon :component="Trash" depth="3" mr-2 size="18" />
Delete suite
{{ t('tools.benchmark-builder.deleteSuite') }}
</c-button>
<c-button
variant="text"
@click="suites.splice(index + 1, 0, { data: [0], title: `Suite ${suites.length + 1}` })"
>
<n-icon :component="Plus" depth="3" mr-2 size="18" />
Add suite
{{ t('tools.benchmark-builder.addSuite') }}
</c-button>
</div>
</div>
@ -117,7 +118,7 @@ function copyAsBulletList() {
<div style="flex: 0 0 100%">
<div style="max-width: 600px; margin: 0 auto">
<div mx-auto max-w-sm flex justify-center gap-3>
<c-input-text v-model:value="unit" placeholder="Unit (eg: ms)" label="Unit" label-position="left" mb-4 />
<c-input-text v-model:value="unit" :placeholder="t('tools.benchmark-builder.unitPlaceholder')" :label="t('tools.benchmark-builder.unitLabel')" label-position="left" mb-4 />
<c-button
@click="
@ -127,7 +128,7 @@ function copyAsBulletList() {
]
"
>
Reset suites
{{ t('tools.benchmark-builder.resetSuites') }}
</c-button>
</div>
@ -135,10 +136,10 @@ function copyAsBulletList() {
<div mt-5 flex justify-center gap-3>
<c-button @click="copyAsMarkdown()">
Copy as markdown table
{{ t('tools.benchmark-builder.copyAsMarkdown') }}
</c-button>
<c-button @click="copyAsBulletList()">
Copy as bullet list
{{ t('tools.benchmark-builder.copyAsBulletList') }}
</c-button>
</div>
</div>

View file

@ -10,6 +10,7 @@ const emit = defineEmits(['update:values']);
const refs = useTemplateRefsList<typeof NInputNumber>();
const { t } = useI18n();
const values = useVModel(props, 'values', emit);
async function addValue() {
@ -35,11 +36,11 @@ function onInputEnter(index: number) {
:ref="refs.set"
v-model:value="values[index]"
:show-button="false"
placeholder="Set your measure..."
:placeholder="t('tools.benchmark-builder.setYourMeasure')"
autofocus
@keydown.enter="onInputEnter(index)"
/>
<c-tooltip tooltip="Delete this value">
<c-tooltip :tooltip="t('tools.benchmark-builder.deleteThisValue')">
<c-button circle variant="text" @click="values.splice(index, 1)">
<n-icon :component="Trash" depth="3" size="18" />
</c-button>
@ -48,7 +49,7 @@ function onInputEnter(index: number) {
<c-button @click="addValue">
<n-icon :component="Plus" depth="3" mr-2 size="18" />
Add a measure
{{ t('tools.benchmark-builder.addAMeasure') }}
</c-button>
</div>
</template>

View file

@ -1,11 +1,11 @@
import { SpeedFilled } from '@vicons/material';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.benchmark-builder.title'),
name: t('tools.benchmark-builder.title'),
path: '/benchmark-builder',
description: translate('tools.benchmark-builder.description'),
description: t('tools.benchmark-builder.description'),
keywords: ['benchmark', 'builder', 'execution', 'duration', 'mean', 'variance'],
component: () => import('./benchmark-builder.vue'),
icon: SpeedFilled,

View file

@ -0,0 +1,26 @@
tools:
benchmark-builder:
title: Benchmark builder
description: Easily compare execution time of tasks with this very simple online benchmark builder.
header:
position: Position
title: Suite
size: Samples
mean: Mean
variance: Variance
suiteNameLabel: Suite name
suiteNamePlaceholder: Suite name...
suiteValues: Suite values
suiteTitle: Suite {index}
deleteSuite: Delete suite
addSuite: Add suite
resetSuites: Reset suites
unitLabel: Unit
unitPlaceholder: 'Unit (eg: ms)'
setYourMeasure: Set your measure...
deleteThisValue: Delete this value
addAMeasure: Add a measure
copyAsMarkdown: Copy as markdown table
copyAsBulletList: Copy as bullet list

View file

@ -0,0 +1,26 @@
tools:
benchmark-builder:
title: 基准测试生成器
description: 使用这个非常简单的在线基准测试生成器轻松比较任务的执行时间。
header:
position: 位置
title: 套件
size: 样本数
mean: 平均值
variance: 方差
suiteNameLabel: 套件名称
suiteNamePlaceholder: 输入套件名称...
suiteValues: 套件数值
suiteTitle: 套件 {index}
deleteSuite: 删除套件
addSuite: 添加套件
resetSuites: 重置套件
unitLabel: 单位
unitPlaceholder: '单位(例如:毫秒)'
setYourMeasure: 设置您的度量...
deleteThisValue: 删除此数值
addAMeasure: 添加一个度量
copyAsMarkdown: 复制为 markdown 表格
copyAsBulletList: 复制为项目列表

View file

@ -36,6 +36,7 @@ const languages = {
const entropy = ref(generateEntropy());
const passphraseInput = ref('');
const { t } = useI18n();
const language = ref<keyof typeof languages>('English');
const passphrase = computed({
@ -53,11 +54,11 @@ const entropyValidation = useValidation({
rules: [
{
validator: value => value === '' || (value.length <= 32 && value.length >= 16 && value.length % 4 === 0),
message: 'Entropy length should be >= 16, <= 32 and be a multiple of 4',
message: t('tools.bip39-generator.validation.lengthError'),
},
{
validator: value => /^[a-fA-F0-9]*$/.test(value),
message: 'Entropy should be an hexadecimal string',
message: t('tools.bip39-generator.validation.stringTypeError'),
},
],
});
@ -67,7 +68,7 @@ const mnemonicValidation = useValidation({
rules: [
{
validator: value => isNotThrowing(() => mnemonicToEntropy(value, languages[language.value])),
message: 'Invalid mnemonic',
message: t('tools.bip39-generator.validation.mnemonicError'),
},
],
});
@ -76,8 +77,8 @@ function refreshEntropy() {
entropy.value = generateEntropy();
}
const { copy: copyEntropy } = useCopy({ source: entropy, text: 'Entropy copied to the clipboard' });
const { copy: copyPassphrase } = useCopy({ source: passphrase, text: 'Passphrase copied to the clipboard' });
const { copy: copyEntropy } = useCopy({ source: entropy, text: t('tools.bip39-generator.copied.entropy') });
const { copy: copyPassphrase } = useCopy({ source: passphrase, text: t('tools.bip39-generator.copied.passphrase') });
</script>
<template>
@ -87,18 +88,18 @@ const { copy: copyPassphrase } = useCopy({ source: passphrase, text: 'Passphrase
<c-select
v-model:value="language"
searchable
label="Language:"
:label="t('tools.bip39-generator.languageLabel')"
:options="Object.keys(languages)"
/>
</n-gi>
<n-gi span="2">
<n-form-item
label="Entropy (seed):"
:label="t('tools.bip39-generator.entropyLabel')"
:feedback="entropyValidation.message"
:validation-status="entropyValidation.status"
>
<n-input-group>
<c-input-text v-model:value="entropy" placeholder="Your string..." />
<c-input-text v-model:value="entropy" :placeholder="t('tools.bip39-generator.entropyPlaceholder')" />
<c-button @click="refreshEntropy()">
<n-icon size="22">
@ -115,12 +116,12 @@ const { copy: copyPassphrase } = useCopy({ source: passphrase, text: 'Passphrase
</n-gi>
</n-grid>
<n-form-item
label="Passphrase (mnemonic):"
:label="t('tools.bip39-generator.passphraseLabel')"
:feedback="mnemonicValidation.message"
:validation-status="mnemonicValidation.status"
>
<n-input-group>
<c-input-text v-model:value="passphrase" placeholder="Your mnemonic..." raw-text />
<c-input-text v-model:value="passphrase" :placeholder="t('tools.bip39-generator.passphrasePlaceholder')" raw-text />
<c-button @click="copyPassphrase()">
<n-icon size="22" :component="Copy" />

View file

@ -1,11 +1,11 @@
import { AlignJustified } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.bip39-generator.title'),
name: t('tools.bip39-generator.title'),
path: '/bip39-generator',
description: translate('tools.bip39-generator.description'),
description: t('tools.bip39-generator.description'),
keywords: ['BIP39', 'passphrase', 'generator', 'mnemonic', 'entropy'],
component: () => import('./bip39-generator.vue'),
icon: AlignJustified,

View file

@ -0,0 +1,18 @@
tools:
bip39-generator:
title: BIP39 passphrase generator
description: Generate BIP39 passphrase from existing or random mnemonic, or get the mnemonic from the passphrase.
languageLabel: 'Language:'
entropyLabel: 'Entropy (seed):'
entropyPlaceholder: Your string...
passphraseLabel: 'Passphrase (mnemonic):'
passphrasePlaceholder: Your mnemonic...
validation:
lengthError: 'Entropy length should be >= 16, <= 32 and be a multiple of 4'
stringTypeError: Entropy should be an hexadecimal string
mnemonicError: Invalid mnemonic
copied:
entropy: Entropy copied to the clipboard
passphrase: Passphrase copied to the clipboard

View file

@ -0,0 +1,18 @@
tools:
bip39-generator:
title: BIP39 助记词生成器
description: 从现有或随机助记词生成 BIP39 助记词,或从助记词获取助记词。
languageLabel: '语言:'
entropyLabel: '熵(种子):'
entropyPlaceholder: 您的字符串...
passphraseLabel: '助记词(口令):'
passphrasePlaceholder: 您的助记词...
validation:
lengthError: '熵的长度应为 >= 16<= 32并且是4的倍数'
stringTypeError: 熵应为十六进制字符串
mnemonicError: 无效的助记词
copied:
entropy: 熵已复制到剪贴板
passphrase: 助记词已复制到剪贴板

View file

@ -19,6 +19,8 @@ const {
},
});
const { t } = useI18n();
const video = ref<HTMLVideoElement>();
const medias = ref<Media[]>([]);
const currentCamera = ref(cameras.value[0]?.deviceId);
@ -106,20 +108,19 @@ function downloadMedia({ type, value, createdAt }: Media) {
<template>
<div>
<c-card v-if="!isSupported">
Your browser does not support recording video from camera
{{ t('tools.camera-recorder.unSupported') }}
</c-card>
<c-card v-else-if="!permissionGranted" text-center>
You need to grant permission to use your camera and microphone
{{ t('tools.camera-recorder.needPermissionGranted') }}
<c-alert v-if="permissionCannotBePrompted" mt-4 text-left>
Your browser has blocked permission request or does not support it. You need to grant permission manually in
your browser settings (usually the lock icon in the address bar).
{{ t('tools.camera-recorder.permissionCannotBePrompted') }}
</c-alert>
<div v-else mt-4 flex justify-center>
<c-button @click="requestPermissions">
Grant permission
{{ t('tools.camera-recorder.grantPermission') }}
</c-button>
</div>
</c-card>
@ -130,24 +131,24 @@ function downloadMedia({ type, value, createdAt }: Media) {
v-model:value="currentCamera"
label-position="left"
label-width="60px"
label="Video:"
:label="t('tools.camera-recorder.cameraLabel')"
:options="cameras.map(({ deviceId, label }) => ({ value: deviceId, label }))"
placeholder="Select camera"
:placeholder="t('tools.camera-recorder.cameraPlaceholder')"
/>
<c-select
v-if="currentMicrophone && microphones.length > 0"
v-model:value="currentMicrophone"
label="Audio:"
:label="t('tools.camera-recorder.microphoneLabel')"
label-position="left"
label-width="60px"
:options="microphones.map(({ deviceId, label }) => ({ value: deviceId, label }))"
placeholder="Select microphone"
:placeholder="t('tools.camera-recorder.microphonePlaceholder')"
/>
</div>
<div v-if="!isMediaStreamAvailable" mt-3 flex justify-center>
<c-button type="primary" @click="start">
Start webcam
{{ t('tools.camera-recorder.startWebcam') }}
</c-button>
</div>
@ -159,32 +160,32 @@ function downloadMedia({ type, value, createdAt }: Media) {
<div flex items-center justify-between gap-2>
<c-button :disabled="!isMediaStreamAvailable" @click="takeScreenshot">
<span mr-2> <icon-mdi-camera /></span>
Take screenshot
{{ t('tools.camera-recorder.takeScreenshot') }}
</c-button>
<div v-if="isRecordingSupported" flex justify-center gap-2>
<c-button v-if="recordingState === 'stopped'" @click="startRecording">
<span mr-2> <icon-mdi-video /></span>
Start recording
{{ t('tools.camera-recorder.startRecording') }}
</c-button>
<c-button v-if="recordingState === 'recording'" @click="pauseRecording">
<span mr-2> <icon-mdi-pause /></span>
Pause
{{ t('tools.camera-recorder.pause') }}
</c-button>
<c-button v-if="recordingState === 'paused'" @click="resumeRecording">
<span mr-2> <icon-mdi-play /></span>
Resume
{{ t('tools.camera-recorder.resume') }}
</c-button>
<c-button v-if="recordingState !== 'stopped'" type="error" @click="stopRecording">
<span mr-2> <icon-mdi-record /></span>
Stop
{{ t('tools.camera-recorder.stop') }}
</c-button>
</div>
<div v-else italic op-60>
Video recording is not supported in your browser
{{ t('tools.camera-recorder.unSupportRecord') }}
</div>
</div>
</div>
@ -192,13 +193,13 @@ function downloadMedia({ type, value, createdAt }: Media) {
<div grid grid-cols-2 mt-5 gap-2>
<c-card v-for="({ type, value, createdAt }, index) in medias" :key="index">
<img v-if="type === 'image'" :src="value" max-h-full w-full alt="screenshot">
<img v-if="type === 'image'" :src="value" max-h-full w-full :alt="t('tools.camera-recorder.screenshot')">
<video v-else :src="value" controls max-h-full w-full />
<div flex items-center justify-between>
<div font-bold>
{{ type === 'image' ? 'Screenshot' : 'Video' }}
{{ type === 'image' ? t('tools.camera-recorder.screenshot') : t('tools.camera-recorder.video') }}
</div>
<div flex gap-2>

View file

@ -1,11 +1,11 @@
import { Camera } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.camera-recorder.title'),
name: t('tools.camera-recorder.title'),
path: '/camera-recorder',
description: translate('tools.camera-recorder.description'),
description: t('tools.camera-recorder.description'),
keywords: ['camera', 'recoder'],
component: () => import('./camera-recorder.vue'),
icon: Camera,

View file

@ -0,0 +1,22 @@
tools:
camera-recorder:
title: Camera recorder
description: Take a picture or record a video from your webcam or camera.
unSupported: Your browser does not support recording video from camera
needPermissionGranted: You need to grant permission to use your camera and microphone
permissionCannotBePrompted: Your browser has blocked permission request or does not support it. You need to grant permission manually in your browser settings (usually the lock icon in the address bar).
grantPermission: Grant permission
cameraLabel: 'Video:'
cameraPlaceholder: Select camera
microphoneLabel: 'Audio:'
microphonePlaceholder: Select microphone
startWebcam: Start webcam
takeScreenshot: Take screenshot
startRecording: Start recording
pause: Pause
resume: Resume
stop: Stop
unSupportRecord: Video recording is not supported in your browser
screenshot: screenshot
video: Video

View file

@ -0,0 +1,22 @@
tools:
camera-recorder:
title: 摄像头录制器
description: 从您的网络摄像头或相机拍照或录制视频。
unSupported: 您的浏览器不支持从摄像头录制视频
needPermissionGranted: 您需要授予使用摄像头和麦克风的权限
permissionCannotBePrompted: 您的浏览器已阻止权限请求或不支持它。 您需要在浏览器设置中手动授予权限(通常在地址栏中的锁图标)。
grantPermission: 授予权限
cameraLabel: '视频:'
cameraPlaceholder: 选择摄像头
microphoneLabel: '音频:'
microphonePlaceholder: 选择麦克风
startWebcam: 启动网络摄像头
takeScreenshot: 拍照
startRecording: 开始录制
pause: 暂停
resume: 恢复
stop: 停止
unSupportRecord: 您的浏览器不支持视频录制
screenshot: 截图
video: 视频

View file

@ -18,63 +18,65 @@ const baseConfig = {
stripRegexp: /[^A-Za-zÀ-ÖØ-öø-ÿ]+/gi,
};
const { t } = useI18n();
const input = ref('lorem ipsum dolor sit amet');
const formats = computed(() => [
{
label: 'Lowercase:',
label: t('tools.case-converter.lowercase'),
value: input.value.toLocaleLowerCase(),
},
{
label: 'Uppercase:',
label: t('tools.case-converter.uppercase'),
value: input.value.toLocaleUpperCase(),
},
{
label: 'Camelcase:',
label: t('tools.case-converter.camelcase'),
value: camelCase(input.value, baseConfig),
},
{
label: 'Capitalcase:',
label: t('tools.case-converter.capitalcase'),
value: capitalCase(input.value, baseConfig),
},
{
label: 'Constantcase:',
label: t('tools.case-converter.constantcase'),
value: constantCase(input.value, baseConfig),
},
{
label: 'Dotcase:',
label: t('tools.case-converter.dotcase'),
value: dotCase(input.value, baseConfig),
},
{
label: 'Headercase:',
label: t('tools.case-converter.headercase'),
value: headerCase(input.value, baseConfig),
},
{
label: 'Nocase:',
label: t('tools.case-converter.nocase'),
value: noCase(input.value, baseConfig),
},
{
label: 'Paramcase:',
label: t('tools.case-converter.paramcase'),
value: paramCase(input.value, baseConfig),
},
{
label: 'Pascalcase:',
label: t('tools.case-converter.pascalcase'),
value: pascalCase(input.value, baseConfig),
},
{
label: 'Pathcase:',
label: t('tools.case-converter.pathcase'),
value: pathCase(input.value, baseConfig),
},
{
label: 'Sentencecase:',
label: t('tools.case-converter.sentencecase'),
value: sentenceCase(input.value, baseConfig),
},
{
label: 'Snakecase:',
label: t('tools.case-converter.snakecase'),
value: snakeCase(input.value, baseConfig),
},
{
label: 'Mockingcase:',
label: t('tools.case-converter.mockingcase'),
value: input.value
.split('')
.map((char, index) => (index % 2 === 0 ? char.toUpperCase() : char.toLowerCase()))
@ -93,8 +95,8 @@ const inputLabelAlignmentConfig = {
<c-card>
<c-input-text
v-model:value="input"
label="Your string:"
placeholder="Your string..."
:label="t('tools.case-converter.inputLabel')"
:placeholder="t('tools.case-converter.inputPlaceholder')"
raw-text
v-bind="inputLabelAlignmentConfig"
/>

View file

@ -1,11 +1,11 @@
import { LetterCaseToggle } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.case-converter.title'),
name: t('tools.case-converter.title'),
path: '/case-converter',
description: translate('tools.case-converter.description'),
description: t('tools.case-converter.description'),
keywords: [
'case',
'converter',

View file

@ -0,0 +1,22 @@
tools:
case-converter:
title: Case converter
description: Change the case of a string and chose between different formats
inputLabel: 'Your string:'
inputPlaceholder: Your string...
lowercase: 'Lowercase:'
uppercase: 'Uppercase:'
camelcase: 'Camelcase:'
capitalcase: 'Capitalcase:'
constantcase: 'Constantcase:'
dotcase: 'Dotcase:'
headercase: 'Headercase:'
nocase: 'Nocase:'
paramcase: 'Paramcase:'
pascalcase: 'Pascalcase:'
pathcase: 'Pathcase:'
sentencecase: 'Sentencecase:'
snakecase: 'Snakecase:'
mockingcase: 'Mockingcase:'

View file

@ -0,0 +1,22 @@
tools:
case-converter:
title: 大小写转换器
description: 更改字符串的大小写,并在不同格式之间进行选择
inputLabel: '您的字符串:'
inputPlaceholder: 您的字符串...
lowercase: '小写:'
uppercase: '大写:'
camelcase: '驼峰式:'
capitalcase: '首字母大写:'
constantcase: '常量式:'
dotcase: '点式:'
headercase: '标题式:'
nocase: '无格式:'
paramcase: '参数式:'
pascalcase: '帕斯卡式:'
pathcase: '路径式:'
sentencecase: '句式:'
snakecase: '蛇式:'
mockingcase: '嘲讽式:'

View file

@ -7,11 +7,12 @@ import { computeChmodOctalRepresentation, computeChmodSymbolicRepresentation } f
import type { Group, Scope } from './chmod-calculator.types';
const themeVars = useThemeVars();
const { t } = useI18n();
const scopes: { scope: Scope; title: string }[] = [
{ scope: 'read', title: 'Read (4)' },
{ scope: 'write', title: 'Write (2)' },
{ scope: 'execute', title: 'Execute (1)' },
{ scope: 'read', title: t('tools.chmod-calculator.read') },
{ scope: 'write', title: t('tools.chmod-calculator.write') },
{ scope: 'execute', title: t('tools.chmod-calculator.execute') },
];
const groups: Group[] = ['owner', 'group', 'public'];
@ -32,13 +33,13 @@ const symbolic = computed(() => computeChmodSymbolicRepresentation({ permissions
<tr>
<th class="text-center" scope="col" />
<th class="text-center" scope="col">
Owner (u)
{{ t('tools.chmod-calculator.owner') }}
</th>
<th class="text-center" scope="col">
Group (g)
{{ t('tools.chmod-calculator.group') }}
</th>
<th class="text-center" scope="col">
Public (o)
{{ t('tools.chmod-calculator.public') }}
</th>
</tr>
</thead>

View file

@ -1,11 +1,11 @@
import { FileInvoice } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.chmod-calculator.title'),
name: t('tools.chmod-calculator.title'),
path: '/chmod-calculator',
description: translate('tools.chmod-calculator.description'),
description: t('tools.chmod-calculator.description'),
keywords: [
'chmod',
'calculator',

View file

@ -0,0 +1,11 @@
tools:
chmod-calculator:
title: Chmod calculator
description: Compute your chmod permissions and commands with this online chmod calculator.
read: 'Read (4)'
write: 'Write (2)'
execute: 'Execute (1)'
owner: 'Owner (u)'
group: 'Group (g)'
public: Public (o)

View file

@ -0,0 +1,11 @@
tools:
chmod-calculator:
title: Chmod 计算器
description: 使用此在线 Chmod 计算器计算您的 Chmod 权限和命令。
read: '读取 (4)'
write: '写入 (2)'
execute: '执行 (1)'
owner: '所有者 (u)'
group: '群组 (g)'
public: 公共 (o)

View file

@ -3,6 +3,7 @@ import { useRafFn } from '@vueuse/core';
import { formatMs } from './chronometer.service';
const { t } = useI18n();
const isRunning = ref(false);
const counter = ref(0);
@ -37,14 +38,14 @@ function pause() {
</c-card>
<div mt-5 flex justify-center gap-3>
<c-button v-if="!isRunning" type="primary" @click="resume">
Start
{{ t('tools.chronometer.start') }}
</c-button>
<c-button v-else type="warning" @click="pause">
Stop
{{ t('tools.chronometer.stop') }}
</c-button>
<c-button @click="counter = 0">
Reset
{{ t('tools.chronometer.reset') }}
</c-button>
</div>
</div>

View file

@ -1,11 +1,11 @@
import { TimerOutlined } from '@vicons/material';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.chronometer.title'),
name: t('tools.chronometer.title'),
path: '/chronometer',
description: translate('tools.chronometer.description'),
description: t('tools.chronometer.description'),
keywords: ['chronometer', 'time', 'lap', 'duration', 'measure', 'pause', 'resume', 'stopwatch'],
component: () => import('./chronometer.vue'),
icon: TimerOutlined,

View file

@ -0,0 +1,8 @@
tools:
chronometer:
title: Chronometer
description: Monitor the duration of a thing. Basically a chronometer with simple chronometer features.
start: Start
stop: Stop
reset: Reset

View file

@ -0,0 +1,8 @@
tools:
chronometer:
title: 计时器
description: 监控事物的持续时间。基本上是一个具有简单计时器功能的计时器。
start: 开始
stop: 停止
reset: 重置

View file

@ -1,6 +1,7 @@
import { type Colord, colord } from 'colord';
import { withDefaultOnError } from '@/utils/defaults';
import { useValidation } from '@/composable/validation';
import { translate as t } from '@/plugins/i18n.plugin';
export { removeAlphaChannelWhenOpaque, buildColorFormat };
@ -13,7 +14,7 @@ function buildColorFormat({
parse = value => colord(value),
format,
placeholder,
invalidMessage = `Invalid ${label.toLowerCase()} format.`,
invalidMessage = t('tools.color-converter.invalidMessage', { format: label.toLowerCase() }),
type = 'text',
}: {
label: string

View file

@ -10,9 +10,11 @@ import { buildColorFormat } from './color-converter.models';
extend([cmykPlugin, hwbPlugin, namesPlugin, lchPlugin]);
const { t } = useI18n();
const formats = {
picker: buildColorFormat({
label: 'color picker',
label: t('tools.color-converter.colorPicker'),
format: (v: Colord) => v.toHex(),
type: 'color-picker',
}),
@ -47,7 +49,7 @@ const formats = {
placeholder: 'e.g. cmyk(0, 100%, 100%, 0)',
}),
name: buildColorFormat({
label: 'name',
label: t('tools.color-converter.name'),
format: (v: Colord) => v.toName({ closest: true }) ?? 'Unknown',
placeholder: 'e.g. red',
}),

View file

@ -1,11 +1,11 @@
import { Palette } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.color-converter.title'),
name: t('tools.color-converter.title'),
path: '/color-converter',
description: translate('tools.color-converter.description'),
description: t('tools.color-converter.description'),
keywords: ['color', 'converter'],
component: () => import('./color-converter.vue'),
icon: Palette,

View file

@ -0,0 +1,9 @@
tools:
color-converter:
title: Color converter
description: Convert color between the different formats (hex, rgb, hsl and css name).
colorPicker: color picker
name: name
invalidMessage: 'Invalid {format} format.'

View file

@ -0,0 +1,9 @@
tools:
color-converter:
title: 颜色转换器
description: 在不同格式之间转换颜色十六进制、RGB、HSL 和 CSS 名称)。
colorPicker: 颜色选择器
name: 名称
invalidMessage: '无效的 {format} 格式。'

View file

@ -1,5 +1,7 @@
<script setup lang="ts">
import cronstrue from 'cronstrue';
import 'cronstrue/locales/zh_CN';
import 'cronstrue/locales/fr';
import { isValidCron } from 'cron-validator';
import { useStyleStore } from '@/stores/style.store';
@ -9,84 +11,86 @@ function isCronValid(v: string) {
const styleStore = useStyleStore();
const { t, locale } = useI18n();
const cron = ref('40 * * * *');
const cronstrueConfig = reactive({
verbose: true,
dayOfWeekStartIndexZero: true,
use24HourTimeFormat: true,
throwExceptionOnParseError: true,
locale: locale.value === 'zh' ? 'zh_CN' : locale,
});
const helpers = [
{
symbol: '*',
meaning: 'Any value',
meaning: t('tools.crontab-generator.anyMeaning'),
example: '* * * *',
equivalent: 'Every minute',
equivalent: t('tools.crontab-generator.anyExample'),
},
{
symbol: '-',
meaning: 'Range of values',
meaning: t('tools.crontab-generator.rangeMeaning'),
example: '1-10 * * *',
equivalent: 'Minutes 1 through 10',
equivalent: t('tools.crontab-generator.rangeExample'),
},
{
symbol: ',',
meaning: 'List of values',
meaning: t('tools.crontab-generator.listMeaning'),
example: '1,10 * * *',
equivalent: 'At minutes 1 and 10',
equivalent: t('tools.crontab-generator.listExample'),
},
{
symbol: '/',
meaning: 'Step values',
meaning: t('tools.crontab-generator.stepMeaning'),
example: '*/10 * * *',
equivalent: 'Every 10 minutes',
equivalent: t('tools.crontab-generator.stepExample'),
},
{
symbol: '@yearly',
meaning: 'Once every year at midnight of 1 January',
meaning: t('tools.crontab-generator.yearlyMeaning'),
example: '@yearly',
equivalent: '0 0 1 1 *',
},
{
symbol: '@annually',
meaning: 'Same as @yearly',
meaning: t('tools.crontab-generator.annuallyMeaning', { yearly: '@yearly' }),
example: '@annually',
equivalent: '0 0 1 1 *',
},
{
symbol: '@monthly',
meaning: 'Once a month at midnight on the first day',
meaning: t('tools.crontab-generator.monthlyMeaning'),
example: '@monthly',
equivalent: '0 0 1 * *',
},
{
symbol: '@weekly',
meaning: 'Once a week at midnight on Sunday morning',
meaning: t('tools.crontab-generator.weeklyMeaning'),
example: '@weekly',
equivalent: '0 0 * * 0',
},
{
symbol: '@daily',
meaning: 'Once a day at midnight',
meaning: t('tools.crontab-generator.dailyMeaning'),
example: '@daily',
equivalent: '0 0 * * *',
},
{
symbol: '@midnight',
meaning: 'Same as @daily',
meaning: t('tools.crontab-generator.midnightMeaning', { daily: '@daily' }),
example: '@midnight',
equivalent: '0 0 * * *',
},
{
symbol: '@hourly',
meaning: 'Once an hour at the beginning of the hour',
meaning: t('tools.crontab-generator.hourlyMeaning'),
example: '@hourly',
equivalent: '0 * * * *',
},
{
symbol: '@reboot',
meaning: 'Run at startup',
meaning: t('tools.crontab-generator.rebootMeaning'),
example: '',
equivalent: '',
},
@ -102,7 +106,7 @@ const cronString = computed(() => {
const cronValidationRules = [
{
validator: (value: string) => isCronValid(value),
message: 'This cron is invalid',
message: t('tools.crontab-generator.invalidMessage'),
},
];
</script>
@ -127,13 +131,13 @@ const cronValidationRules = [
<div flex justify-center>
<n-form :show-feedback="false" label-width="170" label-placement="left">
<n-form-item label="Verbose">
<n-form-item :label="t('tools.crontab-generator.verbose')">
<n-switch v-model:value="cronstrueConfig.verbose" />
</n-form-item>
<n-form-item label="Use 24 hour time format">
<n-form-item :label="t('tools.crontab-generator.use24HourTimeFormat')">
<n-switch v-model:value="cronstrueConfig.use24HourTimeFormat" />
</n-form-item>
<n-form-item label="Days start at 0">
<n-form-item :label="t('tools.crontab-generator.dayOfWeekStartIndexZero')">
<n-switch v-model:value="cronstrueConfig.dayOfWeekStartIndexZero" />
</n-form-item>
</n-form>
@ -141,29 +145,29 @@ const cronValidationRules = [
</c-card>
<c-card>
<pre>
[optional] seconds (0 - 59)
| minute (0 - 59)
| | hour (0 - 23)
| | | day of month (1 - 31)
| | | | month (1 - 12) OR jan,feb,mar,apr ...
| | | | | day of week (0 - 6, sunday=0) OR sun,mon ...
{{ t('tools.crontab-generator.secondDesc') }}
| {{ t('tools.crontab-generator.minuteDesc') }}
| | {{ t('tools.crontab-generator.hourDesc') }}
| | | {{ t('tools.crontab-generator.dayOfMonthDesc') }}
| | | | {{ t('tools.crontab-generator.monthDesc') }}
| | | | | {{ t('tools.crontab-generator.dayOfWeekDesc') }}
| | | | | |
* * * * * * command</pre>
* * * * * * {{ t('tools.crontab-generator.command') }}</pre>
<div v-if="styleStore.isSmallScreen">
<c-card v-for="{ symbol, meaning, example, equivalent } in helpers" :key="symbol" mb-3 important:border-none>
<div>
Symbol: <strong>{{ symbol }}</strong>
{{ t('tools.crontab-generator.symbol') }} <strong>{{ symbol }}</strong>
</div>
<div>
Meaning: <strong>{{ meaning }}</strong>
{{ t('tools.crontab-generator.meaning') }} <strong>{{ meaning }}</strong>
</div>
<div>
Example:
{{ t('tools.crontab-generator.example') }}
<strong><code>{{ example }}</code></strong>
</div>
<div>
Equivalent: <strong>{{ equivalent }}</strong>
{{ t('tools.crontab-generator.equivalent') }} <strong>{{ equivalent }}</strong>
</div>
</c-card>
</div>

View file

@ -1,11 +1,11 @@
import { Alarm } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.crontab-generator.title'),
name: t('tools.crontab-generator.title'),
path: '/crontab-generator',
description: translate('tools.crontab-generator.description'),
description: t('tools.crontab-generator.description'),
keywords: [
'crontab',
'generator',

View file

@ -0,0 +1,38 @@
tools:
crontab-generator:
title: Crontab generator
description: Validate and generate crontab and get the human readable description of the cron schedule.
anyMeaning: Any value
anyExample: Every minute
rangeMeaning: Range of values
rangeExample: Minutes 1 through 10
listMeaning: List of values
listExample: At minutes 1 and 10
stepMeaning: Step values
stepExample: Every 10 minutes
yearlyMeaning: Once every year at midnight of 1 January
annuallyMeaning: Same as {yearly}
monthlyMeaning: Once a month at midnight on the first day
weeklyMeaning: Once a week at midnight on Sunday morning
dailyMeaning: Once a day at midnight
midnightMeaning: Same as {daily}
hourlyMeaning: Once an hour at the beginning of the hour
rebootMeaning: Run at startup
verbose: Verbose
use24HourTimeFormat: Use 24 hour time format
dayOfWeekStartIndexZero: Days start at 0
secondDesc: '[optional] seconds (0 - 59)'
minuteDesc: 'minute (0 - 59)'
hourDesc: 'hour (0 - 23)'
dayOfMonthDesc: 'day of month (1 - 31)'
monthDesc: 'month (1 - 12) OR jan,feb,mar,apr ...'
dayOfWeekDesc: 'day of week (0 - 6, sunday=0) OR sun,mon ...'
command: command
symbol: 'Symbol:'
meaning: 'Meaning:'
example: 'Example:'
equivalent: 'Equivalent:'
invalidMessage: This cron is invalid

View file

@ -0,0 +1,38 @@
tools:
crontab-generator:
title: 定时任务生成器
description: 验证和生成 crontab并获取定时任务的可读描述。
anyMeaning: 任意值
anyExample: 每分钟
rangeMeaning: 值范围
rangeExample: 1 到 10 分钟
listMeaning: 值列表
listExample: 在第 1 和第 10 分钟
stepMeaning: 步进值
stepExample: 每 10 分钟
yearlyMeaning: 每年 1 月 1 日午夜
annuallyMeaning: '等同于 {yearly}'
monthlyMeaning: 每月第一天午夜
weeklyMeaning: 每周星期日凌晨
dailyMeaning: 每天午夜
midnightMeaning: '等同于 {daily}'
hourlyMeaning: 每小时整点
rebootMeaning: 启动时运行
verbose: 冗长模式
use24HourTimeFormat: 使用 24 小时时间格式
dayOfWeekStartIndexZero: 一周从 0 开始
secondDesc: '[可选] 秒0 - 59'
minuteDesc: '分钟0 - 59'
hourDesc: '小时0 - 23'
dayOfMonthDesc: '日期1 - 31'
monthDesc: '月份1 - 12或 jan、feb、mar、apr ...'
dayOfWeekDesc: '星期几0 - 6星期日=0或 sun、mon ...'
command: 命令
symbol: '符号:'
meaning: '含义:'
example: '示例:'
equivalent: '等同:'
invalidMessage: 此 cron 表达式无效

View file

@ -29,67 +29,69 @@ import {
import { withDefaultOnError } from '@/utils/defaults';
import { useValidation } from '@/composable/validation';
const { t } = useI18n();
const inputDate = ref('');
const toDate: ToDateMapper = date => new Date(date);
const formats: DateFormat[] = [
{
name: 'JS locale date string',
name: t('tools.date-converter.localDate'),
fromDate: date => date.toString(),
toDate,
formatMatcher: () => false,
},
{
name: 'ISO 8601',
name: t('tools.date-converter.ISO8601'),
fromDate: formatISO,
toDate: parseISO,
formatMatcher: date => isISO8601DateTimeString(date),
},
{
name: 'ISO 9075',
name: t('tools.date-converter.ISO9075'),
fromDate: formatISO9075,
toDate: parseISO,
formatMatcher: date => isISO9075DateString(date),
},
{
name: 'RFC 3339',
name: t('tools.date-converter.RFC3339'),
fromDate: formatRFC3339,
toDate,
formatMatcher: date => isRFC3339DateString(date),
},
{
name: 'RFC 7231',
name: t('tools.date-converter.RFC7231'),
fromDate: formatRFC7231,
toDate,
formatMatcher: date => isRFC7231DateString(date),
},
{
name: 'Unix timestamp',
name: t('tools.date-converter.unixTimestamp'),
fromDate: date => String(getUnixTime(date)),
toDate: sec => fromUnixTime(+sec),
formatMatcher: date => isUnixTimestamp(date),
},
{
name: 'Timestamp',
name: t('tools.date-converter.timestamp'),
fromDate: date => String(getTime(date)),
toDate: ms => parseJSON(+ms),
formatMatcher: date => isTimestamp(date),
},
{
name: 'UTC format',
name: t('tools.date-converter.UTCformat'),
fromDate: date => date.toUTCString(),
toDate,
formatMatcher: date => isUTCDateString(date),
},
{
name: 'Mongo ObjectID',
name: t('tools.date-converter.mongoObjectID'),
fromDate: date => `${Math.floor(date.getTime() / 1000).toString(16)}0000000000000000`,
toDate: objectId => new Date(Number.parseInt(objectId.substring(0, 8), 16) * 1000),
formatMatcher: date => isMongoObjectId(date),
},
{
name: 'Excel date/time',
name: t('tools.date-converter.excelDate'),
fromDate: date => dateToExcelFormat(date),
toDate: excelFormatToDate,
formatMatcher: isExcelFormat,
@ -126,7 +128,7 @@ const validation = useValidation({
watch: [formatIndex],
rules: [
{
message: 'This date is invalid for this format',
message: t('tools.date-converter.invalidMessage'),
validator: value =>
withDefaultOnError(() => {
if (value === '') {
@ -155,7 +157,7 @@ function formatDateUsingFormatter(formatter: (date: Date) => string, date?: Date
<c-input-text
v-model:value="inputDate"
autofocus
placeholder="Put your date string here..."
:placeholder="t('tools.date-converter.inputPlaceholder')"
clearable
test-id="date-time-converter-input"
:validation="validation"
@ -180,7 +182,7 @@ function formatDateUsingFormatter(formatter: (date: Date) => string, date?: Date
label-position="left"
label-align="right"
:value="formatDateUsingFormatter(fromDate, normalizedDate)"
placeholder="Invalid date..."
:placeholder="t('tools.date-converter.invalidDatePlaceholder')"
:test-id="name"
readonly
mt-2

View file

@ -1,11 +1,11 @@
import { Calendar } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.date-converter.title'),
name: t('tools.date-converter.title'),
path: '/date-converter',
description: translate('tools.date-converter.description'),
description: t('tools.date-converter.description'),
keywords: ['date', 'time', 'converter', 'iso', 'utc', 'timezone', 'year', 'month', 'day', 'minute', 'seconde'],
component: () => import('./date-time-converter.vue'),
icon: Calendar,

View file

@ -0,0 +1,20 @@
tools:
date-converter:
title: Date-time converter
description: Convert date and time into the various different formats.
inputPlaceholder: Put your date string here...
invalidDatePlaceholder: Invalid date...
localDate: JS locale date string
ISO8601: ISO 8601
ISO9075: ISO 9075
RFC3339: RFC 3339
RFC7231: RFC 7231
unixTimestamp: Unix timestamp
timestamp: Timestamp
UTCformat: UTC format
mongoObjectID: Mongo ObjectID
excelDate: Excel date/time
invalidMessage: This date is invalid for this format

View file

@ -0,0 +1,20 @@
tools:
date-converter:
title: 日期时间转换器
description: 将日期和时间转换为各种不同的格式。
inputPlaceholder: 在此处输入日期字符串...
invalidDatePlaceholder: 无效的日期...
localDate: JS 本地日期字符串
ISO8601: ISO 8601
ISO9075: ISO 9075
RFC3339: RFC 3339
RFC7231: RFC 7231
unixTimestamp: Unix 时间戳
timestamp: 时间戳
UTCformat: UTC 格式
mongoObjectID: Mongo ObjectID
excelDate: Excel 日期/时间
invalidMessage: 该日期不适用于此格式

View file

@ -1,55 +1,56 @@
<script setup lang="ts">
import { useWindowSize } from '@vueuse/core';
const { t } = useI18n();
const { width, height } = useWindowSize();
const sections = [
{
name: 'Screen',
name: t('tools.device-information.screen'),
information: [
{
label: 'Screen size',
label: t('tools.device-information.screenSize'),
value: computed(() => `${window.screen.availWidth} x ${window.screen.availHeight}`),
},
{
label: 'Orientation',
label: t('tools.device-information.orientation'),
value: computed(() => window.screen.orientation.type),
},
{
label: 'Orientation angle',
label: t('tools.device-information.orientationAngle'),
value: computed(() => `${window.screen.orientation.angle}°`),
},
{
label: 'Color depth',
label: t('tools.device-information.colorDepth'),
value: computed(() => `${window.screen.colorDepth} bits`),
},
{
label: 'Pixel ratio',
label: t('tools.device-information.pixelRatio'),
value: computed(() => `${window.devicePixelRatio} dppx`),
},
{
label: 'Window size',
label: t('tools.device-information.windowSize'),
value: computed(() => `${width.value} x ${height.value}`),
},
],
},
{
name: 'Device',
name: t('tools.device-information.device'),
information: [
{
label: 'Browser vendor',
label: t('tools.device-information.browserVendor'),
value: computed(() => navigator.vendor),
},
{
label: 'Languages',
label: t('tools.device-information.languages'),
value: computed(() => navigator.languages.join(', ')),
},
{
label: 'Platform',
label: t('tools.device-information.platform'),
value: computed(() => navigator.platform),
},
{
label: 'User agent',
label: t('tools.device-information.userAgent'),
value: computed(() => navigator.userAgent),
},
],

View file

@ -1,11 +1,11 @@
import { DeviceDesktop } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.device-information.title'),
name: t('tools.device-information.title'),
path: '/device-information',
description: translate('tools.device-information.description'),
description: t('tools.device-information.description'),
keywords: [
'device',
'information',

View file

@ -0,0 +1,17 @@
tools:
device-information:
title: Device information
description: Get information about your current device (screen size, pixel-ratio, user agent, ...)
screen: Screen
screenSize: Screen size
orientation: Orientation
orientationAngle: Orientation angle
colorDepth: Color depth
pixelRatio: Pixel ratio
windowSize: Window size
device: Device
browserVendor: Browser vendor
languages: Languages
platform: Platform
userAgent: User agent

View file

@ -0,0 +1,17 @@
tools:
device-information:
title: 设备信息
description: 获取关于您当前设备的信息(屏幕大小、像素比、用户代理...
screen: 屏幕
screenSize: 屏幕尺寸
orientation: 方向
orientationAngle: 方向角度
colorDepth: 色彩深度
pixelRatio: 像素比
windowSize: 窗口大小
device: 设备
browserVendor: 浏览器供应商
languages: 语言
platform: 平台
userAgent: 用户代理

View file

@ -5,6 +5,7 @@ import { useDownloadFileFromBase64 } from '@/composable/downloadBase64';
import { textToBase64 } from '@/utils/base64';
import TextareaCopyable from '@/components/TextareaCopyable.vue';
const { t } = useI18n();
const dockerRun = ref(
'docker run -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro --restart always --log-opt max-size=1g nginx',
);
@ -32,12 +33,12 @@ const { download } = useDownloadFileFromBase64({ source: dockerComposeBase64, fi
<div>
<c-input-text
v-model:value="dockerRun"
label="Your docker run command:"
:label="t('tools.docker-run-to-docker-compose-converter.inputLabel')"
style="font-family: monospace"
multiline
raw-text
monospace
placeholder="Your docker run command to convert..."
:placeholder="t('tools.docker-run-to-docker-compose-converter.inputPlaceholder')"
rows="3"
/>
@ -47,12 +48,12 @@ const { download } = useDownloadFileFromBase64({ source: dockerComposeBase64, fi
<div mt-5 flex justify-center>
<c-button :disabled="dockerCompose === ''" secondary @click="download">
Download docker-compose.yml
{{ t('tools.docker-run-to-docker-compose-converter.downloadBtn') }}
</c-button>
</div>
<div v-if="notComposable.length > 0">
<n-alert title="This options are not translatable to docker-compose" type="info" mt-5>
<n-alert :title="t('tools.docker-run-to-docker-compose-converter.notComposable')" type="info" mt-5>
<ul>
<li v-for="(message, index) of notComposable" :key="index">
{{ message }}
@ -63,7 +64,7 @@ const { download } = useDownloadFileFromBase64({ source: dockerComposeBase64, fi
<div v-if="notImplemented.length > 0">
<n-alert
title="This options are not yet implemented and therefore haven't been translated to docker-compose"
:title="t('tools.docker-run-to-docker-compose-converter.notImplemented')"
type="warning"
mt-5
>
@ -76,7 +77,7 @@ const { download } = useDownloadFileFromBase64({ source: dockerComposeBase64, fi
</div>
<div v-if="errors.length > 0">
<n-alert title="The following errors occured" type="error" mt-5>
<n-alert :title="t('tools.docker-run-to-docker-compose-converter.errors')" type="error" mt-5>
<ul>
<li v-for="(message, index) of errors" :key="index">
{{ message }}

View file

@ -1,11 +1,11 @@
import { BrandDocker } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.docker-run-to-docker-compose-converter.title'),
name: t('tools.docker-run-to-docker-compose-converter.title'),
path: '/docker-run-to-docker-compose-converter',
description: translate('tools.docker-run-to-docker-compose-converter.description'),
description: t('tools.docker-run-to-docker-compose-converter.description'),
keywords: ['docker', 'run', 'compose', 'yaml', 'yml', 'convert', 'deamon'],
component: () => import('./docker-run-to-docker-compose-converter.vue'),
icon: BrandDocker,

View file

@ -0,0 +1,12 @@
tools:
docker-run-to-docker-compose-converter:
title: Docker run to Docker compose converter
description: Turns docker run commands into docker-compose files!
inputLabel: 'Your docker run command:'
inputPlaceholder: Your docker run command to convert...
downloadBtn: Download docker-compose.yml
notComposable: This options are not translatable to docker-compose
notImplemented: This options are not yet implemented and therefore haven't been translated to docker-compose
errors: The following errors occured

View file

@ -0,0 +1,12 @@
tools:
docker-run-to-docker-compose-converter:
title: Docker run 转换为 Docker compose 转换器
description: 将 docker run 命令转换为 docker-compose 文件!
inputLabel: '您的 docker run 命令:'
inputPlaceholder: 您要转换的 docker run 命令...
downloadBtn: 下载 docker-compose.yml
notComposable: 这些选项无法转换为 docker-compose
notImplemented: 这些选项尚未实现,因此尚未被翻译为 docker-compose
errors: 发生了以下错误

View file

@ -5,12 +5,13 @@ import { useCopy } from '@/composable/copy';
const props = (defineProps<{ emojiInfo: EmojiInfo }>());
const { emojiInfo } = toRefs(props);
const { t } = useI18n();
const { copy } = useCopy();
</script>
<template>
<c-card flex items-center gap-3 important:py-8px important:pl-10px important:pr-5px>
<div cursor-pointer text-30px @click="copy(emojiInfo.emoji, { notificationMessage: `Emoji ${emojiInfo.emoji} copied to the clipboard` })">
<div cursor-pointer text-30px @click="copy(emojiInfo.emoji, { notificationMessage: t('tools.emoji-picker.emojiCopied', { emoji: emojiInfo.emoji }) })">
{{ emojiInfo.emoji }}
</div>
@ -30,10 +31,10 @@ const { copy } = useCopy();
</div> -->
<div flex gap-2 text-xs font-mono op-70>
<span cursor-pointer transition hover:text-primary @click="copy(emojiInfo.codePoints, { notificationMessage: `Code points '${emojiInfo.codePoints}' copied to the clipboard` })">
<span cursor-pointer transition hover:text-primary @click="copy(emojiInfo.codePoints, { notificationMessage: t('tools.emoji-picker.codePointsCopied', { codePoints: emojiInfo.codePoints }) })">
{{ emojiInfo.codePoints }}
</span>
<span cursor-pointer truncate transition hover:text-primary @click="copy(emojiInfo.unicode, { notificationMessage: `Unicode '${emojiInfo.unicode}' copied to the clipboard` })">
<span cursor-pointer truncate transition hover:text-primary @click="copy(emojiInfo.unicode, { notificationMessage: t('tools.emoji-picker.unicodeCopied', { unicode: emojiInfo.unicode }) })">
{{ emojiInfo.unicode }}
</span>
</div>

View file

@ -5,6 +5,7 @@ import _ from 'lodash';
import type { EmojiInfo } from './emoji.types';
import { useFuzzySearch } from '@/composable/fuzzySearch';
const { t } = useI18n();
const escapeUnicode = ({ emoji }: { emoji: string }) => emoji.split('').map(unit => `\\u${unit.charCodeAt(0).toString(16).padStart(4, '0')}`).join('');
const getEmojiCodePoints = ({ emoji }: { emoji: string }) => emoji.codePointAt(0) ? `0x${emoji.codePointAt(0)?.toString(16)}` : undefined;
@ -42,7 +43,7 @@ const { searchResult } = useFuzzySearch({
<div flex items-center gap-3>
<c-input-text
v-model:value="searchQuery"
placeholder="Search emojis (e.g. 'smile')..."
:placeholder="t('tools.emoji-picker.searchPlaceholder')"
mx-auto max-w-600px
>
<template #prefix>
@ -58,12 +59,12 @@ const { searchResult } = useFuzzySearch({
text-20px
font-bold
>
No results
{{ t('tools.emoji-picker.noResults') }}
</div>
<div v-else>
<div mt-4 text-20px font-bold>
Search result
{{ t('tools.emoji-picker.searchResult') }}
</div>
<emoji-grid :emoji-infos="searchResult" />

View file

@ -1,11 +1,11 @@
import { MoodSmile } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.emoji-picker.title'),
name: t('tools.emoji-picker.title'),
path: '/emoji-picker',
description: translate('tools.emoji-picker.description'),
description: t('tools.emoji-picker.description'),
keywords: ['emoji', 'picker', 'unicode', 'copy', 'paste'],
component: () => import('./emoji-picker.vue'),
icon: MoodSmile,

View file

@ -0,0 +1,12 @@
tools:
emoji-picker:
title: Emoji picker
description: Copy and paste emojis easily and get the unicode and code points value of each emoji.
searchPlaceholder: Search emojis (e.g. "smile")...
noResults: No results
searchResult: Search result
emojiCopied: Emoji {emoji} copied to the clipboard
codePointsCopied: Code points {codePoints} copied to the clipboard
unicodeCopied: Unicode {unicode} copied to the clipboard

View file

@ -0,0 +1,12 @@
tools:
emoji-picker:
title: 表情选择器
description: 轻松复制和粘贴表情符号,并获取每个表情符号的 Unicode 和代码点值。
searchPlaceholder: 搜索表情符号例如“smile”...
noResults: 没有结果
searchResult: 搜索结果
emojiCopied: 表情符号 {emoji} 已复制到剪贴板
codePointsCopied: 代码点 {codePoints} 已复制到剪贴板
unicodeCopied: Unicode {unicode} 已复制到剪贴板

View file

@ -4,45 +4,47 @@ import { computedCatch } from '@/composable/computed/catchedComputed';
const algos = { AES, TripleDES, Rabbit, RC4 };
const { t } = useI18n();
const cypherInput = ref('Lorem ipsum dolor sit amet');
const cypherAlgo = ref<keyof typeof algos>('AES');
const cypherSecret = ref('my secret key');
const cypherOutput = computed(() => algos[cypherAlgo.value].encrypt(cypherInput.value, cypherSecret.value).toString());
const decryptInput = ref('U2FsdGVkX1/EC3+6P5dbbkZ3e1kQ5o2yzuU0NHTjmrKnLBEwreV489Kr0DIB+uBs');
const decryptInput = ref('U2FsdGVkX18oguRKlUyr7Po25uzcRyz1DVR6+3ULIoQ/gvlXJ+JT+uVJkz+WmSEZ');
const decryptAlgo = ref<keyof typeof algos>('AES');
const decryptSecret = ref('my secret key');
const [decryptOutput, decryptError] = computedCatch(() => algos[decryptAlgo.value].decrypt(decryptInput.value, decryptSecret.value).toString(enc.Utf8), {
defaultValue: '',
defaultErrorMessage: 'Unable to decrypt your text',
defaultErrorMessage: t('tools.encryption.errorMessage'),
});
</script>
<template>
<c-card title="Encrypt">
<c-card :title="t('tools.encryption.encrypt.title')">
<div flex gap-3>
<c-input-text
v-model:value="cypherInput"
label="Your text:"
placeholder="The string to cypher"
:label="t('tools.encryption.encrypt.inputLabel')"
:placeholder="t('tools.encryption.encrypt.inputPlaceholder')"
rows="4"
multiline raw-text monospace autosize flex-1
/>
<div flex flex-1 flex-col gap-2>
<c-input-text v-model:value="cypherSecret" label="Your secret key:" clearable raw-text />
<c-input-text v-model:value="cypherSecret" :label="t('tools.encryption.encrypt.secretLabel')" clearable raw-text />
<c-select
v-model:value="cypherAlgo"
label="Encryption algorithm:"
:label="t('tools.encryption.encrypt.algoLabel')"
:options="Object.keys(algos).map((label) => ({ label, value: label }))"
/>
</div>
</div>
<c-input-text
label="Your text encrypted:"
:label="t('tools.encryption.encrypt.outputLabel')"
:value="cypherOutput"
rows="3"
placeholder="Your string hash"
:placeholder="t('tools.encryption.encrypt.outputPlaceholder')"
multiline monospace readonly autosize mt-5
/>
</c-card>
@ -50,29 +52,29 @@ const [decryptOutput, decryptError] = computedCatch(() => algos[decryptAlgo.valu
<div flex gap-3>
<c-input-text
v-model:value="decryptInput"
label="Your encrypted text:"
placeholder="The string to cypher"
:label="t('tools.encryption.decrypt.inputLabel')"
:placeholder="t('tools.encryption.decrypt.inputPlaceholder')"
rows="4"
multiline raw-text monospace autosize flex-1
/>
<div flex flex-1 flex-col gap-2>
<c-input-text v-model:value="decryptSecret" label="Your secret key:" clearable raw-text />
<c-input-text v-model:value="decryptSecret" :label="t('tools.encryption.decrypt.secretLabel')" clearable raw-text />
<c-select
v-model:value="decryptAlgo"
label="Encryption algorithm:"
:label="t('tools.encryption.decrypt.algoLabel')"
:options="Object.keys(algos).map((label) => ({ label, value: label }))"
/>
</div>
</div>
<c-alert v-if="decryptError" type="error" mt-12 title="Error while decrypting">
<c-alert v-if="decryptError" type="error" mt-12 :title="t('tools.encryption.decrypt.decryptError')">
{{ decryptError }}
</c-alert>
<c-input-text
v-else
label="Your decrypted text:"
:label="t('tools.encryption.decrypt.outputLabel')"
:value="decryptOutput"
placeholder="Your string hash"
:placeholder="t('tools.encryption.decrypt.outputPlaceholder')"
rows="3"
multiline monospace readonly autosize mt-5
/>

View file

@ -1,11 +1,11 @@
import { Lock } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.encryption.title'),
name: t('tools.encryption.title'),
path: '/encryption',
description: translate('tools.encryption.description'),
description: t('tools.encryption.description'),
keywords: ['cypher', 'encipher', 'text', 'AES', 'TripleDES', 'Rabbit', 'RC4'],
component: () => import('./encryption.vue'),
icon: Lock,

View file

@ -0,0 +1,24 @@
tools:
encryption:
title: Encrypt / decrypt text
description: Encrypt and decrypt text clear text using crypto algorithm like AES, TripleDES, Rabbit or RC4.
encrypt:
title: Encrypt
inputLabel: 'Your text:'
inputPlaceholder: The string to cypher
secretLabel: 'Your secret key:'
algoLabel: 'Encryption algorithm:'
outputLabel: 'Your text encrypted:'
outputPlaceholder: Your string hash
decrypt:
title: Decrypt
inputLabel: 'Your encrypted text:'
inputPlaceholder: The string to cypher
secretLabel: 'Your secret key:'
algoLabel: 'Encryption algorithm:'
outputLabel: 'Your decrypted text:'
outputPlaceholder: Your string hash
decryptError: Error while decrypting
errorMessage: Unable to decrypt your text

View file

@ -0,0 +1,24 @@
tools:
encryption:
title: 加密/解密文本
description: 使用 AES、TripleDES、Rabbit 或 RC4 等加密算法对文本进行加密和解密。
encrypt:
title: 加密
inputLabel: '您的文本:'
inputPlaceholder: 要加密的字符串
secretLabel: '您的密钥:'
algoLabel: '加密算法:'
outputLabel: '加密后的文本:'
outputPlaceholder: 您的字符串哈希值
decrypt:
title: 解密
inputLabel: '您的加密文本:'
inputPlaceholder: 要解密的字符串
secretLabel: '您的密钥:'
algoLabel: '加密算法:'
outputLabel: '解密后的文本:'
outputPlaceholder: 您的字符串哈希值
decryptError: 解密时出错
errorMessage: 无法解密您的文本

View file

@ -1,6 +1,7 @@
import { formatDuration } from 'date-fns';
import type { Locale } from 'date-fns';
export function formatMsDuration(duration: number) {
export function formatMsDuration(duration: number, locale: Locale) {
const ms = Math.floor(duration % 1000);
const secs = Math.floor(((duration - ms) / 1000) % 60);
const mins = Math.floor((((duration - ms) / 1000 - secs) / 60) % 60);
@ -11,6 +12,6 @@ export function formatMsDuration(duration: number) {
hours: hrs,
minutes: mins,
seconds: secs,
}) + (ms > 0 ? ` ${ms} ms` : '')
}, { locale }) + (ms > 0 ? ` ${ms} ms` : '')
);
}

View file

@ -3,57 +3,58 @@
import { addMilliseconds, formatRelative } from 'date-fns';
import { enGB } from 'date-fns/locale';
import { enGB, zhCN } from 'date-fns/locale';
import { formatMsDuration } from './eta-calculator.service';
const { t, locale } = useI18n();
const unitCount = ref(3 * 62);
const unitPerTimeSpan = ref(3);
const timeSpan = ref(5);
const timeSpanUnitMultiplier = ref(60000);
const startedAt = ref(Date.now());
const localeLang = computed(() => locale.value === 'zh' ? zhCN : enGB);
const durationMs = computed(() => {
const timeSpanMs = timeSpan.value * timeSpanUnitMultiplier.value;
return unitCount.value / (unitPerTimeSpan.value / timeSpanMs);
});
const endAt = computed(() =>
formatRelative(addMilliseconds(startedAt.value, durationMs.value), Date.now(), { locale: enGB }),
formatRelative(addMilliseconds(startedAt.value, durationMs.value), Date.now(), { locale: localeLang.value }),
);
</script>
<template>
<div>
<div text-justify op-70>
With a concrete example, if you wash 5 plates in 3 minutes and you have 500 plates to wash, it will take you 5
hours to wash them all.
{{ t('tools.eta-calculator.tips') }}
</div>
<n-divider />
<div flex gap-2>
<n-form-item label="Amount of element to consume" flex-1>
<n-form-item :label="t('tools.eta-calculator.unitCount')" flex-1>
<n-input-number v-model:value="unitCount" :min="1" />
</n-form-item>
<n-form-item label="The consumption started at" flex-1>
<n-form-item :label="t('tools.eta-calculator.startedAt')" flex-1>
<n-date-picker v-model:value="startedAt" type="datetime" />
</n-form-item>
</div>
<p>Amount of unit consumed by time span</p>
<p>{{ t('tools.eta-calculator.unitPerTimeSpan') }}</p>
<div flex flex-col items-baseline gap-y-2 md:flex-row>
<n-input-number v-model:value="unitPerTimeSpan" :min="1" />
<div flex items-baseline gap-2>
<span ml-2>in</span>
<span ml-2>{{ t('tools.eta-calculator.in') }}</span>
<n-input-number v-model:value="timeSpan" min-w-130px :min="1" />
<c-select
v-model:value="timeSpanUnitMultiplier"
min-w-130px
:options="[
{ label: 'milliseconds', value: 1 },
{ label: 'seconds', value: 1000 },
{ label: 'minutes', value: 1000 * 60 },
{ label: 'hours', value: 1000 * 60 * 60 },
{ label: 'days', value: 1000 * 60 * 60 * 24 },
{ label: t('tools.eta-calculator.milliseconds'), value: 1 },
{ label: t('tools.eta-calculator.seconds'), value: 1000 },
{ label: t('tools.eta-calculator.minutes'), value: 1000 * 60 },
{ label: t('tools.eta-calculator.hours'), value: 1000 * 60 * 60 },
{ label: t('tools.eta-calculator.days'), value: 1000 * 60 * 60 * 24 },
]"
/>
</div>
@ -61,12 +62,12 @@ const endAt = computed(() =>
<n-divider />
<c-card mb-2>
<n-statistic label="Total duration">
{{ formatMsDuration(durationMs) }}
<n-statistic :label="t('tools.eta-calculator.totalDuration')">
{{ formatMsDuration(durationMs, localeLang) }}
</n-statistic>
</c-card>
<c-card>
<n-statistic label="It will end ">
<n-statistic :label="t('tools.eta-calculator.endAt')">
{{ endAt }}
</n-statistic>
</c-card>

View file

@ -1,11 +1,11 @@
import { Hourglass } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.eta-calculator.title'),
name: t('tools.eta-calculator.title'),
path: '/eta-calculator',
description: translate('tools.eta-calculator.description'),
description: t('tools.eta-calculator.description'),
keywords: ['eta', 'calculator', 'estimated', 'time', 'arrival', 'average'],
component: () => import('./eta-calculator.vue'),
icon: Hourglass,

View file

@ -0,0 +1,17 @@
tools:
eta-calculator:
title: ETA calculator
description: An ETA (Estimated Time of Arrival) calculator to know the approximate end time of a task, for example the moment of ending of a download.
tips: With a concrete example, if you wash 5 plates in 3 minutes and you have 500 plates to wash, it will take you 5 hours to wash them all.
unitCount: Amount of element to consume
startedAt: The consumption started at
unitPerTimeSpan: Amount of unit consumed by time span
in: in
milliseconds: milliseconds
seconds: seconds
minutes: minutes
hours: hours
days: days
totalDuration: Total duration
endAt: It will end

View file

@ -0,0 +1,17 @@
tools:
eta-calculator:
title: 预计到达时间计算器
description: 一个预计到达时间ETA计算器用于了解任务的大致结束时间例如下载结束的时间。
tips: 以一个具体的例子来说,如果你用 3 分钟洗 5 个盘子,而你有 500 个盘子要洗,那么你需要 5 个小时来洗完所有盘子。
unitCount: 要消耗的元素数量
startedAt: 消耗开始于
unitPerTimeSpan: 每个时间段消耗的单位数量
in:
milliseconds: 毫秒
seconds:
minutes: 分钟
hours: 小时
days:
totalDuration: 总持续时间
endAt: 它将在以下时间结束

View file

@ -0,0 +1,77 @@
## 配置
设置全局配置
```shell
git config --global user.name "[姓名]"
git config --global user.email "[邮箱]"
```
## 入门
创建一个 git 仓库
```shell
git init
```
克隆现有的 git 仓库
```shell
git clone [url]
```
## 提交
提交所有已跟踪的更改
```shell
git commit -am "[提交信息]"
```
将新修改添加到上次提交中
```shell
git commit --amend --no-edit
```
## 我犯了一个错误
更改上次提交的消息
```shell
git commit --amend
```
撤消最近的提交并保留更改
```shell
git reset HEAD~1
```
撤消最近的 `N` 个提交并保留更改
```shell
git reset HEAD~N
```
撤消最近的提交并放弃更改
```shell
git reset HEAD~1 --hard
```
将分支重置为远程状态
```shell
git fetch origin
git reset --hard origin/[分支名]
```
## 其他
将本地 master 分支重命名为 main
```shell
git branch -m master main
```

View file

@ -1,13 +1,16 @@
<script setup lang="ts">
import { useThemeVars } from 'naive-ui';
import Memo from './git-memo.content.md';
import MemoZH from './git-memo.content.zh.md';
const themeVars = useThemeVars();
const { locale } = useI18n();
</script>
<template>
<div>
<Memo />
<MemoZH v-if="locale === 'zh'" />
<Memo v-else />
</div>
</template>

View file

@ -1,11 +1,11 @@
import { BrandGit } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.git-memo.title'),
name: t('tools.git-memo.title'),
path: '/git-memo',
description: translate('tools.git-memo.description'),
description: t('tools.git-memo.description'),
keywords: ['git', 'push', 'force', 'pull', 'commit', 'amend', 'rebase', 'merge', 'reset', 'soft', 'hard', 'lease'],
component: () => import('./git-memo.vue'),
icon: BrandGit,

View file

@ -0,0 +1,4 @@
tools:
git-memo:
title: Git cheatsheet
description: Git is a decentralized version management software. With this cheatsheet you will have a quick access to the most common git commands.

View file

@ -0,0 +1,4 @@
tools:
git-memo:
title: Git 备忘录
description: Git 是一款分布式版本管理软件。使用这个备忘录,您将快速访问最常用的 Git 命令。

View file

@ -22,6 +22,7 @@ type Encoding = keyof typeof enc | 'Bin';
const algoNames = Object.keys(algos) as AlgoNames[];
const encoding = useQueryParam<Encoding>({ defaultValue: 'Hex', name: 'encoding' });
const clearText = ref('');
const { t } = useI18n();
function formatWithEncoding(words: lib.WordArray, encoding: Encoding) {
if (encoding === 'Bin') {
@ -37,29 +38,38 @@ const hashText = (algo: AlgoNames, value: string) => formatWithEncoding(algos[al
<template>
<div>
<c-card>
<c-input-text v-model:value="clearText" multiline raw-text placeholder="Your string to hash..." rows="3" autosize autofocus label="Your text to hash:" />
<c-input-text
v-model:value="clearText"
multiline
raw-text
:placeholder="t('tools.hash-text.textPlaceholder')"
rows="3"
autosize
autofocus
:label="t('tools.hash-text.textLabel')"
/>
<n-divider />
<c-select
v-model:value="encoding"
mb-4
label="Digest encoding"
:label="t('tools.hash-text.hashLabel')"
:options="[
{
label: 'Binary (base 2)',
label: t('tools.hash-text.binary'),
value: 'Bin',
},
{
label: 'Hexadecimal (base 16)',
label: t('tools.hash-text.hexadecimal'),
value: 'Hex',
},
{
label: 'Base64 (base 64)',
label: t('tools.hash-text.base64'),
value: 'Base64',
},
{
label: 'Base64url (base 64 with url safe chars)',
label: t('tools.hash-text.base64url'),
value: 'Base64url',
},
]"

View file

@ -1,11 +1,11 @@
import { EyeOff } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.hash-text.title'),
name: t('tools.hash-text.title'),
path: '/hash-text',
description: translate('tools.hash-text.description'),
description: t('tools.hash-text.description'),
keywords: [
'hash',
'digest',

View file

@ -0,0 +1,12 @@
tools:
hash-text:
title: Hash text
description: 'Hash a text string using the function you need : MD5, SHA1, SHA256, SHA224, SHA512, SHA384, SHA3 or RIPEMD160'
textLabel: 'Your text to hash:'
textPlaceholder: 'Your string to hash...'
hashLabel: Digest encoding
binary: Binary (base 2)
hexadecimal: Hexadecimal (base 16)
base64: Base64 (base 64)
base64url: Base64url (base 64 with url safe chars)

View file

@ -0,0 +1,12 @@
tools:
hash-text:
title: 文本转哈希
description: '使用所需的函数对文本字符串进行哈希计算MD5、SHA1、SHA256、SHA224、SHA512、SHA384、SHA3或RIPEMD160'
textLabel: '要进行哈希的文本:'
textPlaceholder: '要进行哈希的字符串...'
hashLabel: '摘要编码'
binary: '二进制基数2'
hexadecimal: '十六进制基数16'
base64: 'Base64基数64'
base64url: 'Base64url带有URL安全字符的基数64'

View file

@ -42,49 +42,50 @@ const encoding = ref<Encoding>('Hex');
const hmac = computed(() =>
formatWithEncoding(algos[hashFunction.value](plainText.value, secret.value), encoding.value),
);
const { t } = useI18n();
const { copy } = useCopy({ source: hmac });
</script>
<template>
<div flex flex-col gap-4>
<c-input-text v-model:value="plainText" multiline raw-text placeholder="Plain text to compute the hash..." rows="3" autosize autofocus label="Plain text to compute the hash" />
<c-input-text v-model:value="secret" raw-text placeholder="Enter the secret key..." label="Secret key" clearable />
<c-input-text v-model:value="plainText" multiline raw-text :placeholder="t('tools.hmac-generator.plainText.placeholder')" rows="3" autosize autofocus :label="t('tools.hmac-generator.plainText.label')" />
<c-input-text v-model:value="secret" raw-text :placeholder="t('tools.hmac-generator.secret.placeholder')" :label="t('tools.hmac-generator.secret.label')" clearable />
<div flex gap-2>
<c-select
v-model:value="hashFunction" label="Hashing function"
v-model:value="hashFunction" :label="t('tools.hmac-generator.hashFunction.label')"
flex-1
placeholder="Select an hashing function..."
:placeholder="t('tools.hmac-generator.hashFunction.placeholder')"
:options="Object.keys(algos).map((label) => ({ label, value: label }))"
/>
<c-select
v-model:value="encoding" label="Output encoding"
v-model:value="encoding" :label="t('tools.hmac-generator.encoding.label')"
flex-1
placeholder="Select the result encoding..."
:placeholder="t('tools.hmac-generator.encoding.placeholder')"
:options="[
{
label: 'Binary (base 2)',
label: t('tools.hmac-generator.encoding.binary'),
value: 'Bin',
},
{
label: 'Hexadecimal (base 16)',
label: t('tools.hmac-generator.encoding.hexadecimal'),
value: 'Hex',
},
{
label: 'Base64 (base 64)',
label: t('tools.hmac-generator.encoding.base64'),
value: 'Base64',
},
{
label: 'Base64-url (base 64 with url safe chars)',
label: t('tools.hmac-generator.encoding.Base64Url'),
value: 'Base64url',
},
]"
/>
</div>
<input-copyable v-model:value="hmac" type="textarea" placeholder="The result of the HMAC..." label="HMAC of your text" />
<input-copyable v-model:value="hmac" type="textarea" :placeholder="t('tools.hmac-generator.result.placeholder')" :label="t('tools.hmac-generator.result.label')" />
<div flex justify-center>
<c-button @click="copy()">
Copy HMAC
{{ t('tools.hmac-generator.button.copy') }}
</c-button>
</div>
</div>

View file

@ -1,11 +1,11 @@
import { ShortTextRound } from '@vicons/material';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.hmac-generator.title'),
name: t('tools.hmac-generator.title'),
path: '/hmac-generator',
description: translate('tools.hmac-generator.description'),
description: t('tools.hmac-generator.description'),
keywords: ['hmac', 'generator', 'MD5', 'SHA1', 'SHA256', 'SHA224', 'SHA512', 'SHA384', 'SHA3', 'RIPEMD160'],
component: () => import('./hmac-generator.vue'),
icon: ShortTextRound,

View file

@ -0,0 +1,26 @@
tools:
hmac-generator:
title: Hmac generator
description: Computes a hash-based message authentication code (HMAC) using a secret key and your favorite hashing function.
plainText:
label: Plain text to compute the hash
placeholder: Plain text to compute the hash...
secret:
label: Secret key
placeholder: Enter the secret key...
hashFunction:
label: Hashing function
placeholder: Select an hashing function...
encoding:
label: Output encoding
placeholder: Select the result encoding...
binary: Binary (base 2)
hexadecimal: Hexadecimal (base 16)
base64: Base64 (base 64)
Base64Url: Base64-url (base 64 with url safe chars)
result:
label: HMAC of your text
placeholder: The result of the HMAC...
button:
copy: Copy HMAC

View file

@ -0,0 +1,26 @@
tools:
hmac-generator:
title: HMAC 生成器
description: 使用密钥和您喜欢的哈希函数计算基于哈希的消息认证码HMAC
plainText:
label: 要计算哈希的明文
placeholder: 要计算哈希的明文...
secret:
label: 密钥
placeholder: 输入密钥...
hashFunction:
label: 哈希函数
placeholder: 选择一个哈希函数...
encoding:
label: 输出编码
placeholder: 选择结果的编码方式...
binary: 二进制基数2
hexadecimal: 十六进制基数16
base64: Base64基数64
Base64Url: Base64-url带有URL安全字符的基数64
result:
label: 您的文本的 HMAC
placeholder: HMAC 的结果...
button:
copy: 复制 HMAC

View file

@ -3,6 +3,7 @@ import { escape, unescape } from 'lodash';
import { useCopy } from '@/composable/copy';
const { t } = useI18n();
const escapeInput = ref('<title>IT Tool</title>');
const escapeOutput = computed(() => escape(escapeInput.value));
const { copy: copyEscaped } = useCopy({ source: escapeOutput });
@ -13,23 +14,23 @@ const { copy: copyUnescaped } = useCopy({ source: unescapeOutput });
</script>
<template>
<c-card title="Escape html entities">
<n-form-item label="Your string :">
<c-card :title="t('tools.html-entities.escape.title')">
<n-form-item :label="t('tools.html-entities.escape.inputLabel')">
<c-input-text
v-model:value="escapeInput"
multiline
placeholder="The string to escape"
:placeholder="t('tools.html-entities.escape.inputPlaceholder')"
rows="3"
autosize
raw-text
/>
</n-form-item>
<n-form-item label="Your string escaped :">
<n-form-item :label="t('tools.html-entities.escape.outputLabel')">
<c-input-text
multiline
readonly
placeholder="Your string escaped"
:placeholder="t('tools.html-entities.escape.outputPlaceholder')"
:value="escapeOutput"
rows="3"
autosize
@ -38,28 +39,28 @@ const { copy: copyUnescaped } = useCopy({ source: unescapeOutput });
<div flex justify-center>
<c-button @click="copyEscaped()">
Copy
{{ t('tools.html-entities.copy') }}
</c-button>
</div>
</c-card>
<c-card title="Unescape html entities">
<n-form-item label="Your escaped string :">
<c-card :title="t('tools.html-entities.unescape.title')">
<n-form-item :label="t('tools.html-entities.unescape.inputLabel')">
<c-input-text
v-model:value="unescapeInput"
multiline
placeholder="The string to unescape"
:placeholder="t('tools.html-entities.unescape.inputPlaceholder')"
rows="3"
autosize
raw-text
/>
</n-form-item>
<n-form-item label="Your string unescaped :">
<n-form-item :label="t('tools.html-entities.unescape.outputLabel')">
<c-input-text
:value="unescapeOutput"
multiline
readonly
placeholder="Your string unescaped"
:placeholder="t('tools.html-entities.unescape.outputPlaceholder')"
rows="3"
autosize
/>
@ -67,7 +68,7 @@ const { copy: copyUnescaped } = useCopy({ source: unescapeOutput });
<div flex justify-center>
<c-button @click="copyUnescaped()">
Copy
{{ t('tools.html-entities.copy') }}
</c-button>
</div>
</c-card>

View file

@ -1,11 +1,11 @@
import { Code } from '@vicons/tabler';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.html-entities.title'),
name: t('tools.html-entities.title'),
path: '/html-entities',
description: translate('tools.html-entities.description'),
description: t('tools.html-entities.description'),
keywords: ['html', 'entities', 'escape', 'unescape', 'special', 'characters', 'tags'],
component: () => import('./html-entities.vue'),
icon: Code,

View file

@ -0,0 +1,19 @@
tools:
html-entities:
title: Escape html entities
description: Escape or unescape html entities (replace <,>, &, " and ' to their html version)
escape:
title: Escape html entities
inputLabel: 'Your string :'
inputPlaceholder: The string to escape
outputLabel: 'Your string escaped :'
outputPlaceholder: Your string escaped
unescape:
title: Unescape html entities
inputLabel: 'Your escaped string :'
inputPlaceholder: The string to unescape
outputLabel: 'Your string unescaped :'
outputPlaceholder: Your string unescaped
copy: Copy

View file

@ -0,0 +1,19 @@
tools:
html-entities:
title: 转义 HTML 实体
description: 转义或取消转义 HTML 实体(将 <,>, &, " 和 ' 替换为它们的 HTML 版本)
escape:
title: 转义 HTML 实体
inputLabel: '输入字符串:'
inputPlaceholder: 要转义的字符串
outputLabel: '转义后的字符串:'
outputPlaceholder: 转义后的字符串
unescape:
title: 取消转义 HTML 实体
inputLabel: '输入转义后的字符串:'
inputPlaceholder: 要取消转义的字符串
outputLabel: '取消转义后的字符串:'
outputPlaceholder: 取消转义后的字符串
copy: 复制

Some files were not shown because too many files have changed in this diff Show more