diff --git a/src/tools/hash-text/locales/zh.yml b/src/tools/hash-text/locales/zh.yml
index 66363a71..9dcc9c4f 100644
--- a/src/tools/hash-text/locales/zh.yml
+++ b/src/tools/hash-text/locales/zh.yml
@@ -1,12 +1,12 @@
tools:
hash-text:
title: 文本转哈希
- description: 使用所需的函数对文本字符串进行哈希计算:MD5、SHA1、SHA256、SHA224、SHA512、SHA384、SHA3或RIPEMD160
+ description: '使用所需的函数对文本字符串进行哈希计算:MD5、SHA1、SHA256、SHA224、SHA512、SHA384、SHA3或RIPEMD160'
textLabel: '要进行哈希的文本:'
textPlaceholder: '要进行哈希的字符串...'
- hashLabel: 摘要编码
- binary: 二进制(基数2)
- hexadecimal: 十六进制(基数16)
- base64: Base64(基数64)
- base64url: Base64url(带有URL安全字符的基数64)
+ hashLabel: '摘要编码'
+ binary: '二进制(基数2)'
+ hexadecimal: '十六进制(基数16)'
+ base64: 'Base64(基数64)'
+ base64url: 'Base64url(带有URL安全字符的基数64)'
diff --git a/src/tools/html-entities/locales/en.yml b/src/tools/html-entities/locales/en.yml
index b37b45cd..aaaf0ea4 100644
--- a/src/tools/html-entities/locales/en.yml
+++ b/src/tools/html-entities/locales/en.yml
@@ -1,7 +1,7 @@
tools:
html-entities:
title: Escape html entities
- description: Escape or unescape html entities (replace <,>, &, " and \' to their html version)
+ description: Escape or unescape html entities (replace <,>, &, " and ' to their html version)
escape:
title: Escape html entities
diff --git a/src/tools/html-entities/locales/zh.yml b/src/tools/html-entities/locales/zh.yml
index 35b8062e..4288d852 100644
--- a/src/tools/html-entities/locales/zh.yml
+++ b/src/tools/html-entities/locales/zh.yml
@@ -1,7 +1,7 @@
tools:
html-entities:
title: 转义 HTML 实体
- description: 转义或取消转义 HTML 实体(将 <,>, &, " 和 \' 替换为它们的 HTML 版本)
+ description: 转义或取消转义 HTML 实体(将 <,>, &, " 和 ' 替换为它们的 HTML 版本)
escape:
title: 转义 HTML 实体
diff --git a/src/tools/html-wysiwyg-editor/editor/menu-bar.vue b/src/tools/html-wysiwyg-editor/editor/menu-bar.vue
index d3ad3168..cc3079c6 100644
--- a/src/tools/html-wysiwyg-editor/editor/menu-bar.vue
+++ b/src/tools/html-wysiwyg-editor/editor/menu-bar.vue
@@ -20,6 +20,7 @@ import {
} from '@vicons/tabler';
import type { Component } from 'vue';
import MenuBarItem from './menu-bar-item.vue';
+import { translate as t } from '@/plugins/i18n.plugin';
const props = defineProps<{ editor: Editor }>();
const { editor } = toRefs(props);
@@ -38,28 +39,28 @@ const items: MenuItem[] = [
{
type: 'button',
icon: Bold,
- title: 'Bold',
+ title: t('tools.html-wysiwyg-editor.bold'),
action: () => editor.value.chain().focus().toggleBold().run(),
isActive: () => editor.value.isActive('bold'),
},
{
type: 'button',
icon: Italic,
- title: 'Italic',
+ title: t('tools.html-wysiwyg-editor.italic'),
action: () => editor.value.chain().focus().toggleItalic().run(),
isActive: () => editor.value.isActive('italic'),
},
{
type: 'button',
icon: Strikethrough,
- title: 'Strike',
+ title: t('tools.html-wysiwyg-editor.strike'),
action: () => editor.value.chain().focus().toggleStrike().run(),
isActive: () => editor.value.isActive('strike'),
},
{
type: 'button',
icon: Code,
- title: 'Inline code',
+ title: t('tools.html-wysiwyg-editor.inlineCode'),
action: () => editor.value.chain().focus().toggleCode().run(),
isActive: () => editor.value.isActive('code'),
},
@@ -69,28 +70,28 @@ const items: MenuItem[] = [
{
type: 'button',
icon: H1,
- title: 'Heading 1',
+ title: t('tools.html-wysiwyg-editor.heading1'),
action: () => editor.value.chain().focus().toggleHeading({ level: 1 }).run(),
isActive: () => editor.value.isActive('heading', { level: 1 }),
},
{
type: 'button',
icon: H2,
- title: 'Heading 2',
+ title: t('tools.html-wysiwyg-editor.heading2'),
action: () => editor.value.chain().focus().toggleHeading({ level: 2 }).run(),
isActive: () => editor.value.isActive('heading', { level: 2 }),
},
{
type: 'button',
icon: H3,
- title: 'Heading 3',
+ title: t('tools.html-wysiwyg-editor.heading3'),
action: () => editor.value.chain().focus().toggleHeading({ level: 4 }).run(),
isActive: () => editor.value.isActive('heading', { level: 4 }),
},
{
type: 'button',
icon: H4,
- title: 'Heading 4',
+ title: t('tools.html-wysiwyg-editor.heading4'),
action: () => editor.value.chain().focus().toggleHeading({ level: 4 }).run(),
isActive: () => editor.value.isActive('heading', { level: 4 }),
},
@@ -100,21 +101,21 @@ const items: MenuItem[] = [
{
type: 'button',
icon: List,
- title: 'Bullet list',
+ title: t('tools.html-wysiwyg-editor.bulletList'),
action: () => editor.value.chain().focus().toggleBulletList().run(),
isActive: () => editor.value.isActive('bulletList'),
},
{
type: 'button',
icon: ListNumbers,
- title: 'Ordered list',
+ title: t('tools.html-wysiwyg-editor.orderedList'),
action: () => editor.value.chain().focus().toggleOrderedList().run(),
isActive: () => editor.value.isActive('orderedList'),
},
{
type: 'button',
icon: CodePlus,
- title: 'Code block',
+ title: t('tools.html-wysiwyg-editor.codeBlock'),
action: () => editor.value.chain().focus().toggleCodeBlock().run(),
isActive: () => editor.value.isActive('codeBlock'),
},
@@ -122,7 +123,7 @@ const items: MenuItem[] = [
{
type: 'button',
icon: Blockquote,
- title: 'Blockquote',
+ title: t('tools.html-wysiwyg-editor.blockquote'),
action: () => editor.value.chain().focus().toggleBlockquote().run(),
isActive: () => editor.value.isActive('blockquote'),
},
@@ -132,26 +133,26 @@ const items: MenuItem[] = [
{
type: 'button',
icon: TextWrap,
- title: 'Hard break',
+ title: t('tools.html-wysiwyg-editor.hardBreak'),
action: () => editor.value.chain().focus().setHardBreak().run(),
},
{
type: 'button',
icon: ClearFormatting,
- title: 'Clear format',
+ title: t('tools.html-wysiwyg-editor.clearFormat'),
action: () => editor.value.chain().focus().clearNodes().unsetAllMarks().run(),
},
{
type: 'button',
icon: ArrowBack,
- title: 'Undo',
+ title: t('tools.html-wysiwyg-editor.undo'),
action: () => editor.value.chain().focus().undo().run(),
},
{
type: 'button',
icon: ArrowForwardUp,
- title: 'Redo',
+ title: t('tools.html-wysiwyg-editor.redo'),
action: () => editor.value.chain().focus().redo().run(),
},
];
diff --git a/src/tools/html-wysiwyg-editor/index.ts b/src/tools/html-wysiwyg-editor/index.ts
index 461ad235..971be977 100644
--- a/src/tools/html-wysiwyg-editor/index.ts
+++ b/src/tools/html-wysiwyg-editor/index.ts
@@ -1,10 +1,11 @@
import { Edit } from '@vicons/tabler';
import { defineTool } from '../tool';
+import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
- name: 'HTML WYSIWYG editor',
+ name: t('tools.html-wysiwyg-editor.title'),
path: '/html-wysiwyg-editor',
- description: 'Online HTML editor with feature-rich WYSIWYG editor, get the source code of the content immediately.',
+ description: t('tools.html-wysiwyg-editor.description'),
keywords: ['html', 'wysiwyg', 'editor', 'p', 'ul', 'ol', 'converter', 'live'],
component: () => import('./html-wysiwyg-editor.vue'),
icon: Edit,
diff --git a/src/tools/html-wysiwyg-editor/locales/en.yml b/src/tools/html-wysiwyg-editor/locales/en.yml
index 03e5e503..f05d4cf3 100644
--- a/src/tools/html-wysiwyg-editor/locales/en.yml
+++ b/src/tools/html-wysiwyg-editor/locales/en.yml
@@ -2,3 +2,20 @@ tools:
html-wysiwyg-editor:
title: HTML WYSIWYG editor
description: Online HTML editor with feature-rich WYSIWYG editor, get the source code of the content immediately.
+
+ bold: Bold
+ italic: Italic
+ strike: Strike
+ inlineCode: Inline code
+ heading1: Heading 1
+ heading2: Heading 2
+ heading3: Heading 3
+ heading4: Heading 4
+ bulletList: Bullet list
+ orderedList: Ordered list
+ codeBlock: Code block
+ blockquote: Blockquote
+ hardBreak: Hard break
+ clearFormat: Clear format
+ undo: Undo
+ redo: Redo
diff --git a/src/tools/html-wysiwyg-editor/locales/zh.yml b/src/tools/html-wysiwyg-editor/locales/zh.yml
new file mode 100644
index 00000000..d0e983d0
--- /dev/null
+++ b/src/tools/html-wysiwyg-editor/locales/zh.yml
@@ -0,0 +1,21 @@
+tools:
+ html-wysiwyg-editor:
+ title: HTML所见即所得编辑器
+ description: 在线 HTML 编辑器,具有功能丰富的所见即所得编辑器,可立即获取内容的源代码。
+
+ bold: 粗体
+ italic: 斜体
+ strike: 删除线
+ inlineCode: 行内代码
+ heading1: 标题 1
+ heading2: 标题 2
+ heading3: 标题 3
+ heading4: 标题 4
+ bulletList: 无序列表
+ orderedList: 有序列表
+ codeBlock: 代码块
+ blockquote: 引用块
+ hardBreak: 强制换行
+ clearFormat: 清除格式
+ undo: 撤销
+ redo: 重做
diff --git a/src/tools/http-status-codes/http-status-codes.constants.ts b/src/tools/http-status-codes/http-status-codes.constants.ts
index 279cd7ce..49268b05 100644
--- a/src/tools/http-status-codes/http-status-codes.constants.ts
+++ b/src/tools/http-status-codes/http-status-codes.constants.ts
@@ -1,3 +1,5 @@
+import { translate as t } from '@/plugins/i18n.plugin';
+
export const codesByCategories: {
category: string
codes: {
@@ -8,423 +10,404 @@ export const codesByCategories: {
}[]
}[] = [
{
- category: '1xx informational response',
+ category: t('tools.http-status-codes.1xx'),
codes: [
{
code: 100,
- name: 'Continue',
- description: 'Waiting for the client to emit the body of the request.',
+ name: t('tools.http-status-codes.100.name'),
+ description: t('tools.http-status-codes.100.description'),
type: 'HTTP',
},
{
code: 101,
- name: 'Switching Protocols',
- description: 'The server has agreed to change protocol.',
+ name: t('tools.http-status-codes.101.name'),
+ description: t('tools.http-status-codes.101.description'),
type: 'HTTP',
},
{
code: 102,
- name: 'Processing',
- description: 'The server is processing the request, but no response is available yet.',
+ name: t('tools.http-status-codes.102.name'),
+ description: t('tools.http-status-codes.102.description'),
type: 'WebDav',
},
{
code: 103,
- name: 'Early Hints',
- description: 'The server returns some response headers before final HTTP message.',
+ name: t('tools.http-status-codes.103.name'),
+ description: t('tools.http-status-codes.103.description'),
type: 'HTTP',
},
],
},
{
- category: '2xx success',
+ category: t('tools.http-status-codes.2xx'),
codes: [
{
code: 200,
- name: 'OK',
- description: 'Standard response for successful HTTP requests.',
+ name: t('tools.http-status-codes.200.name'),
+ description: t('tools.http-status-codes.200.description'),
type: 'HTTP',
},
{
code: 201,
- name: 'Created',
- description: 'The request has been fulfilled, resulting in the creation of a new resource.',
+ name: t('tools.http-status-codes.201.name'),
+ description: t('tools.http-status-codes.201.description'),
type: 'HTTP',
},
{
code: 202,
- name: 'Accepted',
- description: 'The request has been accepted for processing, but the processing has not been completed.',
+ name: t('tools.http-status-codes.202.name'),
+ description: t('tools.http-status-codes.202.description'),
type: 'HTTP',
},
{
code: 203,
- name: 'Non-Authoritative Information',
- description:
- 'The request is successful but the content of the original request has been modified by a transforming proxy.',
+ name: t('tools.http-status-codes.203.name'),
+ description: t('tools.http-status-codes.203.description'),
type: 'HTTP',
},
{
code: 204,
- name: 'No Content',
- description: 'The server successfully processed the request and is not returning any content.',
+ name: t('tools.http-status-codes.204.name'),
+ description: t('tools.http-status-codes.204.description'),
type: 'HTTP',
},
{
code: 205,
- name: 'Reset Content',
- description: 'The server indicates to reinitialize the document view which sent this request.',
+ name: t('tools.http-status-codes.205.name'),
+ description: t('tools.http-status-codes.205.description'),
type: 'HTTP',
},
{
code: 206,
- name: 'Partial Content',
- description: 'The server is delivering only part of the resource due to a range header sent by the client.',
+ name: t('tools.http-status-codes.206.name'),
+ description: t('tools.http-status-codes.206.description'),
type: 'HTTP',
},
{
code: 207,
- name: 'Multi-Status',
- description:
- 'The message body that follows is an XML message and can contain a number of separate response codes.',
+ name: t('tools.http-status-codes.207.name'),
+ description: t('tools.http-status-codes.207.description'),
type: 'WebDav',
},
{
code: 208,
- name: 'Already Reported',
- description:
- 'The members of a DAV binding have already been enumerated in a preceding part of the (multistatus) response.',
+ name: t('tools.http-status-codes.208.name'),
+ description: t('tools.http-status-codes.208.description'),
type: 'WebDav',
},
{
code: 226,
- name: 'IM Used',
- description:
- 'The server has fulfilled a request for the resource, and the response is a representation of the result.',
+ name: t('tools.http-status-codes.226.name'),
+ description: t('tools.http-status-codes.226.description'),
type: 'HTTP',
},
],
},
{
- category: '3xx redirection',
+ category: t('tools.http-status-codes.3xx'),
codes: [
{
code: 300,
- name: 'Multiple Choices',
- description: 'Indicates multiple options for the resource that the client may follow.',
+ name: t('tools.http-status-codes.300.name'),
+ description: t('tools.http-status-codes.300.description'),
type: 'HTTP',
},
{
code: 301,
- name: 'Moved Permanently',
- description: 'This and all future requests should be directed to the given URI.',
+ name: t('tools.http-status-codes.301.name'),
+ description: t('tools.http-status-codes.301.description'),
type: 'HTTP',
},
{
code: 302,
- name: 'Found',
- description: 'Redirect to another URL. This is an example of industry practice contradicting the standard.',
+ name: t('tools.http-status-codes.302.name'),
+ description: t('tools.http-status-codes.302.description'),
type: 'HTTP',
},
{
code: 303,
- name: 'See Other',
- description: 'The response to the request can be found under another URI using a GET method.',
+ name: t('tools.http-status-codes.303.name'),
+ description: t('tools.http-status-codes.303.description'),
type: 'HTTP',
},
{
code: 304,
- name: 'Not Modified',
- description:
- 'Indicates that the resource has not been modified since the version specified by the request headers.',
+ name: t('tools.http-status-codes.304.name'),
+ description: t('tools.http-status-codes.304.description'),
type: 'HTTP',
},
{
code: 305,
- name: 'Use Proxy',
- description:
- 'The requested resource is available only through a proxy, the address for which is provided in the response.',
+ name: t('tools.http-status-codes.305.name'),
+ description: t('tools.http-status-codes.305.description'),
type: 'HTTP',
},
{
code: 306,
- name: 'Switch Proxy',
- description: 'No longer used. Originally meant "Subsequent requests should use the specified proxy."',
+ name: t('tools.http-status-codes.306.name'),
+ description: t('tools.http-status-codes.306.description'),
type: 'HTTP',
},
{
code: 307,
- name: 'Temporary Redirect',
- description:
- 'In this case, the request should be repeated with another URI; however, future requests should still use the original URI.',
+ name: t('tools.http-status-codes.307.name'),
+ description: t('tools.http-status-codes.307.description'),
type: 'HTTP',
},
{
code: 308,
- name: 'Permanent Redirect',
- description: 'The request and all future requests should be repeated using another URI.',
+ name: t('tools.http-status-codes.308.name'),
+ description: t('tools.http-status-codes.308.description'),
type: 'HTTP',
},
],
},
{
- category: '4xx client error',
+ category: t('tools.http-status-codes.4xx'),
codes: [
{
code: 400,
- name: 'Bad Request',
- description: 'The server cannot or will not process the request due to an apparent client error.',
+ name: t('tools.http-status-codes.400.name'),
+ description: t('tools.http-status-codes.400.description'),
type: 'HTTP',
},
{
code: 401,
- name: 'Unauthorized',
- description:
- 'Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided.',
+ name: t('tools.http-status-codes.401.name'),
+ description: t('tools.http-status-codes.401.description'),
type: 'HTTP',
},
{
code: 402,
- name: 'Payment Required',
- description:
- 'Reserved for future use. The original intention was that this code might be used as part of some form of digital cash or micropayment scheme.',
+ name: t('tools.http-status-codes.402.name'),
+ description: t('tools.http-status-codes.402.description'),
type: 'HTTP',
},
{
code: 403,
- name: 'Forbidden',
- description:
- 'The request was valid, but the server is refusing action. The user might not have the necessary permissions for a resource.',
+ name: t('tools.http-status-codes.403.name'),
+ description: t('tools.http-status-codes.403.description'),
type: 'HTTP',
},
{
code: 404,
- name: 'Not Found',
- description: 'The requested resource could not be found but may be available in the future.',
+ name: t('tools.http-status-codes.404.name'),
+ description: t('tools.http-status-codes.404.description'),
type: 'HTTP',
},
{
code: 405,
- name: 'Method Not Allowed',
- description: 'A request method is not supported for the requested resource.',
+ name: t('tools.http-status-codes.405.name'),
+ description: t('tools.http-status-codes.405.description'),
type: 'HTTP',
},
{
code: 406,
- name: 'Not Acceptable',
- description:
- 'The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request.',
+ name: t('tools.http-status-codes.406.name'),
+ description: t('tools.http-status-codes.406.description'),
type: 'HTTP',
},
{
code: 407,
- name: 'Proxy Authentication Required',
- description: 'The client must first authenticate itself with the proxy.',
+ name: t('tools.http-status-codes.407.name'),
+ description: t('tools.http-status-codes.407.description'),
type: 'HTTP',
},
{
code: 408,
- name: 'Request Timeout',
- description: 'The server timed out waiting for the request.',
+ name: t('tools.http-status-codes.408.name'),
+ description: t('tools.http-status-codes.408.description'),
type: 'HTTP',
},
{
code: 409,
- name: 'Conflict',
- description:
- 'Indicates that the request could not be processed because of conflict in the request, such as an edit conflict.',
+ name: t('tools.http-status-codes.409.name'),
+ description: t('tools.http-status-codes.409.description'),
type: 'HTTP',
},
{
code: 410,
- name: 'Gone',
- description: 'Indicates that the resource requested is no longer available and will not be available again.',
+ name: t('tools.http-status-codes.410.name'),
+ description: t('tools.http-status-codes.410.description'),
type: 'HTTP',
},
{
code: 411,
- name: 'Length Required',
- description:
- 'The request did not specify the length of its content, which is required by the requested resource.',
+ name: t('tools.http-status-codes.411.name'),
+ description: t('tools.http-status-codes.411.description'),
type: 'HTTP',
},
{
code: 412,
- name: 'Precondition Failed',
- description: 'The server does not meet one of the preconditions that the requester put on the request.',
+ name: t('tools.http-status-codes.412.name'),
+ description: t('tools.http-status-codes.412.description'),
type: 'HTTP',
},
{
code: 413,
- name: 'Payload Too Large',
- description: 'The request is larger than the server is willing or able to process.',
+ name: t('tools.http-status-codes.413.name'),
+ description: t('tools.http-status-codes.413.description'),
type: 'HTTP',
},
{
code: 414,
- name: 'URI Too Long',
- description: 'The URI provided was too long for the server to process.',
+ name: t('tools.http-status-codes.414.name'),
+ description: t('tools.http-status-codes.414.description'),
type: 'HTTP',
},
{
code: 415,
- name: 'Unsupported Media Type',
- description: 'The request entity has a media type which the server or resource does not support.',
+ name: t('tools.http-status-codes.415.name'),
+ description: t('tools.http-status-codes.415.description'),
type: 'HTTP',
},
{
code: 416,
- name: 'Range Not Satisfiable',
- description: 'The client has asked for a portion of the file, but the server cannot supply that portion.',
+ name: t('tools.http-status-codes.416.name'),
+ description: t('tools.http-status-codes.416.description'),
type: 'HTTP',
},
{
code: 417,
- name: 'Expectation Failed',
- description: 'The server cannot meet the requirements of the Expect request-header field.',
+ name: t('tools.http-status-codes.417.name'),
+ description: t('tools.http-status-codes.417.description'),
type: 'HTTP',
},
{
code: 418,
- name: 'I\'m a teapot',
- description: 'The server refuses the attempt to brew coffee with a teapot.',
+ name: t('tools.http-status-codes.418.name'),
+ description: t('tools.http-status-codes.418.description'),
type: 'HTTP',
},
{
code: 421,
- name: 'Misdirected Request',
- description: 'The request was directed at a server that is not able to produce a response.',
+ name: t('tools.http-status-codes.421.name'),
+ description: t('tools.http-status-codes.421.description'),
type: 'HTTP',
},
{
code: 422,
- name: 'Unprocessable Entity',
- description: 'The request was well-formed but was unable to be followed due to semantic errors.',
+ name: t('tools.http-status-codes.422.name'),
+ description: t('tools.http-status-codes.422.description'),
type: 'HTTP',
},
{
code: 423,
- name: 'Locked',
- description: 'The resource that is being accessed is locked.',
+ name: t('tools.http-status-codes.423.name'),
+ description: t('tools.http-status-codes.423.description'),
type: 'HTTP',
},
{
code: 424,
- name: 'Failed Dependency',
- description: 'The request failed due to failure of a previous request.',
+ name: t('tools.http-status-codes.424.name'),
+ description: t('tools.http-status-codes.424.description'),
type: 'HTTP',
},
{
code: 425,
- name: 'Too Early',
- description: 'Indicates that the server is unwilling to risk processing a request that might be replayed.',
+ name: t('tools.http-status-codes.425.name'),
+ description: t('tools.http-status-codes.425.description'),
type: 'HTTP',
},
{
code: 426,
- name: 'Upgrade Required',
- description: 'The client should switch to a different protocol such as TLS/1.0.',
+ name: t('tools.http-status-codes.426.name'),
+ description: t('tools.http-status-codes.426.description'),
type: 'HTTP',
},
{
code: 428,
- name: 'Precondition Required',
- description: 'The origin server requires the request to be conditional.',
+ name: t('tools.http-status-codes.428.name'),
+ description: t('tools.http-status-codes.428.description'),
type: 'HTTP',
},
{
code: 429,
- name: 'Too Many Requests',
- description: 'The user has sent too many requests in a given amount of time.',
+ name: t('tools.http-status-codes.429.name'),
+ description: t('tools.http-status-codes.429.description'),
type: 'HTTP',
},
{
code: 431,
- name: 'Request Header Fields Too Large',
- description:
- 'The server is unwilling to process the request because either an individual header field, or all the header fields collectively, are too large.',
+ name: t('tools.http-status-codes.431.name'),
+ description: t('tools.http-status-codes.431.description'),
type: 'HTTP',
},
{
code: 451,
- name: 'Unavailable For Legal Reasons',
- description:
- 'A server operator has received a legal demand to deny access to a resource or to a set of resources that includes the requested resource.',
+ name: t('tools.http-status-codes.451.name'),
+ description: t('tools.http-status-codes.451.description'),
type: 'HTTP',
},
],
},
{
- category: '5xx server error',
+ category: t('tools.http-status-codes.5xx'),
codes: [
{
code: 500,
- name: 'Internal Server Error',
- description:
- 'A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.',
+ name: t('tools.http-status-codes.500.name'),
+ description: t('tools.http-status-codes.500.description'),
type: 'HTTP',
},
{
code: 501,
- name: 'Not Implemented',
- description:
- 'The server either does not recognize the request method, or it lacks the ability to fulfill the request.',
+ name: t('tools.http-status-codes.501.name'),
+ description: t('tools.http-status-codes.501.description'),
type: 'HTTP',
},
{
code: 502,
- name: 'Bad Gateway',
- description:
- 'The server was acting as a gateway or proxy and received an invalid response from the upstream server.',
+ name: t('tools.http-status-codes.502.name'),
+ description: t('tools.http-status-codes.502.description'),
type: 'HTTP',
},
{
code: 503,
- name: 'Service Unavailable',
- description: 'The server is currently unavailable (because it is overloaded or down for maintenance).',
+ name: t('tools.http-status-codes.503.name'),
+ description: t('tools.http-status-codes.503.description'),
type: 'HTTP',
},
{
code: 504,
- name: 'Gateway Timeout',
- description:
- 'The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.',
+ name: t('tools.http-status-codes.504.name'),
+ description: t('tools.http-status-codes.504.description'),
type: 'HTTP',
},
{
code: 505,
- name: 'HTTP Version Not Supported',
- description: 'The server does not support the HTTP protocol version used in the request.',
+ name: t('tools.http-status-codes.505.name'),
+ description: t('tools.http-status-codes.505.description'),
type: 'HTTP',
},
{
code: 506,
- name: 'Variant Also Negotiates',
- description: 'Transparent content negotiation for the request results in a circular reference.',
+ name: t('tools.http-status-codes.506.name'),
+ description: t('tools.http-status-codes.506.description'),
type: 'HTTP',
},
{
code: 507,
- name: 'Insufficient Storage',
- description: 'The server is unable to store the representation needed to complete the request.',
+ name: t('tools.http-status-codes.507.name'),
+ description: t('tools.http-status-codes.507.description'),
type: 'HTTP',
},
{
code: 508,
- name: 'Loop Detected',
- description: 'The server detected an infinite loop while processing the request.',
+ name: t('tools.http-status-codes.508.name'),
+ description: t('tools.http-status-codes.508.description'),
type: 'HTTP',
},
{
code: 510,
- name: 'Not Extended',
- description: 'Further extensions to the request are required for the server to fulfill it.',
+ name: t('tools.http-status-codes.510.name'),
+ description: t('tools.http-status-codes.510.description'),
type: 'HTTP',
},
{
code: 511,
- name: 'Network Authentication Required',
- description: 'The client needs to authenticate to gain network access.',
+ name: t('tools.http-status-codes.511.name'),
+ description: t('tools.http-status-codes.511.description'),
type: 'HTTP',
},
],
diff --git a/src/tools/http-status-codes/http-status-codes.vue b/src/tools/http-status-codes/http-status-codes.vue
index 84ab3137..434ae673 100644
--- a/src/tools/http-status-codes/http-status-codes.vue
+++ b/src/tools/http-status-codes/http-status-codes.vue
@@ -1,8 +1,10 @@
@@ -25,7 +27,7 @@ const codesByCategoryFiltered = computed(() => {
diff --git a/src/tools/http-status-codes/index.ts b/src/tools/http-status-codes/index.ts
index 43afae83..9ba257fd 100644
--- a/src/tools/http-status-codes/index.ts
+++ b/src/tools/http-status-codes/index.ts
@@ -1,17 +1,18 @@
import { HttpRound } from '@vicons/material';
import { defineTool } from '../tool';
-import { codesByCategories } from './http-status-codes.constants';
+// import { codesByCategories } from './http-status-codes.constants';
+import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
- name: 'HTTP status codes',
+ name: t('tools.http-status-codes.title'),
path: '/http-status-codes',
- description: 'The list of all HTTP status codes their name and their meaning.',
+ description: t('tools.http-status-codes.description'),
keywords: [
'http',
'status',
'codes',
- ...codesByCategories.flatMap(({ codes }) => codes.flatMap(({ code, name }) => [String(code), name])),
+ // ...codesByCategories.flatMap(({ codes }) => codes.flatMap(({ code, name }) => [String(code), name])),
],
component: () => import('./http-status-codes.vue'),
icon: HttpRound,
diff --git a/src/tools/http-status-codes/locales/en.yml b/src/tools/http-status-codes/locales/en.yml
index 07f2a168..e2a02caa 100644
--- a/src/tools/http-status-codes/locales/en.yml
+++ b/src/tools/http-status-codes/locales/en.yml
@@ -2,3 +2,201 @@ tools:
http-status-codes:
title: HTTP status codes
description: The list of all HTTP status codes their name and their meaning.
+
+ searchPlaceholder: Search http status...
+ searchResults: Search results
+
+ 1xx: 1xx informational response
+ 100:
+ name: Continue
+ description: Waiting for the client to emit the body of the request.
+ 101:
+ name: Switching Protocols
+ description: The server has agreed to change protocol.
+ 102:
+ name: Processing
+ description: The server is processing the request, but no response is available yet.
+ 103:
+ name: Early Hints
+ description: The server returns some response headers before final HTTP message.
+ 2xx: 2xx success
+ 200:
+ name: OK
+ description: Standard response for successful HTTP requests.
+ 201:
+ name: Created
+ description: The request has been fulfilled, resulting in the creation of a new resource.
+ 202:
+ name: Accepted
+ description: The request has been accepted for processing, but the processing has not been completed.
+ 203:
+ name: Non-Authoritative Information
+ description: The request is successful but the content of the original request has been modified by a transforming proxy.
+ 204:
+ name: No Content
+ description: The server successfully processed the request and is not returning any content.
+ 205:
+ name: Reset Content
+ description: The server indicates to reinitialize the document view which sent this request.
+ 206:
+ name: Partial Content
+ description: The server is delivering only part of the resource due to a range header sent by the client.
+ 207:
+ name: Multi-Status
+ description: The message body that follows is an XML message and can contain a number of separate response codes.
+ 208:
+ name: Already Reported
+ description: The members of a DAV binding have already been enumerated in a preceding part of the (multistatus) response.
+ 226:
+ name: IM Used
+ description: The server has fulfilled a request for the resource, and the response is a representation of the result.
+ 3xx: 3xx redirection
+ 300:
+ name: Multiple Choices
+ description: Indicates multiple options for the resource that the client may follow.
+ 301:
+ name: Moved Permanently
+ description: This and all future requests should be directed to the given URI.
+ 302:
+ name: Found
+ description: Redirect to another URL. This is an example of industry practice contradicting the standard.
+ 303:
+ name: See Other
+ description: The response to the request can be found under another URI using a GET method.
+ 304:
+ name: Not Modified
+ description: Indicates that the resource has not been modified since the version specified by the request headers.
+ 305:
+ name: Use Proxy
+ description: The requested resource is available only through a proxy, the address for which is provided in the response.
+ 306:
+ name: Switch Proxy
+ description: No longer used. Originally meant "Subsequent requests should use the specified proxy."
+ 307:
+ name: Temporary Redirect
+ description: In this case, the request should be repeated with another URI; however, future requests should still use the original URI.
+ 308:
+ name: Permanent Redirect
+ description: The request and all future requests should be repeated using another URI.
+ 4xx: 4xx client error
+ 400:
+ name: Bad Request
+ description: The server cannot or will not process the request due to an apparent client error.
+ 401:
+ name: Unauthorized
+ description: Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided.
+ 402:
+ name: Payment Required
+ description: Reserved for future use. The original intention was that this code might be used as part of some form of digital cash or micropayment scheme.
+ 403:
+ name: Forbidden
+ description: The request was valid, but the server is refusing action. The user might not have the necessary permissions for a resource.
+ 404:
+ name: Not Found
+ description: The requested resource could not be found but may be available in the future.
+ 405:
+ name: Method Not Allowed
+ description: A request method is not supported for the requested resource.
+ 406:
+ name: Not Acceptable
+ description: The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request.
+ 407:
+ name: Proxy Authentication Required
+ description: The client must first authenticate itself with the proxy.
+ 408:
+ name: Request Timeout
+ description: The server timed out waiting for the request.
+ 409:
+ name: Conflict
+ description: Indicates that the request could not be processed because of conflict in the request, such as an edit conflict.
+ 410:
+ name: Gone
+ description: Indicates that the resource requested is no longer available and will not be available again.
+ 411:
+ name: Length Required
+ description: The request did not specify the length of its content, which is required by the requested resource.
+ 412:
+ name: Precondition Failed
+ description: The server does not meet one of the preconditions that the requester put on the request.
+ 413:
+ name: Payload Too Large
+ description: The request is larger than the server is willing or able to process.
+ 414:
+ name: URI Too Long
+ description: The URI provided was too long for the server to process.
+ 415:
+ name: Unsupported Media Type
+ description: The request entity has a media type which the server or resource does not support.
+ 416:
+ name: Range Not Satisfiable
+ description: The client has asked for a portion of the file, but the server cannot supply that portion.
+ 417:
+ name: Expectation Failed
+ description: The server cannot meet the requirements of the Expect request-header field.
+ 418:
+ name: I'm a teapot
+ description: The server refuses the attempt to brew coffee with a teapot.
+ 421:
+ name: Misdirected Request
+ description: The request was directed at a server that is not able to produce a response.
+ 422:
+ name: Unprocessable Entity
+ description: The request was well-formed but was unable to be followed due to semantic errors.
+ 423:
+ name: Locked
+ description: The resource that is being accessed is locked.
+ 424:
+ name: Failed Dependency
+ description: The request failed due to failure of a previous request.
+ 425:
+ name: Too Early
+ description: Indicates that the server is unwilling to risk processing a request that might be replayed.
+ 426:
+ name: Upgrade Required
+ description: The client should switch to a different protocol such as TLS/1.0.
+ 428:
+ name: Precondition Required
+ description: The origin server requires the request to be conditional.
+ 429:
+ name: Too Many Requests
+ description: The user has sent too many requests in a given amount of time.
+ 431:
+ name: Request Header Fields Too Large
+ description: The server is unwilling to process the request because either an individual header field, or all the header fields collectively, are too large.
+ 451:
+ name: Unavailable For Legal Reasons
+ description: A server operator has received a legal demand to deny access to a resource or to a set of resources that includes the requested resource.
+ 5xx: 5xx server error
+ 500:
+ name: Internal Server Error
+ description: A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.
+ 501:
+ name: Not Implemented
+ description: The server either does not recognize the request method, or it lacks the ability to fulfill the request.
+ 502:
+ name: Bad Gateway
+ description: The server was acting as a gateway or proxy and received an invalid response from the upstream server.
+ 503:
+ name: Service Unavailable
+ description: The server is currently unavailable (because it is overloaded or down for maintenance).
+ 504:
+ name: Gateway Timeout
+ description: The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.
+ 505:
+ name: HTTP Version Not Supported
+ description: The server does not support the HTTP protocol version used in the request.
+ 506:
+ name: Variant Also Negotiates
+ description: Transparent content negotiation for the request results in a circular reference.
+ 507:
+ name: Insufficient Storage
+ description: The server is unable to store the representation needed to complete the request.
+ 508:
+ name: Loop Detected
+ description: The server detected an infinite loop while processing the request.
+ 510:
+ name: Not Extended
+ description: Further extensions to the request are required for the server to fulfill it.
+ 511:
+ name: Network Authentication Required
+ description: The client needs to authenticate to gain network access.
diff --git a/src/tools/http-status-codes/locales/zh.yml b/src/tools/http-status-codes/locales/zh.yml
new file mode 100644
index 00000000..1fc3def2
--- /dev/null
+++ b/src/tools/http-status-codes/locales/zh.yml
@@ -0,0 +1,202 @@
+tools:
+ http-status-codes:
+ title: HTTP 状态码
+ description: 所有 HTTP 状态码及其名称和含义的列表。
+
+ searchPlaceholder: 搜索 HTTP 状态码...
+ searchResults: 搜索结果
+
+ 1xx: 1xx 信息性响应
+ 100:
+ name: 继续
+ description: 等待客户端发送请求主体。
+ 101:
+ name: 切换协议
+ description: 服务器已同意切换协议。
+ 102:
+ name: 处理中
+ description: 服务器正在处理请求,但尚未有响应可用。
+ 103:
+ name: 早期提示
+ description: 服务器在最终 HTTP 消息之前返回一些响应头。
+ 2xx: 2xx 成功
+ 200:
+ name: OK
+ description: 成功的标准 HTTP 请求响应。
+ 201:
+ name: 已创建
+ description: 请求已成功,导致创建新资源。
+ 202:
+ name: 已接受
+ description: 请求已被接受处理,但处理尚未完成。
+ 203:
+ name: 非权威信息
+ description: 请求成功,但原始请求的内容已被转换代理修改。
+ 204:
+ name: 无内容
+ description: 服务器成功处理请求,但未返回任何内容。
+ 205:
+ name: 重置内容
+ description: 服务器指示重新初始化发送此请求的文档视图。
+ 206:
+ name: 部分内容
+ description: 服务器仅因客户端发送的范围头而传送资源的部分。
+ 207:
+ name: 多状态
+ description: 接下来的消息主体是 XML 消息,可以包含许多独立的响应代码。
+ 208:
+ name: 已报告
+ description: DAV 绑定的成员已在响应的前一部分中枚举。
+ 226:
+ name: 使用 IM
+ description: 服务器已满足对资源的请求,响应是结果的表示。
+ 3xx: 3xx 重定向
+ 300:
+ name: 多种选择
+ description: 表示客户端可以跟随的资源的多个选项。
+ 301:
+ name: 永久移动
+ description: 此次及所有后续请求应重定向到给定的 URI。
+ 302:
+ name: 找到
+ description: 重定向到另一个 URL。这是一个违反标准的行业实践示例。
+ 303:
+ name: 查看其他
+ description: 请求的响应可以在另一个 URI 下使用 GET 方法找到。
+ 304:
+ name: 未修改
+ description: 表示资源自请求标头指定的版本以来未被修改。
+ 305:
+ name: 使用代理
+ description: 请求的资源仅通过代理提供,响应中提供了代理的地址。
+ 306:
+ name: 切换代理
+ description: 不再使用。最初的含义是“后续请求应使用指定的代理”。
+ 307:
+ name: 临时重定向
+ description: 在这种情况下,应重复使用另一个 URI 进行请求;但是,将来的请求仍应使用原始 URI。
+ 308:
+ name: 永久重定向
+ description: 请求和所有后续请求应重复使用另一个 URI。
+ 4xx: 4xx 客户端错误
+ 400:
+ name: 错误请求
+ description: 由于明显的客户端错误,服务器无法处理请求或不会处理请求。
+ 401:
+ name: 未经授权
+ description: 类似于 403 Forbidden,但专门用于在需要验证但验证失败或尚未提供的情况下使用。
+ 402:
+ name: 需要付款
+ description: 保留以备将来使用。最初的意图是,该代码可能作为某种数字货币或微支付方案的一部分使用。
+ 403:
+ name: 禁止
+ description: 请求有效,但服务器拒绝执行操作。用户可能没有资源所需的必要权限。
+ 404:
+ name: 未找到
+ description: 请求的资源未找到,但将来可能会可用。
+ 405:
+ name: 方法不允许
+ description: 请求方法不受请求资源支持。
+ 406:
+ name: 不可接受
+ description: 请求的资源能够生成的内容不符合请求中发送的 Accept 标头。
+ 407:
+ name: 需要代理身份验证
+ description: 客户端必须首先通过代理进行身份验证。
+ 408:
+ name: 请求超时
+ description: 服务器在等待请求时超时。
+ 409:
+ name: 冲突
+ description: 表示由于请求中的冲突(如编辑冲突)无法处理请求。
+ 410:
+ name: 已消失
+ description: 表示请求的资源不再可用,也不会再次可用。
+ 411:
+ name: 需要长度
+ description: 请求未指定所需资源的长度。
+ 412:
+ name: 前提条件失败
+ description: 服务器未满足请求者对请求的其中一个前提条件。
+ 413:
+ name: 负载过大
+ description: 请求的大小超过服务器愿意或能够处理的范围。
+ 414:
+ name: URI 过长
+ description: 提供的 URI 对服务器来说太长,无法处理。
+ 415:
+ name: 不支持的媒体类型
+ description: 请求实体具有服务器或资源不支持的媒体类型。
+ 416:
+ name: 范围不可满足
+ description: 客户端请求文件的一部分,但服务器无法提供该部分。
+ 417:
+ name: 预期失败
+ description: 服务器无法满足 Expect 请求标头字段的要求。
+ 418:
+ name: 我是茶壶
+ description: 服务器拒绝使用茶壶煮咖啡。
+ 421:
+ name: 请求错误
+ description: 请求指向无法生成响应的服务器。
+ 422:
+ name: 无法处理的实体
+ description: 请求格式正确,但由于语义错误无法进行后续处理。
+ 423:
+ name: 已锁定
+ description: 正在访问的资源已被锁定。
+ 424:
+ name: 失败的依赖
+ description: 由于先前请求的失败,请求失败。
+ 425:
+ name: 太早
+ description: 表示服务器不愿冒险处理可能会被重播的请求。
+ 426:
+ name: 需要升级
+ description: 客户端应切换到其他协议,如 TLS/1.0。
+ 428:
+ name: 需要前提条件
+ description: 源服务器要求请求是有条件的。
+ 429:
+ name: 请求过多
+ description: 用户在一定时间内发送了太多请求。
+ 431:
+ name: 请求头字段太大
+ description: 服务器不愿处理请求,因为单个标头字段或所有标头字段的总和太大。
+ 451:
+ name: 因法律原因不可用
+ description: 服务器操作员收到法律要求拒绝访问资源或包含请求的资源集。
+ 5xx: 5xx 服务器错误
+ 500:
+ name: 内部服务器错误
+ description: 遇到意外情况并且没有更具体消息适用时给出的通用错误消息。
+ 501:
+ name: 未实现
+ description: 服务器不识别请求方法,或缺乏实现请求的能力。
+ 502:
+ name: 错误网关
+ description: 服务器作为网关或代理行事,并从上游服务器接收到无效响应。
+ 503:
+ name: 服务不可用
+ description: 服务器当前不可用(因为过载或正在维护)。
+ 504:
+ name: 网关超时
+ description: 服务器作为网关或代理行事,未从上游服务器收到及时响应。
+ 505:
+ name: 不支持的 HTTP 版本
+ description: 服务器不支持请求中使用的 HTTP 协议版本。
+ 506:
+ name: 变体也进行协商
+ description: 用于请求结果的透明内容协商导致循环引用。
+ 507:
+ name: 存储空间不足
+ description: 服务器无法存储完成请求所需的表示。
+ 508:
+ name: 检测到循环
+ description: 服务器在处理请求时检测到无限循环。
+ 510:
+ name: 未扩展
+ description: 服务器需要进一步扩展请求才能满足它。
+ 511:
+ name: 需要网络认证
+ description: 客户端需要进行身份验证以获得网络访问权限。
diff --git a/src/tools/json-diff/diff-viewer/diff-viewer.vue b/src/tools/json-diff/diff-viewer/diff-viewer.vue
index 1c585df7..7070ab17 100644
--- a/src/tools/json-diff/diff-viewer/diff-viewer.vue
+++ b/src/tools/json-diff/diff-viewer/diff-viewer.vue
@@ -5,6 +5,8 @@ import { DiffRootViewer } from './diff-viewer.models';
import { useAppTheme } from '@/ui/theme/themes';
const props = defineProps<{ leftJson: unknown; rightJson: unknown }>();
+
+const { t } = useI18n();
const onlyShowDifferences = ref(false);
const { leftJson, rightJson } = toRefs(props);
const appTheme = useAppTheme();
@@ -20,14 +22,14 @@ const showResults = computed(() => !_.isUndefined(leftJson.value) && !_.isUndefi
-
+
- The provided JSONs are the same
+ {{ t('tools.json-diff.jsonAreTheSame') }}
diff --git a/src/tools/json-diff/index.ts b/src/tools/json-diff/index.ts
index 7c4c1eee..7f21808d 100644
--- a/src/tools/json-diff/index.ts
+++ b/src/tools/json-diff/index.ts
@@ -1,10 +1,11 @@
import { CompareArrowsRound } from '@vicons/material';
import { defineTool } from '../tool';
+import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
- name: 'JSON diff',
+ name: t('tools.json-diff.title'),
path: '/json-diff',
- description: 'Compare two JSON objects and get the differences between them.',
+ description: t('tools.json-diff.description'),
keywords: ['json', 'diff', 'compare', 'difference', 'object', 'data'],
component: () => import('./json-diff.vue'),
icon: CompareArrowsRound,
diff --git a/src/tools/json-diff/json-diff.vue b/src/tools/json-diff/json-diff.vue
index 80ada78b..2fceb713 100644
--- a/src/tools/json-diff/json-diff.vue
+++ b/src/tools/json-diff/json-diff.vue
@@ -5,6 +5,8 @@ import DiffsViewer from './diff-viewer/diff-viewer.vue';
import { withDefaultOnError } from '@/utils/defaults';
import { isNotThrowing } from '@/utils/boolean';
+const { t } = useI18n();
+
const rawLeftJson = ref('');
const rawRightJson = ref('');
@@ -14,7 +16,7 @@ const rightJson = computed(() => withDefaultOnError(() => JSON5.parse(rawRightJs
const jsonValidationRules = [
{
validator: (value: string) => value === '' || isNotThrowing(() => JSON5.parse(value)),
- message: 'Invalid JSON format',
+ message: t('tools.json-diff.invalidJSONFormat'),
},
];
@@ -23,8 +25,8 @@ const jsonValidationRules = [
= {
- typ: 'Type',
- alg: 'Algorithm',
- iss: 'Issuer',
- sub: 'Subject',
- aud: 'Audience',
- exp: 'Expiration Time',
- nbf: 'Not Before',
- iat: 'Issued At',
- jti: 'JWT ID',
- name: 'Full name',
- given_name: 'Given name(s) or first name(s)',
- family_name: 'Surname(s) or last name(s)',
- middle_name: 'Middle name(s)',
- nickname: 'Casual name',
- preferred_username: 'Shorthand name by which the End-User wishes to be referred to',
- profile: 'Profile page URL',
- picture: 'Profile picture URL',
- website: 'Web page or blog URL',
- email: 'Preferred e-mail address',
- email_verified: 'True if the e-mail address has been verified; otherwise false',
- gender: 'Gender',
- birthdate: 'Birthday',
- zoneinfo: 'Time zone',
- locale: 'Locale',
- phone_number: 'Preferred telephone number',
- phone_number_verified: 'True if the phone number has been verified; otherwise false',
- address: 'Preferred postal address',
- updated_at: 'Time the information was last updated',
- azp: 'Authorized party - the party to which the ID Token was issued',
- nonce: 'Value used to associate a Client session with an ID Token',
- auth_time: 'Time when the authentication occurred',
- at_hash: 'Access Token hash value',
- c_hash: 'Code hash value',
- acr: 'Authentication Context Class Reference',
- amr: 'Authentication Methods References',
- sub_jwk: 'Public key used to check the signature of an ID Token',
- cnf: 'Confirmation',
- sip_from_tag: 'SIP From tag header field parameter value',
- sip_date: 'SIP Date header field value',
- sip_callid: 'SIP Call-Id header field value',
- sip_cseq_num: 'SIP CSeq numeric header field parameter value',
- sip_via_branch: 'SIP Via branch header field parameter value',
- orig: 'Originating Identity String',
- dest: 'Destination Identity String',
- mky: 'Media Key Fingerprint String',
- events: 'Security Events',
- toe: 'Time of Event',
- txn: 'Transaction Identifier',
- rph: 'Resource Priority Header Authorization',
- sid: 'Session ID',
- vot: 'Vector of Trust value',
- vtm: 'Vector of Trust trustmark URL',
- attest: 'Attestation level as defined in SHAKEN framework',
- origid: 'Originating Identifier as defined in SHAKEN framework',
- act: 'Actor',
- scope: 'Scope Values',
- client_id: 'Client Identifier',
- may_act: 'Authorized Actor - the party that is authorized to become the actor',
- jcard: 'jCard data',
- at_use_nbr: 'Number of API requests for which the access token can be used',
- div: 'Diverted Target of a Call',
- opt: 'Original PASSporT (in Full Form)',
- vc: 'Verifiable Credential as specified in the W3C Recommendation',
- vp: 'Verifiable Presentation as specified in the W3C Recommendation',
- sph: 'SIP Priority header field',
- ace_profile: 'ACE profile a token is supposed to be used with.',
- cnonce: 'Client nonce',
- exi: 'Expires in',
- roles: 'Roles',
- groups: 'Groups',
- entitlements: 'Entitlements',
- token_introspection: 'Token introspection response',
+ typ: t('tools.jwt-parser.typ'),
+ alg: t('tools.jwt-parser.alg'),
+ iss: t('tools.jwt-parser.iss'),
+ sub: t('tools.jwt-parser.sub'),
+ aud: t('tools.jwt-parser.aud'),
+ exp: t('tools.jwt-parser.exp'),
+ nbf: t('tools.jwt-parser.nbf'),
+ iat: t('tools.jwt-parser.iat'),
+ jti: t('tools.jwt-parser.jti'),
+ name: t('tools.jwt-parser.name'),
+ given_name: t('tools.jwt-parser.givenName'),
+ family_name: t('tools.jwt-parser.familyName'),
+ middle_name: t('tools.jwt-parser.middleName'),
+ nickname: t('tools.jwt-parser.nickname'),
+ preferred_username: t('tools.jwt-parser.preferredUsername'),
+ profile: t('tools.jwt-parser.profile'),
+ picture: t('tools.jwt-parser.picture'),
+ website: t('tools.jwt-parser.website'),
+ email: t('tools.jwt-parser.email'),
+ email_verified: t('tools.jwt-parser.emailVerified'),
+ gender: t('tools.jwt-parser.gender'),
+ birthdate: t('tools.jwt-parser.birthdate'),
+ zoneinfo: t('tools.jwt-parser.zoneinfo'),
+ locale: t('tools.jwt-parser.locale'),
+ phone_number: t('tools.jwt-parser.phoneNumber'),
+ phone_number_verified: t('tools.jwt-parser.phoneNumberVerified'),
+ address: t('tools.jwt-parser.address'),
+ updated_at: t('tools.jwt-parser.updatedAt'),
+ azp: t('tools.jwt-parser.azp'),
+ nonce: t('tools.jwt-parser.nonce'),
+ auth_time: t('tools.jwt-parser.authTime'),
+ at_hash: t('tools.jwt-parser.atHash'),
+ c_hash: t('tools.jwt-parser.cHash'),
+ acr: t('tools.jwt-parser.acr'),
+ amr: t('tools.jwt-parser.amr'),
+ sub_jwk: t('tools.jwt-parser.subJwk'),
+ cnf: t('tools.jwt-parser.cnf'),
+ sip_from_tag: t('tools.jwt-parser.sipFromTag'),
+ sip_date: t('tools.jwt-parser.sipDate'),
+ sip_callid: t('tools.jwt-parser.sipCallid'),
+ sip_cseq_num: t('tools.jwt-parser.sipCseqNum'),
+ sip_via_branch: t('tools.jwt-parser.sipViaBranch'),
+ orig: t('tools.jwt-parser.orig'),
+ dest: t('tools.jwt-parser.dest'),
+ mky: t('tools.jwt-parser.mky'),
+ events: t('tools.jwt-parser.events'),
+ toe: t('tools.jwt-parser.toe'),
+ txn: t('tools.jwt-parser.txn'),
+ rph: t('tools.jwt-parser.rph'),
+ sid: t('tools.jwt-parser.sid'),
+ vot: t('tools.jwt-parser.vot'),
+ vtm: t('tools.jwt-parser.vtm'),
+ attest: t('tools.jwt-parser.attest'),
+ origid: t('tools.jwt-parser.origid'),
+ act: t('tools.jwt-parser.act'),
+ scope: t('tools.jwt-parser.scope'),
+ client_id: t('tools.jwt-parser.clientId'),
+ may_act: t('tools.jwt-parser.mayAct'),
+ jcard: t('tools.jwt-parser.jcard'),
+ at_use_nbr: t('tools.jwt-parser.atUseNbr'),
+ div: t('tools.jwt-parser.div'),
+ opt: t('tools.jwt-parser.opt'),
+ vc: t('tools.jwt-parser.vc'),
+ vp: t('tools.jwt-parser.vp'),
+ sph: t('tools.jwt-parser.sph'),
+ ace_profile: t('tools.jwt-parser.aceProfile'),
+ cnonce: t('tools.jwt-parser.cnonce'),
+ exi: t('tools.jwt-parser.exi'),
+ roles: t('tools.jwt-parser.roles'),
+ groups: t('tools.jwt-parser.groups'),
+ entitlements: t('tools.jwt-parser.entitlements'),
+ token_introspection: t('tools.jwt-parser.tokenIntrospection'),
};
diff --git a/src/tools/jwt-parser/jwt-parser.vue b/src/tools/jwt-parser/jwt-parser.vue
index 6b30fc0c..791ec571 100644
--- a/src/tools/jwt-parser/jwt-parser.vue
+++ b/src/tools/jwt-parser/jwt-parser.vue
@@ -4,6 +4,8 @@ import { useValidation } from '@/composable/validation';
import { isNotThrowing } from '@/utils/boolean';
import { withDefaultOnError } from '@/utils/defaults';
+const { t } = useI18n();
+
const rawJwt = ref(
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c',
);
@@ -13,8 +15,8 @@ const decodedJWT = computed(() =>
);
const sections = [
- { key: 'header', title: 'Header' },
- { key: 'payload', title: 'Payload' },
+ { key: 'header', title: t('tools.jwt-parser.header') },
+ { key: 'payload', title: t('tools.jwt-parser.payload') },
] as const;
const validation = useValidation({
@@ -22,7 +24,7 @@ const validation = useValidation({
rules: [
{
validator: value => value.length > 0 && isNotThrowing(() => decodeJwt({ jwt: rawJwt.value })),
- message: 'Invalid JWT',
+ message: t('tools.jwt-parser.invalidJWT'),
},
],
});
@@ -30,7 +32,7 @@ const validation = useValidation({
-
+
diff --git a/src/tools/jwt-parser/locales/en.yml b/src/tools/jwt-parser/locales/en.yml
index 956f9239..ef3cb2d4 100644
--- a/src/tools/jwt-parser/locales/en.yml
+++ b/src/tools/jwt-parser/locales/en.yml
@@ -2,3 +2,97 @@ tools:
jwt-parser:
title: JWT parser
description: Parse and decode your JSON Web Token (jwt) and display its content.
+
+ label: JWT to decode
+ placeholder: Put your token here...
+ header: Header
+ payload: Payload
+
+ invalidJWT: Invalid JWT
+
+ HS256: 'HMAC using SHA-256'
+ HS384: 'HMAC using SHA-384'
+ HS512: 'HMAC using SHA-512'
+ RS256: 'RSASSA-PKCS1-v1_5 using SHA-256'
+ RS384: 'RSASSA-PKCS1-v1_5 using SHA-384'
+ RS512: 'RSASSA-PKCS1-v1_5 using SHA-512'
+ ES256: 'ECDSA using P-256 and SHA-256'
+ ES384: 'ECDSA using P-384 and SHA-384'
+ ES512: 'ECDSA using P-521 and SHA-512'
+ PS256: 'RSASSA-PSS using SHA-256 and MGF1 with SHA-256'
+ PS384: 'RSASSA-PSS using SHA-384 and MGF1 with SHA-384'
+ PS512: 'RSASSA-PSS using SHA-512 and MGF1 with SHA-512'
+ none: 'No digital signature or MAC performed'
+
+ typ: 'Type'
+ alg: 'Algorithm'
+ iss: 'Issuer'
+ sub: 'Subject'
+ aud: 'Audience'
+ exp: 'Expiration Time'
+ nbf: 'Not Before'
+ iat: 'Issued At'
+ jti: 'JWT ID'
+ name: 'Full name'
+ givenName: 'Given name(s) or first name(s)'
+ familyName: 'Surname(s) or last name(s)'
+ middleName: 'Middle name(s)'
+ nickname: 'Casual name'
+ preferredUsername: 'Shorthand name by which the End-User wishes to be referred to'
+ profile: 'Profile page URL'
+ picture: 'Profile picture URL'
+ website: 'Web page or blog URL'
+ email: 'Preferred e-mail address'
+ emailVerified: 'True if the e-mail address has been verified; otherwise false'
+ gender: 'Gender'
+ birthdate: 'Birthday'
+ zoneinfo: 'Time zone'
+ locale: 'Locale'
+ phoneNumber: 'Preferred telephone number'
+ phoneNumberVerified: 'True if the phone number has been verified; otherwise false'
+ address: 'Preferred postal address'
+ updatedAt: 'Time the information was last updated'
+ azp: 'Authorized party - the party to which the ID Token was issued'
+ nonce: 'Value used to associate a Client session with an ID Token'
+ authTime: 'Time when the authentication occurred'
+ atHash: 'Access Token hash value'
+ cHash: 'Code hash value'
+ acr: 'Authentication Context Class Reference'
+ amr: 'Authentication Methods References'
+ subJwk: 'Public key used to check the signature of an ID Token'
+ cnf: 'Confirmation'
+ sipFromTag: 'SIP From tag header field parameter value'
+ sipDate: 'SIP Date header field value'
+ sipCallid: 'SIP Call-Id header field value'
+ sipCseqNum: 'SIP CSeq numeric header field parameter value'
+ sipViaBranch: 'SIP Via branch header field parameter value'
+ orig: 'Originating Identity String'
+ dest: 'Destination Identity String'
+ mky: 'Media Key Fingerprint String'
+ events: 'Security Events'
+ toe: 'Time of Event'
+ txn: 'Transaction Identifier'
+ rph: 'Resource Priority Header Authorization'
+ sid: 'Session ID'
+ vot: 'Vector of Trust value'
+ vtm: 'Vector of Trust trustmark URL'
+ attest: 'Attestation level as defined in SHAKEN framework'
+ origid: 'Originating Identifier as defined in SHAKEN framework'
+ act: 'Actor'
+ scope: 'Scope Values'
+ clientId: 'Client Identifier'
+ mayAct: 'Authorized Actor - the party that is authorized to become the actor'
+ jcard: 'jCard data'
+ atUseNbr: 'Number of API requests for which the access token can be used'
+ div: 'Diverted Target of a Call'
+ opt: 'Original PASSporT (in Full Form)'
+ vc: 'Verifiable Credential as specified in the W3C Recommendation'
+ vp: 'Verifiable Presentation as specified in the W3C Recommendation'
+ sph: 'SIP Priority header field'
+ aceProfile: 'ACE profile a token is supposed to be used with.'
+ cnonce: 'Client nonce'
+ exi: 'Expires in'
+ roles: 'Roles'
+ groups: 'Groups'
+ entitlements: 'Entitlements'
+ tokenIntrospection: 'Token introspection response'
diff --git a/src/tools/jwt-parser/locales/zh.yml b/src/tools/jwt-parser/locales/zh.yml
new file mode 100644
index 00000000..66f77a4b
--- /dev/null
+++ b/src/tools/jwt-parser/locales/zh.yml
@@ -0,0 +1,98 @@
+tools:
+ jwt-parser:
+ title: JWT 解析器
+ description: 解析和解码您的 JSON Web Token (jwt) 并显示其内容。
+
+ label: 要解码的 JWT
+ placeholder: 在这里放置您的令牌...
+ header: 头部
+ payload: 负载
+
+ invalidJWT: 无效的 JWT
+
+ HS256: '使用 SHA-256 的 HMAC'
+ HS384: '使用 SHA-384 的 HMAC'
+ HS512: '使用 SHA-512 的 HMAC'
+ RS256: '使用 SHA-256 的 RSASSA-PKCS1-v1_5'
+ RS384: '使用 SHA-384 的 RSASSA-PKCS1-v1_5'
+ RS512: '使用 SHA-512 的 RSASSA-PKCS1-v1_5'
+ ES256: '使用 P-256 和 SHA-256 的 ECDSA'
+ ES384: '使用 P-384 和 SHA-384 的 ECDSA'
+ ES512: '使用 P-521 和 SHA-512 的 ECDSA'
+ PS256: '使用 SHA-256 和具有 SHA-256 的 MGF1 的 RSASSA-PSS'
+ PS384: '使用 SHA-384 和具有 SHA-384 的 MGF1 的 RSASSA-PSS'
+ PS512: '使用 SHA-512 和具有 SHA-512 的 MGF1 的 RSASSA-PSS'
+ none: '未执行数字签名或 MAC'
+
+ typ: '类型'
+ alg: '算法'
+ iss: '签发者'
+ sub: '主题'
+ aud: '受众'
+ exp: '过期时间'
+ nbf: '不早于'
+ iat: '签发时间'
+ jti: 'JWT ID'
+ name: '全名'
+ givenName: '名字'
+ familyName: '姓氏'
+ middleName: '中间名'
+ nickname: '昵称'
+ preferredUsername: '用户希望被称呼的简称'
+ profile: '个人资料页面 URL'
+ picture: '个人资料图片 URL'
+ website: '网页或博客 URL'
+ email: '首选电子邮件地址'
+ emailVerified: '如果电子邮件地址已经验证为 true;否则为 false'
+ gender: '性别'
+ birthdate: '生日'
+ zoneinfo: '时区'
+ locale: '区域设置'
+ phoneNumber: '首选电话号码'
+ phoneNumberVerified: '如果电话号码已经验证为 true;否则为 false'
+ address: '首选邮寄地址'
+ updatedAt: '信息上次更新时间'
+ azp: '授权方 - 发出 ID 令牌的一方'
+ nonce: '用于将客户端会话与 ID 令牌关联的值'
+ authTime: '认证发生时间'
+ atHash: '访问令牌哈希值'
+ cHash: '代码哈希值'
+ acr: '认证上下文类引用'
+ amr: '认证方法引用'
+ subJwk: '用于验证 ID 令牌签名的公钥'
+ cnf: '确认'
+ sipFromTag: 'SIP From 标签头字段参数值'
+ sipDate: 'SIP 日期头字段值'
+ sipCallid: 'SIP Call-Id 头字段值'
+ sipCseqNum: 'SIP CSeq 数字头字段参数值'
+ sipViaBranch: 'SIP Via 分支头字段参数值'
+ orig: '原始身份字符串'
+ dest: '目标身份字符串'
+ mky: '媒体密钥指纹字符串'
+ events: '安全事件'
+ toe: '事件时间'
+ txn: '交易标识符'
+ rph: '资源优先级头授权'
+ sid: '会话 ID'
+ vot: '信任向量值'
+ vtm: '信任向量标记 URL'
+ attest: 'SHAKEN 框架中定义的证明级别'
+ origid: 'SHAKEN 框架中定义的起始标识符'
+ act: '操作者'
+ scope: '范围值'
+ clientId: '客户端标识符'
+ mayAct: '授权操作者 - 被授权成为操作者的一方'
+ jcard: 'jCard 数据'
+ atUseNbr: '访问令牌可用于的 API 请求次数'
+ div: '呼叫的被转移目标'
+ opt: '原始 PASSporT(完整形式)'
+ vc: '根据 W3C 推荐规范指定的可验证凭证'
+ vp: '根据 W3C 推荐规范指定的可验证展示'
+ sph: 'SIP 优先级头字段'
+ aceProfile: 'ACE 配置文件应与之一起使用的令牌'
+ cnonce: '客户端随机数'
+ exi: '剩余时间'
+ roles: '角色'
+ groups: '组'
+ entitlements: '权利'
+ tokenIntrospection: '令牌内省响应'
diff --git a/src/tools/keycode-info/index.ts b/src/tools/keycode-info/index.ts
index a9ffab2d..fa8ea17c 100644
--- a/src/tools/keycode-info/index.ts
+++ b/src/tools/keycode-info/index.ts
@@ -1,10 +1,11 @@
import { Keyboard } from '@vicons/tabler';
import { defineTool } from '../tool';
+import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
- name: 'Keycode info',
+ name: t('tools.keycode-info.title'),
path: '/keycode-info',
- description: 'Find the javascript keycode, code, location and modifiers of any pressed key.',
+ description: t('tools.keycode-info.description'),
keywords: [
'keycode',
'info',
diff --git a/src/tools/keycode-info/keycode-info.vue b/src/tools/keycode-info/keycode-info.vue
index a999d8ae..420e9c76 100644
--- a/src/tools/keycode-info/keycode-info.vue
+++ b/src/tools/keycode-info/keycode-info.vue
@@ -5,6 +5,8 @@ import InputCopyable from '../../components/InputCopyable.vue';
const event = ref();
+const { t } = useI18n();
+
useEventListener(document, 'keydown', (e) => {
event.value = e;
});
@@ -16,28 +18,28 @@ const fields = computed(() => {
return [
{
- label: 'Key :',
+ label: t('tools.keycode-info.keyLabel'),
value: event.value.key,
- placeholder: 'Key name...',
+ placeholder: t('tools.keycode-info.keyPlaceholder'),
},
{
- label: 'Keycode :',
+ label: t('tools.keycode-info.keycodeLabel'),
value: String(event.value.keyCode),
- placeholder: 'Keycode...',
+ placeholder: t('tools.keycode-info.keycodePlaceholder'),
},
{
- label: 'Code :',
+ label: t('tools.keycode-info.codeLabel'),
value: event.value.code,
- placeholder: 'Code...',
+ placeholder: t('tools.keycode-info.codePlaceholder'),
},
{
- label: 'Location :',
+ label: t('tools.keycode-info.locationLabel'),
value: String(event.value.location),
- placeholder: 'Code...',
+ placeholder: t('tools.keycode-info.locationPlaceholder'),
},
{
- label: 'Modifiers :',
+ label: t('tools.keycode-info.modifiersLabel'),
value: [
event.value.metaKey && 'Meta',
event.value.shiftKey && 'Shift',
@@ -46,7 +48,7 @@ const fields = computed(() => {
]
.filter(Boolean)
.join(' + '),
- placeholder: 'None',
+ placeholder: t('tools.keycode-info.modifiersPlaceholder'),
},
];
});
@@ -59,7 +61,7 @@ const fields = computed(() => {
{{ event.key }}
- Press the key on your keyboard you want to get info about this key
+ {{ t('tools.keycode-info.tips') }}
diff --git a/src/tools/keycode-info/locales/en.yml b/src/tools/keycode-info/locales/en.yml
index 98322a55..dbae839f 100644
--- a/src/tools/keycode-info/locales/en.yml
+++ b/src/tools/keycode-info/locales/en.yml
@@ -2,3 +2,16 @@ tools:
keycode-info:
title: Keycode info
description: Find the javascript keycode, code, location and modifiers of any pressed key.
+
+ keyLabel: 'Key :'
+ keyPlaceholder: 'Key name...'
+ keycodeLabel: 'Keycode :'
+ keycodePlaceholder: 'Keycode...'
+ codeLabel: 'Code :'
+ codePlaceholder: 'Code...'
+ locationLabel: 'Location :'
+ locationPlaceholder: 'Code...'
+ modifiersLabel: 'Modifiers :'
+ modifiersPlaceholder: 'None'
+
+ tips: Press the key on your keyboard you want to get info about this key
diff --git a/src/tools/keycode-info/locales/zh.yml b/src/tools/keycode-info/locales/zh.yml
new file mode 100644
index 00000000..80b5eac4
--- /dev/null
+++ b/src/tools/keycode-info/locales/zh.yml
@@ -0,0 +1,17 @@
+tools:
+ keycode-info:
+ title: 按键信息
+ description: 查找任何按键的 JavaScript 按键码、代码、位置和修饰键。
+
+ keyLabel: '按键:'
+ keyPlaceholder: '按键名称...'
+ keycodeLabel: '按键码:'
+ keycodePlaceholder: '按键码...'
+ codeLabel: '代码:'
+ codePlaceholder: '代码...'
+ locationLabel: '位置:'
+ locationPlaceholder: '位置...'
+ modifiersLabel: '修饰键:'
+ modifiersPlaceholder: '无'
+
+ tips: 按下您键盘上想要获取信息的按键
diff --git a/src/tools/slugify-string/index.ts b/src/tools/slugify-string/index.ts
index 8dabcdb1..07ee16bc 100644
--- a/src/tools/slugify-string/index.ts
+++ b/src/tools/slugify-string/index.ts
@@ -1,10 +1,11 @@
import { AbcRound } from '@vicons/material';
import { defineTool } from '../tool';
+import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
- name: 'Slugify string',
+ name: t('tools.slugify-string.title'),
path: '/slugify-string',
- description: 'Make a string url, filename and id safe.',
+ description: t('tools.slugify-string.description'),
keywords: ['slugify', 'string', 'escape', 'emoji', 'special', 'character', 'space', 'trim'],
component: () => import('./slugify-string.vue'),
icon: AbcRound,
diff --git a/src/tools/slugify-string/locales/en.yml b/src/tools/slugify-string/locales/en.yml
index 7161b20d..fe2fdd37 100644
--- a/src/tools/slugify-string/locales/en.yml
+++ b/src/tools/slugify-string/locales/en.yml
@@ -2,3 +2,11 @@ tools:
slugify-string:
title: Slugify string
description: Make a string url, filename and id safe.
+
+ inputLabel: Your string to slugify
+ inputPlaceholder: 'Put your string here (ex: My file path)'
+ outputLabel: Your slug
+ outputPlaceholder: 'You slug will be generated here (ex: my-file-path)'
+ copyBtn: Copy slug
+
+ copied: Slug copied to clipboard
diff --git a/src/tools/slugify-string/locales/zh.yml b/src/tools/slugify-string/locales/zh.yml
new file mode 100644
index 00000000..925ae6e6
--- /dev/null
+++ b/src/tools/slugify-string/locales/zh.yml
@@ -0,0 +1,12 @@
+tools:
+ slugify-string:
+ title: 字符串转换为 Slug
+ description: 将字符串转换为 URL、文件名和 ID 安全的格式。
+
+ inputLabel: 要转换为 Slug 的字符串
+ inputPlaceholder: '在此输入您的字符串(例如:我的文件路径)'
+ outputLabel: 您的 Slug
+ outputPlaceholder: '您的 Slug 将在此生成(例如:my-file-path)'
+ copyBtn: 复制 Slug
+
+ copied: Slug 已复制到剪贴板
diff --git a/src/tools/slugify-string/slugify-string.vue b/src/tools/slugify-string/slugify-string.vue
index f7666e30..82b44ec8 100644
--- a/src/tools/slugify-string/slugify-string.vue
+++ b/src/tools/slugify-string/slugify-string.vue
@@ -3,20 +3,21 @@ import slugify from '@sindresorhus/slugify';
import { withDefaultOnError } from '@/utils/defaults';
import { useCopy } from '@/composable/copy';
+const { t } = useI18n();
const input = ref('');
const slug = computed(() => withDefaultOnError(() => slugify(input.value), ''));
-const { copy } = useCopy({ source: slug, text: 'Slug copied to clipboard' });
+const { copy } = useCopy({ source: slug, text: t('tools.slugify-string.copied') });
-
+
-
+
- Copy slug
+ {{ t('tools.slugify-string.copyBtn') }}
diff --git a/src/tools/user-agent-parser/index.ts b/src/tools/user-agent-parser/index.ts
index 1ae05d14..6f8303fa 100644
--- a/src/tools/user-agent-parser/index.ts
+++ b/src/tools/user-agent-parser/index.ts
@@ -1,10 +1,11 @@
import { Browser } from '@vicons/tabler';
import { defineTool } from '../tool';
+import { translate as t } from '@/plugins/i18n.plugin';
export const tool = defineTool({
- name: 'User-agent parser',
+ name: t('tools.user-agent-parser.title'),
path: '/user-agent-parser',
- description: 'Detect and parse Browser, Engine, OS, CPU, and Device type/model from an user-agent string.',
+ description: t('tools.user-agent-parser.description'),
keywords: ['user', 'agent', 'parser', 'browser', 'engine', 'os', 'cpu', 'device', 'user-agent', 'client'],
component: () => import('./user-agent-parser.vue'),
icon: Browser,
diff --git a/src/tools/user-agent-parser/locales/en.yml b/src/tools/user-agent-parser/locales/en.yml
index 8116a38c..a17ad9c9 100644
--- a/src/tools/user-agent-parser/locales/en.yml
+++ b/src/tools/user-agent-parser/locales/en.yml
@@ -2,3 +2,29 @@ tools:
user-agent-parser:
title: User-agent parser
description: Detect and parse Browser, Engine, OS, CPU, and Device type/model from an user-agent string.
+
+ name: Name
+ version: Version
+ model: Model
+ type: Type
+ vendor: Vendor
+ architecture: Architecture
+
+ browser: Browser
+ browserNameFallback: No browser name available
+ browserVersionFallback: No browser version available
+ engine: Engine
+ engineNameFallback: No engine name available
+ engineVersionFallback: No engine version available
+ os: OS
+ osNameFallback: No OS name available
+ osVersionFallback: No OS version available
+ device: Device
+ deviceModelFallback: No device model available
+ deviceTypeFallback: No device type available
+ deviceVendorFallback: No device vendor available
+ cpu: CPU
+ cpuArchitectureFallback: No CPU architecture available
+
+ label: User agent string
+ placeholder: Put your user-agent here...
diff --git a/src/tools/user-agent-parser/locales/zh.yml b/src/tools/user-agent-parser/locales/zh.yml
new file mode 100644
index 00000000..f1949d38
--- /dev/null
+++ b/src/tools/user-agent-parser/locales/zh.yml
@@ -0,0 +1,30 @@
+tools:
+ user-agent-parser:
+ title: User-agent 解析器
+ description: 从用户代理字符串中检测和解析浏览器、引擎、操作系统、CPU 和设备类型/型号。
+
+ name: 名称
+ version: 版本
+ model: 型号
+ type: 类型
+ vendor: 供应商
+ architecture: 架构
+
+ browser: 浏览器
+ browserNameFallback: 没有可用的浏览器名称
+ browserVersionFallback: 没有可用的浏览器版本
+ engine: 引擎
+ engineNameFallback: 没有可用的引擎名称
+ engineVersionFallback: 没有可用的引擎版本
+ os: 操作系统
+ osNameFallback: 没有可用的操作系统名称
+ osVersionFallback: 没有可用的操作系统版本
+ device: 设备
+ deviceModelFallback: 没有可用的设备型号
+ deviceTypeFallback: 没有可用的设备类型
+ deviceVendorFallback: 没有可用的设备供应商
+ cpu: 中央处理器
+ cpuArchitectureFallback: 没有可用的 CPU 架构
+
+ label: 用户代理字符串
+ placeholder: 在此处输入您的用户代理字符串...
diff --git a/src/tools/user-agent-parser/user-agent-parser.vue b/src/tools/user-agent-parser/user-agent-parser.vue
index 5a4ec270..67a23d3f 100644
--- a/src/tools/user-agent-parser/user-agent-parser.vue
+++ b/src/tools/user-agent-parser/user-agent-parser.vue
@@ -6,6 +6,7 @@ import type { UserAgentResultSection } from './user-agent-parser.types';
import { withDefaultOnError } from '@/utils/defaults';
const ua = ref(navigator.userAgent as string);
+const { t } = useI18n();
// If not input in the ua field is present return an empty object of type UAParser.IResult because otherwise
// UAParser returns the values for the current Browser. This is confusing because results are shown for an empty
@@ -19,82 +20,82 @@ const userAgentInfo = computed(() => withDefaultOnError(() => getUserAgentInfo(u
const sections: UserAgentResultSection[] = [
{
- heading: 'Browser',
+ heading: t('tools.user-agent-parser.browser'),
icon: Browser,
content: [
{
- label: 'Name',
+ label: t('tools.user-agent-parser.name'),
getValue: block => block?.browser.name,
- undefinedFallback: 'No browser name available',
+ undefinedFallback: t('tools.user-agent-parser.browserNameFallback'),
},
{
- label: 'Version',
+ label: t('tools.user-agent-parser.version'),
getValue: block => block?.browser.version,
- undefinedFallback: 'No browser version available',
+ undefinedFallback: t('tools.user-agent-parser.browserVersionFallback'),
},
],
},
{
- heading: 'Engine',
+ heading: t('tools.user-agent-parser.engine'),
icon: Engine,
content: [
{
- label: 'Name',
+ label: t('tools.user-agent-parser.name'),
getValue: block => block?.engine.name,
- undefinedFallback: 'No engine name available',
+ undefinedFallback: t('tools.user-agent-parser.engineNameFallback'),
},
{
- label: 'Version',
+ label: t('tools.user-agent-parser.version'),
getValue: block => block?.engine.version,
- undefinedFallback: 'No engine version available',
+ undefinedFallback: t('tools.user-agent-parser.engineVersionFallback'),
},
],
},
{
- heading: 'OS',
+ heading: t('tools.user-agent-parser.os'),
icon: Adjustments,
content: [
{
- label: 'Name',
+ label: t('tools.user-agent-parser.name'),
getValue: block => block?.os.name,
- undefinedFallback: 'No OS name available',
+ undefinedFallback: t('tools.user-agent-parser.osNameFallback'),
},
{
- label: 'Version',
+ label: t('tools.user-agent-parser.version'),
getValue: block => block?.os.version,
- undefinedFallback: 'No OS version available',
+ undefinedFallback: t('tools.user-agent-parser.osVersionFallback'),
},
],
},
{
- heading: 'Device',
+ heading: t('tools.user-agent-parser.device'),
icon: Devices,
content: [
{
- label: 'Model',
+ label: t('tools.user-agent-parser.model'),
getValue: block => block?.device.model,
- undefinedFallback: 'No device model available',
+ undefinedFallback: t('tools.user-agent-parser.deviceModelFallback'),
},
{
- label: 'Type',
+ label: t('tools.user-agent-parser.type'),
getValue: block => block?.device.type,
- undefinedFallback: 'No device type available',
+ undefinedFallback: t('tools.user-agent-parser.deviceTypeFallback'),
},
{
- label: 'Vendor',
+ label: t('tools.user-agent-parser.vendor'),
getValue: block => block?.device.vendor,
- undefinedFallback: 'No device vendor available',
+ undefinedFallback: t('tools.user-agent-parser.deviceVendorFallback'),
},
],
},
{
- heading: 'CPU',
+ heading: t('tools.user-agent-parser.cpu'),
icon: Cpu,
content: [
{
- label: 'Architecture',
+ label: t('tools.user-agent-parser.architecture'),
getValue: block => block?.cpu.architecture,
- undefinedFallback: 'No CPU architecture available',
+ undefinedFallback: t('tools.user-agent-parser.cpuArchitectureFallback'),
},
],
},
@@ -105,9 +106,9 @@ const sections: UserAgentResultSection[] = [