WIP(translate): translate web category all tools
This commit is contained in:
		
							parent
							
								
									c6583ef013
								
							
						
					
					
						commit
						9db4b41daf
					
				| @ -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)' | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| tools: | ||||
|   html-entities: | ||||
|     title: 转义 HTML 实体 | ||||
|     description: 转义或取消转义 HTML 实体(将 <,>, &, " 和 \' 替换为它们的 HTML 版本) | ||||
|     description: 转义或取消转义 HTML 实体(将 <,>, &, " 和 ' 替换为它们的 HTML 版本) | ||||
| 
 | ||||
|     escape: | ||||
|       title: 转义 HTML 实体 | ||||
|  | ||||
| @ -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(), | ||||
|   }, | ||||
| ]; | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
							
								
								
									
										21
									
								
								src/tools/html-wysiwyg-editor/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/tools/html-wysiwyg-editor/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							| @ -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: 重做 | ||||
| @ -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', | ||||
|       }, | ||||
|     ], | ||||
|  | ||||
| @ -1,8 +1,10 @@ | ||||
| <script setup lang="ts"> | ||||
| import { codesByCategories } from './http-status-codes.constants'; | ||||
| import * as status from './http-status-codes.constants'; | ||||
| import { useFuzzySearch } from '@/composable/fuzzySearch'; | ||||
| 
 | ||||
| const search = ref(''); | ||||
| const { t } = useI18n(); | ||||
| const { codesByCategories } = status; | ||||
| 
 | ||||
