babaofan-translate-cli 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -43
- package/package.json +3 -2
- package/utils.js +244 -0
package/README.md
CHANGED
|
@@ -89,49 +89,6 @@ npm install
|
|
|
89
89
|
- 已安装当前项目依赖
|
|
90
90
|
- 能访问 Google AI Studio / Gemini 接口
|
|
91
91
|
|
|
92
|
-
## 发布到 npm
|
|
93
|
-
|
|
94
|
-
发布前建议先确认:
|
|
95
|
-
|
|
96
|
-
- [package.json](./package.json) 中的 `name`、`version`、`description` 已经正确
|
|
97
|
-
- [config.js](./config.js) 里不要保留你自己的真实 API Key
|
|
98
|
-
- 本地已经执行过测试命令
|
|
99
|
-
|
|
100
|
-
### 1. 登录 npm
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
npm login
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### 2. 检查最终会发布哪些文件
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
npm pack --dry-run
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### 3. 发布
|
|
113
|
-
|
|
114
|
-
首次发布:
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
npm publish
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
如果后续发新版本,先改 `version`,再发布:
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
npm version patch
|
|
124
|
-
npm publish
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
你也可以按需使用:
|
|
128
|
-
|
|
129
|
-
```bash
|
|
130
|
-
npm version minor
|
|
131
|
-
npm version major
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## 在别的项目里使用
|
|
135
92
|
|
|
136
93
|
### 安装
|
|
137
94
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"private": false,
|
|
3
3
|
"name": "babaofan-translate-cli",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"description": "A local CLI for scanning i18n calls, generating semantic keys, translating with Google AI Studio, and updating locale files.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"bin",
|
|
15
15
|
"config.js",
|
|
16
|
-
"README.md"
|
|
16
|
+
"README.md",
|
|
17
|
+
"utils.js"
|
|
17
18
|
],
|
|
18
19
|
"keywords": [
|
|
19
20
|
"i18n",
|
package/utils.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 公共工具函数模块
|
|
5
|
+
* 提供跨脚本使用的通用功能
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import chalk from "chalk";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import fs from "fs";
|
|
11
|
+
import { execSync } from "child_process";
|
|
12
|
+
import os from "os";
|
|
13
|
+
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// 路径工具
|
|
16
|
+
// ============================================================================
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 获取项目根目录
|
|
20
|
+
* @returns {string} 项目根目录路径
|
|
21
|
+
*/
|
|
22
|
+
function getProjectRoot() {
|
|
23
|
+
// return "/Users/jiangshuai/Desktop/coding/cool/uniapp/cool-unix";
|
|
24
|
+
return process.cwd();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 获取相对于项目根目录的路径
|
|
29
|
+
* @param {string} absolutePath - 绝对路径
|
|
30
|
+
* @param {string} projectRoot - 项目根目录(可选)
|
|
31
|
+
* @returns {string} 相对路径
|
|
32
|
+
*/
|
|
33
|
+
function getRelativePath(absolutePath, projectRoot = getProjectRoot()) {
|
|
34
|
+
return absolutePath.replace(projectRoot, "").replace(/^\//, "");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// 文件系统工具
|
|
39
|
+
// ============================================================================
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 确保目录存在,不存在则创建
|
|
43
|
+
* @param {string} filePath - 文件路径或目录路径
|
|
44
|
+
*/
|
|
45
|
+
function ensureDirectoryExists(filePath) {
|
|
46
|
+
const dirPath = path.dirname(filePath);
|
|
47
|
+
if (!fs.existsSync(dirPath)) {
|
|
48
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 递归复制目录/文件(覆盖模式)
|
|
54
|
+
* @param {string} src - 源路径
|
|
55
|
+
* @param {string} dest - 目标路径
|
|
56
|
+
*/
|
|
57
|
+
function copyRecursive(src, dest) {
|
|
58
|
+
const stat = fs.statSync(src);
|
|
59
|
+
|
|
60
|
+
if (fs.existsSync(dest)) {
|
|
61
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (stat.isDirectory()) {
|
|
65
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
66
|
+
const items = fs.readdirSync(src);
|
|
67
|
+
for (const item of items) {
|
|
68
|
+
const srcPath = path.join(src, item);
|
|
69
|
+
const destPath = path.join(dest, item);
|
|
70
|
+
copyRecursive(srcPath, destPath);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
fs.copyFileSync(src, dest);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 清理目录
|
|
79
|
+
* @param {string} dirPath - 目录路径
|
|
80
|
+
* @returns {boolean} 是否成功清理
|
|
81
|
+
*/
|
|
82
|
+
function cleanDirectory(dirPath) {
|
|
83
|
+
if (fs.existsSync(dirPath)) {
|
|
84
|
+
fs.rmSync(dirPath, { recursive: true, force: true });
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// 终端日志工具
|
|
92
|
+
// ============================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 统一的日志工具类
|
|
96
|
+
*/
|
|
97
|
+
const logger = {
|
|
98
|
+
/**
|
|
99
|
+
* 打印标题
|
|
100
|
+
* @param {string} text - 标题文本
|
|
101
|
+
*/
|
|
102
|
+
title(text) {
|
|
103
|
+
console.log();
|
|
104
|
+
console.log(chalk.white.bold(text));
|
|
105
|
+
console.log(chalk.gray("─".repeat(50)));
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 打印信息
|
|
110
|
+
* @param {string} label - 标签
|
|
111
|
+
* @param {string} value - 值
|
|
112
|
+
*/
|
|
113
|
+
info(label, value) {
|
|
114
|
+
console.log(chalk.gray(" ●"), chalk.white(label), chalk.cyan(value));
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 打印成功消息
|
|
119
|
+
* @param {string} text - 消息文本
|
|
120
|
+
*/
|
|
121
|
+
success(text) {
|
|
122
|
+
console.log(chalk.green(" ✓"), chalk.white(text));
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* 打印警告消息
|
|
127
|
+
* @param {string} text - 警告文本
|
|
128
|
+
*/
|
|
129
|
+
warn(text) {
|
|
130
|
+
console.log(chalk.yellow(" ⚠"), chalk.white(text));
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 打印错误消息
|
|
135
|
+
* @param {string} text - 错误文本
|
|
136
|
+
*/
|
|
137
|
+
error(text) {
|
|
138
|
+
console.error(chalk.red(" ✗"), chalk.white(text));
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* 打印文件路径
|
|
143
|
+
* @param {string} filePath - 文件路径
|
|
144
|
+
* @param {string} projectRoot - 项目根目录(可选)
|
|
145
|
+
*/
|
|
146
|
+
file(filePath, projectRoot = getProjectRoot()) {
|
|
147
|
+
const relativePath = getRelativePath(filePath, projectRoot);
|
|
148
|
+
console.log(chalk.gray(" +"), chalk.green(relativePath));
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 打印分隔线
|
|
153
|
+
*/
|
|
154
|
+
divider() {
|
|
155
|
+
console.log(chalk.gray("─".repeat(50)));
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 打印空行
|
|
160
|
+
*/
|
|
161
|
+
newline() {
|
|
162
|
+
console.log();
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// ============================================================================
|
|
167
|
+
// 命令行工具
|
|
168
|
+
// ============================================================================
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 跨平台检测命令是否存在
|
|
172
|
+
* @param {string} command - 要检测的命令
|
|
173
|
+
* @returns {boolean} 命令是否存在
|
|
174
|
+
*/
|
|
175
|
+
function commandExists(command) {
|
|
176
|
+
const isWindows = os.platform() === "win32";
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
if (isWindows) {
|
|
180
|
+
try {
|
|
181
|
+
execSync(`where ${command}`, { stdio: "ignore", shell: "cmd.exe" });
|
|
182
|
+
return true;
|
|
183
|
+
} catch {
|
|
184
|
+
execSync(`${command} --version`, {
|
|
185
|
+
stdio: "ignore",
|
|
186
|
+
shell: "cmd.exe",
|
|
187
|
+
timeout: 3000
|
|
188
|
+
});
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
} else {
|
|
192
|
+
try {
|
|
193
|
+
execSync(`which ${command}`, { stdio: "ignore" });
|
|
194
|
+
return true;
|
|
195
|
+
} catch {
|
|
196
|
+
execSync(`${command} --version`, {
|
|
197
|
+
stdio: "ignore",
|
|
198
|
+
timeout: 3000
|
|
199
|
+
});
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
} catch {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ============================================================================
|
|
209
|
+
// 字符串工具
|
|
210
|
+
// ============================================================================
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 将连字符命名转换为驼峰命名
|
|
214
|
+
* @param {string} str - 连字符字符串
|
|
215
|
+
* @returns {string} 驼峰命名字符串
|
|
216
|
+
*/
|
|
217
|
+
function toCamelCase(str) {
|
|
218
|
+
return str.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* 将驼峰命名转换为连字符命名
|
|
223
|
+
* @param {string} str - 驼峰字符串
|
|
224
|
+
* @returns {string} 连字符命名字符串
|
|
225
|
+
*/
|
|
226
|
+
function toKebabCase(str) {
|
|
227
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ============================================================================
|
|
231
|
+
// 导出
|
|
232
|
+
// ============================================================================
|
|
233
|
+
|
|
234
|
+
export {
|
|
235
|
+
getProjectRoot,
|
|
236
|
+
getRelativePath,
|
|
237
|
+
ensureDirectoryExists,
|
|
238
|
+
copyRecursive,
|
|
239
|
+
cleanDirectory,
|
|
240
|
+
logger,
|
|
241
|
+
commandExists,
|
|
242
|
+
toCamelCase,
|
|
243
|
+
toKebabCase
|
|
244
|
+
};
|