Przeglądaj źródła

feat(i18n): 添加简体中文转繁体中文支持

添加 opencc-js 和 language-hk-loader 依赖
创建 opencc-plugin 插件处理 Vue 和 HTML 文件的简繁转换
更新 tsconfig 和 vite 配置以支持新插件
lsc 1 tydzień temu
rodzic
commit
34c4614a45
6 zmienionych plików z 97 dodań i 2 usunięć
  1. 26 0
      package-lock.json
  2. 2 0
      package.json
  3. 54 0
      src/plugins/opencc-plugin.ts
  4. 10 0
      src/types/opencc-js.d.ts
  5. 2 1
      tsconfig.node.json
  6. 3 1
      vite.config.ts

+ 26 - 0
package-lock.json

@@ -71,7 +71,9 @@
         "eslint": "^8.49.0",
         "eslint-plugin-vue": "^9.17.0",
         "husky": "^8.0.3",
+        "language-hk-loader": "^1.0.1",
         "npm-run-all2": "^6.1.1",
+        "opencc-js": "^1.0.5",
         "sass": "1.69.6",
         "typescript": "~5.3.0",
         "vite": "^5.3.5",
@@ -3852,6 +3854,12 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/language-hk-loader": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/language-hk-loader/-/language-hk-loader-1.0.1.tgz",
+      "integrity": "sha512-OmOLx119bkmabkQYn4GvxzMrnp2PAxX6lhHkMwqyaHA6Casi6SyO5uhst1+svPJcR+kA7r8d7H3ri97N1JKXng==",
+      "dev": true
+    },
     "node_modules/levn": {
       "version": "0.4.1",
       "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz",
@@ -4313,6 +4321,12 @@
         "node": ">=6"
       }
     },
+    "node_modules/opencc-js": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/opencc-js/-/opencc-js-1.0.5.tgz",
+      "integrity": "sha512-LD+1SoNnZdlRwtYTjnQdFrSVCAaYpuDqL5CkmOaHOkKoKh7mFxUicLTRVNLU5C+Jmi1vXQ3QL4jWdgSaa4sKjg==",
+      "dev": true
+    },
     "node_modules/optionator": {
       "version": "0.9.3",
       "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.3.tgz",
@@ -8737,6 +8751,12 @@
       "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
       "dev": true
     },
+    "language-hk-loader": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/language-hk-loader/-/language-hk-loader-1.0.1.tgz",
+      "integrity": "sha512-OmOLx119bkmabkQYn4GvxzMrnp2PAxX6lhHkMwqyaHA6Casi6SyO5uhst1+svPJcR+kA7r8d7H3ri97N1JKXng==",
+      "dev": true
+    },
     "levn": {
       "version": "0.4.1",
       "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz",
@@ -9094,6 +9114,12 @@
         "mimic-fn": "^2.1.0"
       }
     },
+    "opencc-js": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/opencc-js/-/opencc-js-1.0.5.tgz",
+      "integrity": "sha512-LD+1SoNnZdlRwtYTjnQdFrSVCAaYpuDqL5CkmOaHOkKoKh7mFxUicLTRVNLU5C+Jmi1vXQ3QL4jWdgSaa4sKjg==",
+      "dev": true
+    },
     "optionator": {
       "version": "0.9.3",
       "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.3.tgz",

+ 2 - 0
package.json

@@ -78,7 +78,9 @@
     "eslint": "^8.49.0",
     "eslint-plugin-vue": "^9.17.0",
     "husky": "^8.0.3",
+    "language-hk-loader": "^1.0.1",
     "npm-run-all2": "^6.1.1",
+    "opencc-js": "^1.0.5",
     "sass": "1.69.6",
     "typescript": "~5.3.0",
     "vite": "^5.3.5",

+ 54 - 0
src/plugins/opencc-plugin.ts

@@ -0,0 +1,54 @@
+import type { PluginOption } from 'vite'
+import * as OpenCC from 'opencc-js'
+
+// 创建转换配置:简体中文转繁体中文(香港标准)
+const converter = OpenCC.Converter({
+  from: 'cn',
+  to: 'hk'
+})
+
+// Vite 插件配置
+const openccPlugin: PluginOption = {
+  name: 'opencc-plugin',
+  
+  // 处理 Vue SFC 编译后的 JavaScript
+  transform(code, id) {
+    if (id.endsWith('.vue') || id.includes('/node_modules/.vite/')) {
+      // console.log(`[OpenCC] 处理文件: ${id}`)
+      
+      // 转换所有字符串内容
+      const originalCode = code
+      
+      // 简单的字符串转换(不处理复杂情况)
+      code = code.replace(/('|"|`)([^'"`]*?)(\1)/g, (match, quote, content) => {
+        // 排除代码和注释
+        if (!content.includes('//') && !content.includes('/*')) {
+          const converted = converter(content)
+          if (converted !== content) {
+            // console.log(`[OpenCC] 字符串已转换: ${content} → ${converted}`)
+          }
+          return `${quote}${converted}${quote}`
+        }
+        return match
+      })
+      
+      if (code !== originalCode) {
+        // console.log(`[OpenCC] 文件 ${id} 转换完成`)
+      }
+    }
+    
+    return code
+  },
+  
+  // 处理 HTML 文件
+  transformIndexHtml(html) {
+    // console.log('[OpenCC] 处理 HTML 文件')
+    const converted = converter(html)
+    if (converted !== html) {
+      // console.log('[OpenCC] HTML 内容已转换')
+    }
+    return converted
+  }
+}
+
+export default openccPlugin

+ 10 - 0
src/types/opencc-js.d.ts

@@ -0,0 +1,10 @@
+declare module 'opencc-js' {
+  interface ConverterConfig {
+    from: string
+    to: string
+  }
+
+  type Converter = (text: string) => string
+
+  export function Converter(config: ConverterConfig): Converter
+}

+ 2 - 1
tsconfig.node.json

@@ -5,7 +5,8 @@
     "vitest.config.*",
     "cypress.config.*",
     "nightwatch.conf.*",
-    "playwright.config.*"
+    "playwright.config.*",
+    "src/plugins/opencc-plugin.ts"
   ],
   "compilerOptions": {
     "composite": true,

+ 3 - 1
vite.config.ts

@@ -2,12 +2,14 @@ import { fileURLToPath, URL } from 'node:url'
 
 import { defineConfig } from 'vite'
 import vue from '@vitejs/plugin-vue'
+import openccPlugin from './src/plugins/opencc-plugin'
 
 // https://vitejs.dev/config/
 export default defineConfig({
   base: '',
   plugins: [
-    vue(),
+    openccPlugin,
+    vue()
   ],
   server: {
     host: '0.0.0.0',