| const { searchResult } = useFuzzySearch({ | ||||
|   search, | ||||
| @ -17,7 +19,7 @@ const codesByCategoryFiltered = computed(() => { | ||||
|     return codesByCategories; | ||||
|   } | ||||
| 
 | ||||
|   return [{ category: 'Search results', codes: searchResult.value }]; | ||||
|   return [{ category: t('tools.http-status-codes.searchResults'), codes: searchResult.value }]; | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| @ -25,7 +27,7 @@ const codesByCategoryFiltered = computed(() => { | ||||
|   <div> | ||||
|     <c-input-text | ||||
|       v-model:value="search" | ||||
|       placeholder="Search http status..." | ||||
|       :placeholder="t('tools.http-status-codes.searchPlaceholder')" | ||||
|       autofocus raw-text mb-10 | ||||
|     /> | ||||
| 
 | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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. | ||||
|  | ||||
							
								
								
									
										202
									
								
								src/tools/http-status-codes/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								src/tools/http-status-codes/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							| @ -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: 客户端需要进行身份验证以获得网络访问权限。 | ||||
| @ -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 | ||||
| <template> | ||||
|   <div v-if="showResults"> | ||||
|     <div flex justify-center> | ||||
|       <n-form-item label="Only show differences" label-placement="left"> | ||||
|       <n-form-item :label="t('tools.json-diff.onlyShowDifferences')" label-placement="left"> | ||||
|         <n-switch v-model:value="onlyShowDifferences" /> | ||||
|       </n-form-item> | ||||
|     </div> | ||||
| 
 | ||||
|     <c-card data-test-id="diff-result"> | ||||
|       <div v-if="jsonAreTheSame" text-center op-70> | ||||
|         The provided JSONs are the same | ||||
|         {{ t('tools.json-diff.jsonAreTheSame') }} | ||||
|       </div> | ||||
|       <DiffRootViewer v-else :diff="result" /> | ||||
|     </c-card> | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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'), | ||||
|   }, | ||||
| ]; | ||||
| </script> | ||||
| @ -23,8 +25,8 @@ const jsonValidationRules = [ | ||||
|   <c-input-text | ||||
|     v-model:value="rawLeftJson" | ||||
|     :validation-rules="jsonValidationRules" | ||||
|     label="Your first JSON" | ||||
|     placeholder="Paste your first JSON here..." | ||||
|     :label="t('tools.json-diff.inputLable')" | ||||
|     :placeholder="t('tools.json-diff.inputPlaceholder')" | ||||
|     rows="20" | ||||
|     multiline | ||||
|     test-id="leftJson" | ||||
| @ -35,8 +37,8 @@ const jsonValidationRules = [ | ||||
|   <c-input-text | ||||
|     v-model:value="rawRightJson" | ||||
|     :validation-rules="jsonValidationRules" | ||||
|     label="Your JSON to compare" | ||||
|     placeholder="Paste your JSON to compare here..." | ||||
|     :label="t('tools.json-diff.outputLable')" | ||||
|     :placeholder="t('tools.json-diff.outputPlaceholder')" | ||||
|     rows="20" | ||||
|     multiline | ||||
|     test-id="rightJson" | ||||
|  | ||||
| @ -2,3 +2,12 @@ tools: | ||||
|   json-diff: | ||||
|     title: JSON diff | ||||
|     description: Compare two JSON objects and get the differences between them. | ||||
| 
 | ||||
|     inputLable: Your first JSON | ||||
|     inputPlaceholder: Paste your first JSON here... | ||||
|     outputLable: Your JSON to compare | ||||
|     outputPlaceholder: Paste your JSON to compare here... | ||||
|     onlyShowDifferences: Only show differences | ||||
|     jsonAreTheSame: The provided JSONs are the same | ||||
| 
 | ||||
|     invalidJSONFormat: Invalid JSON format | ||||
|  | ||||
							
								
								
									
										13
									
								
								src/tools/json-diff/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/tools/json-diff/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| tools: | ||||
|   json-diff: | ||||
|     title: JSON 对比 | ||||
|     description: 比较两个 JSON 对象并获取它们之间的差异。 | ||||
| 
 | ||||
|     inputLable: 您的第一个 JSON | ||||
|     inputPlaceholder: 在此粘贴您的第一个 JSON... | ||||
|     outputLable: 您要比较的 JSON | ||||
|     outputPlaceholder: 在此粘贴要比较的 JSON... | ||||
|     onlyShowDifferences: 仅显示差异 | ||||
|     jsonAreTheSame: 提供的 JSON 相同 | ||||
| 
 | ||||
|     invalidJSONFormat: 无效的 JSON 格式 | ||||
| @ -1,92 +1,94 @@ | ||||
| import { translate as t } from '@/plugins/i18n.plugin'; | ||||
| 
 | ||||
| // From https://datatracker.ietf.org/doc/html/rfc7518#section-3.1
 | ||||
| export const ALGORITHM_DESCRIPTIONS: { [k: string]: string } = { | ||||
|   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', | ||||
|   HS256: t('tools.jwt-parser.HS256'), | ||||
|   HS384: t('tools.jwt-parser.HS384'), | ||||
|   HS512: t('tools.jwt-parser.HS512'), | ||||
|   RS256: t('tools.jwt-parser.RS256'), | ||||
|   RS384: t('tools.jwt-parser.RS384'), | ||||
|   RS512: t('tools.jwt-parser.RS512'), | ||||
|   ES256: t('tools.jwt-parser.ES256'), | ||||
|   ES384: t('tools.jwt-parser.ES384'), | ||||
|   ES512: t('tools.jwt-parser.ES512'), | ||||
|   PS256: t('tools.jwt-parser.PS256'), | ||||
|   PS384: t('tools.jwt-parser.PS384'), | ||||
|   PS512: t('tools.jwt-parser.PS512'), | ||||
|   none: t('tools.jwt-parser.none'), | ||||
| }; | ||||
| 
 | ||||
| // List extracted from IANA: https://www.iana.org/assignments/jwt/jwt.xhtml
 | ||||
| export const CLAIM_DESCRIPTIONS: Record<string, string> = { | ||||
|   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'), | ||||
| }; | ||||
|  | ||||
| @ -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({ | ||||
| 
 | ||||
| <template> | ||||
|   <c-card> | ||||
|     <c-input-text v-model:value="rawJwt" label="JWT to decode" :validation="validation" placeholder="Put your token here..." rows="5" multiline raw-text autofocus mb-3 /> | ||||
|     <c-input-text v-model:value="rawJwt" :label="t('tools.jwt-parser.label')" :validation="validation" :placeholder="t('tools.jwt-parser.placeholder')" rows="5" multiline raw-text autofocus mb-3 /> | ||||
| 
 | ||||
|     <n-table v-if="validation.isValid"> | ||||
|       <tbody> | ||||
|  | ||||
| @ -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' | ||||
|  | ||||
							
								
								
									
										98
									
								
								src/tools/jwt-parser/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/tools/jwt-parser/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							| @ -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: '令牌内省响应' | ||||
| @ -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', | ||||
|  | ||||
| @ -5,6 +5,8 @@ import InputCopyable from '../../components/InputCopyable.vue'; | ||||
| 
 | ||||
| const event = ref<KeyboardEvent>(); | ||||
| 
 | ||||
| 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 }} | ||||
|       </div> | ||||
|       <span lh-1 op-70> | ||||
|         Press the key on your keyboard you want to get info about this key | ||||
|         {{ t('tools.keycode-info.tips') }} | ||||
|       </span> | ||||
|     </c-card> | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
							
								
								
									
										17
									
								
								src/tools/keycode-info/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/tools/keycode-info/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| tools: | ||||
|   keycode-info: | ||||
|     title: 按键信息 | ||||
|     description: 查找任何按键的 JavaScript 按键码、代码、位置和修饰键。 | ||||
| 
 | ||||
|     keyLabel: '按键:' | ||||
|     keyPlaceholder: '按键名称...' | ||||
|     keycodeLabel: '按键码:' | ||||
|     keycodePlaceholder: '按键码...' | ||||
|     codeLabel: '代码:' | ||||
|     codePlaceholder: '代码...' | ||||
|     locationLabel: '位置:' | ||||
|     locationPlaceholder: '位置...' | ||||
|     modifiersLabel: '修饰键:' | ||||
|     modifiersPlaceholder: '无' | ||||
| 
 | ||||
|     tips: 按下您键盘上想要获取信息的按键 | ||||
| @ -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, | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
							
								
								
									
										12
									
								
								src/tools/slugify-string/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/tools/slugify-string/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							| @ -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 已复制到剪贴板 | ||||
| @ -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') }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <div> | ||||
|     <c-input-text v-model:value="input" multiline placeholder="Put your string here (ex: My file path)" label="Your string to slugify" autofocus raw-text mb-5 /> | ||||
|     <c-input-text v-model:value="input" multiline :placeholder="t('tools.slugify-string.inputPlaceholder')" :label="t('tools.slugify-string.inputLabel')" autofocus raw-text mb-5 /> | ||||
| 
 | ||||
|     <c-input-text :value="slug" multiline readonly placeholder="You slug will be generated here (ex: my-file-path)" label="Your slug" mb-5 /> | ||||
|     <c-input-text :value="slug" multiline readonly :placeholder="t('tools.slugify-string.outputPlaceholder')" :label="t('tools.slugify-string.outputLabel')" mb-5 /> | ||||
| 
 | ||||
|     <div flex justify-center> | ||||
|       <c-button :disabled="slug.length === 0" @click="copy()"> | ||||
|         Copy slug | ||||
|         {{ t('tools.slugify-string.copyBtn') }} | ||||
|       </c-button> | ||||
|     </div> | ||||
|   </div> | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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... | ||||
|  | ||||
							
								
								
									
										30
									
								
								src/tools/user-agent-parser/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/tools/user-agent-parser/locales/zh.yml
									
									
									
									
									
										Normal file
									
								
							| @ -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: 在此处输入您的用户代理字符串... | ||||
| @ -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[] = [ | ||||
|   <div> | ||||
|     <c-input-text | ||||
|       v-model:value="ua" | ||||
|       label="User agent string" | ||||
|       :label="t('tools.user-agent-parser.label')" | ||||
|       multiline | ||||
|       placeholder="Put your user-agent here..." | ||||
|       :placeholder="t('tools.user-agent-parser.placeholder')" | ||||
|       clearable | ||||
|       raw-text | ||||
|       rows="2" | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user