按 U-Claw-海外化改造方案.md 与 范围决策记录.md 实施。这是 fork,不回上游: 海外版删掉的正是上游的中国市场默认值。 阶段 0 地基 - 下载源全部改国际:脚本/CI 61 处 + lockfile 880 条 npmmirror URL 归零 (lockfile 那 880 条是 npm 的 resolved 字段,脚本层参数化根本绕不过它) - 移除 install.ps1 里三个第三方 GitHub 加速代理,bundle 改直连 + SHA256 校验 (原来只检查"文件大于 1MB"就解压运行) - 技能内容与分发分离:skills/manifest.json 单一来源,install.sh 1170→658 行、 install.ps1 721→546 行,两者技能内容归零 实测原来是三份不一致:skills-cn 完整、install.sh 约 40%、install.ps1 约 17%, 且 7 个通用技能只有 U 盘版有 —— 一键安装的用户一个能用的技能都没有 - Node 版本三种(v22.14/16/22.1)统一,新建 NODE_VERSION 单一来源 - Config 页三份合一。portable/Config.html 用根相对路径调 API 却只从 file:// 打开, 保存功能已静默失效两个月;现缩为 120 行重定向壳 - 测试接入 CI(此前 node --test 无人运行,所有断言形同虚设) 阶段 1 双语可用 - 浏览器侧 i18n:JSON 为源、生成经典 script(file:// 下 fetch 本地 JSON 被拦) 语言跟盘走不跟机器走:启动器写 data/.openclaw/locale.js - 8 处硬编码 lang="zh-CN" 归零,data-i18n 覆盖 213 处,词条 en/zh 各 279 条 - B3 单框 Key:12 张模型卡 → 一个输入框,前缀识别 provider, 服务端 /api/test-key 发 1-token 请求实测,错误映射成人话 Key 填错到得知:从"直到对话失败"降到 ≤1 秒 - 区域格式 SG:DD/MM/YYYY、12 小时、S$、Asia/Singapore (ICU 在 en-SG 下把 SGD 渲染成裸 $,与美元无法区分,故自行拼 S$) - README 内容分叉而非翻译,§1.3 证据清单逐条清零 阶段 2 降门槛 - 启动逻辑上移 lib/start.mjs:Windows-Start.bat 220→28 行、 Mac-Start.command 235→33 行 修掉 Mac 侧两个 bug:控制台端口硬编码 18788(回落时打开死页)、 微信插件从未在 Mac 上安装 - U 盘根目录 23 → 3 个可点文件,其余进 advanced/ - 首启向导:语言 → 用途(7 角色,manifest 驱动)→ 密钥,答过不再问 - 三档界面,Simple 档隐藏一切技术名词 - 自动自愈:启动失败先自查自修,修不好导出脱敏诊断包 (Doctor 从"用户要知道去点的工具"变成后台机制) 阶段 3 技能库 - 19 个英文技能,planned 归零。sg-weather / sg-transport 的端点均实测过 - SkillHub 从 56 张手写第三方卡片改为 manifest 生成:703→125 行,中文归零 其他 - origin.json 收拢所有运行时地址,tests/origin.test.mjs 保证迁移不会漏 - portable/ 下用户可见中文归零(由断言保证) - 82 项测试 未验证(本机无 Windows / 无 pwsh): - install.ps1、setup.ps1 约 210 行改动从未经 PowerShell 解析器 - 完整启动路径仅在假 node + 假 openclaw 上冒烟 - 8 个 .bat 的盘根推导仅静态断言 详见 U盘实测清单.md 受阻: - 隐藏黑窗口 —— 需代码签名证书(.vbs 已被 Windows 弃用,替代方案都要签名) - 场景卡 —— OpenClaw 上游 Dashboard 无预填 prompt 接口 - 官网 36 条 —— 上游 2026-04-14 拆到私有仓库,无权限
This commit is contained in:
75
portable/lib/i18n/build-messages.mjs
Normal file
75
portable/lib/i18n/build-messages.mjs
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env node
|
||||
// Generates lib/i18n/messages.js from lib/messages/*.json.
|
||||
//
|
||||
// The launcher (node) reads the JSON directly; the pages cannot, because they
|
||||
// are opened from file:// where fetching local JSON is blocked. Rather than
|
||||
// maintain two copies of every string, the JSON stays the source of truth and
|
||||
// this emits a plain <script> the pages can load.
|
||||
//
|
||||
// node lib/i18n/build-messages.mjs [--check]
|
||||
//
|
||||
// --check exits non-zero if the generated file is stale, for CI.
|
||||
|
||||
import { readFileSync, writeFileSync, readdirSync, existsSync } from 'node:fs';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
const messagesDir = join(here, '..', 'messages');
|
||||
const outputPath = join(here, 'messages.js');
|
||||
const skillsOutputPath = join(here, 'skills-data.js');
|
||||
|
||||
const catalogues = {};
|
||||
for (const file of readdirSync(messagesDir).sort()) {
|
||||
if (!file.endsWith('.json')) continue;
|
||||
catalogues[file.replace(/\.json$/, '')] = JSON.parse(readFileSync(join(messagesDir, file), 'utf8'));
|
||||
}
|
||||
|
||||
const generated = `/* GENERATED FILE — do not edit.
|
||||
* Source: lib/messages/*.json
|
||||
* Regenerate: node lib/i18n/build-messages.mjs
|
||||
*
|
||||
* Exists because pages opened from file:// cannot fetch local JSON.
|
||||
*/
|
||||
window.UCLAW_I18N_MESSAGES = ${JSON.stringify(catalogues, null, 2)};
|
||||
`;
|
||||
|
||||
// The skill catalogue travels the same way and for the same reason: SkillHub is
|
||||
// opened from file://, where fetching manifest.json is blocked.
|
||||
function buildSkillsData() {
|
||||
for (const candidate of [join(here, '..', '..', 'skills'), join(here, '..', '..', '..', 'skills')]) {
|
||||
if (!existsSync(join(candidate, 'manifest.json'))) continue;
|
||||
const manifest = JSON.parse(readFileSync(join(candidate, 'manifest.json'), 'utf8'));
|
||||
return `/* GENERATED FILE — do not edit.
|
||||
* Source: skills/manifest.json
|
||||
* Regenerate: node lib/i18n/build-messages.mjs
|
||||
*/
|
||||
window.UCLAW_SKILLS = ${JSON.stringify({
|
||||
personas: manifest.personas,
|
||||
skills: manifest.skills
|
||||
.filter((s) => s.status === 'shipping')
|
||||
.map(({ id, categories, personas, emoji }) => ({ id, categories, personas, emoji })),
|
||||
}, null, 2)};
|
||||
`;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const generatedSkills = buildSkillsData();
|
||||
|
||||
if (process.argv.includes('--check')) {
|
||||
let current = null;
|
||||
try { current = readFileSync(outputPath, 'utf8'); } catch { /* not generated yet */ }
|
||||
let currentSkills = null;
|
||||
try { currentSkills = readFileSync(skillsOutputPath, 'utf8'); } catch { /* not generated yet */ }
|
||||
if (current !== generated || (generatedSkills && currentSkills !== generatedSkills)) {
|
||||
process.stderr.write('lib/i18n generated files are stale — run: node lib/i18n/build-messages.mjs\n');
|
||||
process.exit(1);
|
||||
}
|
||||
process.stdout.write('generated files are up to date\n');
|
||||
} else {
|
||||
writeFileSync(outputPath, generated, 'utf8');
|
||||
if (generatedSkills) writeFileSync(skillsOutputPath, generatedSkills, 'utf8');
|
||||
const count = Object.keys(catalogues).map((l) => `${l}:${Object.keys(catalogues[l]).length}`).join(' ');
|
||||
process.stdout.write(`wrote lib/i18n/messages.js (${count})\n`);
|
||||
}
|
||||
152
portable/lib/i18n/i18n.js
Normal file
152
portable/lib/i18n/i18n.js
Normal file
@@ -0,0 +1,152 @@
|
||||
/* U-Claw browser-side i18n.
|
||||
*
|
||||
* A classic script, not an ES module, and the catalogue is a script rather than
|
||||
* JSON on purpose: these pages are opened from file:// (the launcher opens
|
||||
* loading.html with a file:// URL, Welcome.html links to its siblings), and from
|
||||
* a file:// origin both fetch() and ES-module imports of local files are blocked.
|
||||
* That is the exact bug that left the old Config.html silently broken. A plain
|
||||
* <script src> tag still works.
|
||||
*
|
||||
* Load order on a page:
|
||||
* <script src="data/.openclaw/locale.js"></script> optional, written by the launcher
|
||||
* <script src="lib/i18n/messages.js"></script>
|
||||
* <script src="lib/i18n/i18n.js"></script>
|
||||
*
|
||||
* Then mark text with data-i18n="key". Attributes use data-i18n-attr="placeholder:key".
|
||||
* The HTML keeps English as its literal fallback, so a missing catalogue degrades
|
||||
* to readable English instead of raw keys.
|
||||
*/
|
||||
(function (global) {
|
||||
'use strict';
|
||||
|
||||
var SUPPORTED = ['en', 'zh-CN'];
|
||||
var FALLBACK = 'en';
|
||||
|
||||
function normalise(tag) {
|
||||
if (!tag) return null;
|
||||
var lower = String(tag).toLowerCase();
|
||||
if (lower.indexOf('zh') === 0) return 'zh-CN';
|
||||
if (lower.indexOf('en') === 0) return 'en';
|
||||
return null;
|
||||
}
|
||||
|
||||
// The language travels with the drive, not the machine: someone who set the
|
||||
// drive up in Chinese and plugs it into a colleague's English Windows should
|
||||
// still see Chinese. The launcher writes data/.openclaw/locale.js on startup;
|
||||
// ?lang= is the manual override, and the browser language is the last resort.
|
||||
function resolveLocale() {
|
||||
var fromQuery = null;
|
||||
try {
|
||||
fromQuery = new URLSearchParams(global.location.search).get('lang');
|
||||
} catch (e) { /* older browser or opaque URL */ }
|
||||
|
||||
return normalise(fromQuery)
|
||||
|| normalise(global.UCLAW_LOCALE)
|
||||
|| normalise(global.navigator && global.navigator.language)
|
||||
|| FALLBACK;
|
||||
}
|
||||
|
||||
var locale = resolveLocale();
|
||||
var catalogues = global.UCLAW_I18N_MESSAGES || {};
|
||||
var active = catalogues[SUPPORTED.indexOf(locale) === -1 ? FALLBACK : locale] || {};
|
||||
var fallback = catalogues[FALLBACK] || {};
|
||||
|
||||
function t(key, vars) {
|
||||
var template = active[key];
|
||||
if (template === undefined) template = fallback[key];
|
||||
if (template === undefined) return key;
|
||||
if (!vars) return template;
|
||||
return template.replace(/\{(\w+)\}/g, function (match, name) {
|
||||
return Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : match;
|
||||
});
|
||||
}
|
||||
|
||||
function apply(root) {
|
||||
var scope = root || global.document;
|
||||
|
||||
scope.querySelectorAll('[data-i18n]').forEach(function (node) {
|
||||
var value = t(node.getAttribute('data-i18n'));
|
||||
// Keep the literal in the HTML when a key has no translation, rather than
|
||||
// replacing readable English with the key name.
|
||||
if (value !== node.getAttribute('data-i18n')) node.textContent = value;
|
||||
});
|
||||
|
||||
scope.querySelectorAll('[data-i18n-attr]').forEach(function (node) {
|
||||
node.getAttribute('data-i18n-attr').split(',').forEach(function (pair) {
|
||||
var parts = pair.split(':');
|
||||
if (parts.length !== 2) return;
|
||||
var attr = parts[0].trim();
|
||||
var value = t(parts[1].trim());
|
||||
if (value !== parts[1].trim()) node.setAttribute(attr, value);
|
||||
});
|
||||
});
|
||||
|
||||
global.document.documentElement.lang = locale;
|
||||
}
|
||||
|
||||
// Region defaults for Singapore. The old pages assumed China: Asia/Shanghai,
|
||||
// YYYY-MM-DD, 24-hour, ¥. SG uses DD/MM/YYYY (neither Chinese nor American),
|
||||
// 12-hour with am/pm, and S$.
|
||||
var REGION = {
|
||||
en: { locale: 'en-SG', timeZone: 'Asia/Singapore', currency: 'SGD', hour12: true },
|
||||
'zh-CN': { locale: 'zh-SG', timeZone: 'Asia/Singapore', currency: 'SGD', hour12: true },
|
||||
};
|
||||
|
||||
function region() {
|
||||
return REGION[locale] || REGION.en;
|
||||
}
|
||||
|
||||
function formatDate(date) {
|
||||
var r = region();
|
||||
try {
|
||||
return new Intl.DateTimeFormat(r.locale, {
|
||||
timeZone: r.timeZone, day: '2-digit', month: '2-digit', year: 'numeric',
|
||||
}).format(date);
|
||||
} catch (e) {
|
||||
return String(date);
|
||||
}
|
||||
}
|
||||
|
||||
function formatTime(date) {
|
||||
var r = region();
|
||||
try {
|
||||
return new Intl.DateTimeFormat(r.locale, {
|
||||
timeZone: r.timeZone, hour: 'numeric', minute: '2-digit', hour12: r.hour12,
|
||||
}).format(date);
|
||||
} catch (e) {
|
||||
return String(date);
|
||||
}
|
||||
}
|
||||
|
||||
// ICU renders SGD as a bare "$" in an en-SG locale, which is ambiguous next to
|
||||
// USD prices. Prices are written S$ throughout the product, so format the
|
||||
// number with Intl and put the symbol on ourselves rather than depending on
|
||||
// whichever ICU build the browser or Node happens to ship.
|
||||
function formatMoney(amount) {
|
||||
var r = region();
|
||||
try {
|
||||
return 'S$' + new Intl.NumberFormat(r.locale, {
|
||||
minimumFractionDigits: 2, maximumFractionDigits: 2,
|
||||
}).format(amount);
|
||||
} catch (e) {
|
||||
return 'S$' + amount;
|
||||
}
|
||||
}
|
||||
|
||||
global.UClawI18n = {
|
||||
locale: locale,
|
||||
supported: SUPPORTED,
|
||||
t: t,
|
||||
apply: apply,
|
||||
region: region,
|
||||
formatDate: formatDate,
|
||||
formatTime: formatTime,
|
||||
formatMoney: formatMoney,
|
||||
};
|
||||
|
||||
if (global.document.readyState === 'loading') {
|
||||
global.document.addEventListener('DOMContentLoaded', function () { apply(); });
|
||||
} else {
|
||||
apply();
|
||||
}
|
||||
})(window);
|
||||
566
portable/lib/i18n/messages.js
Normal file
566
portable/lib/i18n/messages.js
Normal file
@@ -0,0 +1,566 @@
|
||||
/* GENERATED FILE — do not edit.
|
||||
* Source: lib/messages/*.json
|
||||
* Regenerate: node lib/i18n/build-messages.mjs
|
||||
*
|
||||
* Exists because pages opened from file:// cannot fetch local JSON.
|
||||
*/
|
||||
window.UCLAW_I18N_MESSAGES = {
|
||||
"en": {
|
||||
"start.banner": "U-Claw · Portable AI Agent",
|
||||
"start.node_version": "Node.js {version}",
|
||||
"start.quarantine_removing": "Clearing the macOS security flag…",
|
||||
"start.cache_local": "Cache on local disk: {path}",
|
||||
"start.config_migrating": "Bringing your old settings across…",
|
||||
"start.config_migrated": "Settings moved over.",
|
||||
"start.config_creating": "First run — setting things up…",
|
||||
"start.config_created": "Ready.",
|
||||
"start.deps_preparing": "Getting things ready — about 20 seconds.",
|
||||
"start.deps_slow_drive": "This drive is slow, so it may take a few minutes. You can leave it running.",
|
||||
"start.deps_done": "Ready.",
|
||||
"start.no_proxy": "Connecting directly to your model host: {hosts}",
|
||||
"start.wechat_installing": "Installing the WeChat plugin…",
|
||||
"start.wechat_installed": "WeChat plugin installed.",
|
||||
"start.config_center_starting": "Starting the Control Panel…",
|
||||
"start.config_center_port": "Control Panel is on port {port}.",
|
||||
"start.port_in_use": "Port {port} is busy, trying the next one…",
|
||||
"start.gateway_starting": "Starting U-Claw on port {port}…",
|
||||
"start.opening_screen": "Opening the start screen…",
|
||||
"start.opening_config": "Opening the Control Panel…",
|
||||
"start.running_title": "U-Claw is running",
|
||||
"start.running_dashboard": "Dashboard: {url}",
|
||||
"start.running_config": "Control Panel: {url}",
|
||||
"start.running_hint": "Keep this window open while you use U-Claw. Press Ctrl+C to stop.",
|
||||
"start.first_run_wait": "First run from a USB drive takes 30–90 seconds while components unpack. The Control Panel is already open so you can pick a model and paste a key.",
|
||||
"start.stopped": "U-Claw stopped.",
|
||||
"start.exited_unexpectedly": "U-Claw closed on its own (code {code}).",
|
||||
"error.node_missing.what": "A file U-Claw needs is missing from the drive.",
|
||||
"error.node_missing.why": "This usually means the copy onto the USB drive did not finish.",
|
||||
"error.node_missing.action": "Copy the U-Claw folder onto the drive again, or run setup.sh to rebuild it.",
|
||||
"error.unsupported_arch.what": "This Mac's processor is not supported ({arch}).",
|
||||
"error.unsupported_arch.why": "U-Claw ships builds for Apple Silicon and Intel Macs only.",
|
||||
"error.unsupported_arch.action": "Try U-Claw on a different computer.",
|
||||
"error.no_port.what": "U-Claw could not find a free port to start on.",
|
||||
"error.no_port.why": "Ports {from}–{to} are all in use — U-Claw may already be running.",
|
||||
"error.no_port.action": "Close any window already running U-Claw and start it again.",
|
||||
"error.deps_failed.what": "U-Claw could not finish getting ready.",
|
||||
"error.deps_failed.why": "The download did not complete — usually a dropped network connection.",
|
||||
"error.deps_failed.action": "Check your Wi-Fi and start U-Claw again.",
|
||||
"error.press_enter": "Press Enter to close this window.",
|
||||
"loading.title": "Starting U-Claw",
|
||||
"loading.starting": "Starting U-Claw…",
|
||||
"loading.first_run": "First run from a USB drive unpacks the bundled components. Give it a moment — you will be told when it is ready.",
|
||||
"loading.waiting_gateway": "Waiting for U-Claw to come up…",
|
||||
"loading.ready": "U-Claw is ready",
|
||||
"loading.choose_next": "Pick what to do next — start chatting, or set up your model and channels first.",
|
||||
"loading.open_dashboard": "🚀 Start chatting",
|
||||
"loading.open_settings": "⚙️ Settings",
|
||||
"loading.settings_hint": "Add or change your API key, and connect chat apps.",
|
||||
"loading.no_model_hint": "No model set up yet? Open Settings first to add a key.",
|
||||
"loading.slow_drive_note": "A slow drive usually takes 30–90 seconds. If nothing happens for a long time, open Settings:",
|
||||
"loading.elapsed": "Waited {seconds}s",
|
||||
"loading.taking_long": "This is taking longer than usual. You can open Settings while you wait:",
|
||||
"welcome.title": "U-Claw — Getting Started",
|
||||
"welcome.subtitle": "Your AI assistant on a USB drive · three steps",
|
||||
"welcome.quickstart": "Quick start",
|
||||
"welcome.step1_title": "1. Start U-Claw",
|
||||
"welcome.step1_desc": "Double-click the file for your computer:",
|
||||
"welcome.step2_title": "2. Add a key",
|
||||
"welcome.step2_desc": "Settings opens on its own the first time. You need one API key to get going — Google Gemini is the easiest to obtain: sign in with a Google account, no card required.",
|
||||
"welcome.step2_link": "Get a free Gemini key →",
|
||||
"welcome.step3_title": "3. Start talking",
|
||||
"welcome.step3_desc": "Once the key is saved, the chat window opens by itself. That is it.",
|
||||
"welcome.portable_note": "✅ Your settings and history stay in the data/ folder on the drive, so they travel with you between Mac and Windows.",
|
||||
"welcome.models_title": "Which model?",
|
||||
"welcome.model_claude": "Best all-rounder",
|
||||
"welcome.model_gpt": "Most widely used",
|
||||
"welcome.model_gemini": "Free tier, easiest signup",
|
||||
"welcome.model_local": "Offline · nothing leaves this machine",
|
||||
"welcome.models_more": "More options, including SEA-LION for Malay, Tamil and Singlish, are in Settings.",
|
||||
"welcome.trouble_title": "Something not working?",
|
||||
"welcome.trouble_lead": "💡 Run the check-up tool",
|
||||
"welcome.trouble_desc": "If U-Claw will not start, double-click:",
|
||||
"welcome.open_settings": "Open Settings",
|
||||
"welcome.open_docs": "Documentation",
|
||||
"nav.title": "U-Claw — Start here",
|
||||
"nav.tagline": "Portable AI agent — plug in and go",
|
||||
"nav.status_off": "U-Claw is not running",
|
||||
"nav.open_console": "Open it →",
|
||||
"nav.quickstart": "Quick start",
|
||||
"nav.doubleclick": "Double-click",
|
||||
"nav.step2": "Settings opens by itself the first time — pick a model and paste your key.",
|
||||
"nav.mac_gatekeeper": "⚠️ If macOS says the developer cannot be verified: right-click the file, then choose Open.",
|
||||
"nav.config_shortcut": "📝 You can also double-click Config.html — it takes you to the settings page.",
|
||||
"nav.win_smartscreen": "⚠️ If Windows shows a security warning: click More info, then Run anyway.",
|
||||
"nav.everything": "Everything else",
|
||||
"nav.menu_opens": "for the full menu:",
|
||||
"nav.g_settings": "Settings",
|
||||
"nav.g_settings_d": "Model, key and chat apps",
|
||||
"nav.g_checkup": "Check-up",
|
||||
"nav.g_checkup_d": "Finds and fixes common problems",
|
||||
"nav.g_backup": "Backup",
|
||||
"nav.g_backup_d": "Save settings and memory in one click",
|
||||
"nav.g_skills": "Skills",
|
||||
"nav.g_skills_d": "Browse what U-Claw can do",
|
||||
"nav.g_system": "System info",
|
||||
"nav.g_system_d": "Version, port, running state",
|
||||
"nav.g_cli": "Command line",
|
||||
"nav.g_cli_d": "For advanced use",
|
||||
"nav.models_title": "Models you can use",
|
||||
"nav.model_sealion": "Malay, Tamil and Singlish",
|
||||
"nav.model_local": "Local model",
|
||||
"nav.model_more": "More",
|
||||
"nav.model_more_d": "Others are listed in Settings",
|
||||
"nav.more_title": "More",
|
||||
"nav.link_guide": "Getting started",
|
||||
"nav.link_guide_d": "The three-step walkthrough",
|
||||
"nav.link_skills": "Skills",
|
||||
"nav.link_skills_d": "Browse what U-Claw can do",
|
||||
"nav.link_contact": "Contact",
|
||||
"nav.link_site": "Website",
|
||||
"nav.status_on": "U-Claw is running on port {port}",
|
||||
"nav.status_off_hint": "U-Claw is not running — double-click the start file first",
|
||||
"key.page_title": "U-Claw Settings",
|
||||
"key.page_subtitle": "Paste an API key and you are done.",
|
||||
"key.checking": "Checking…",
|
||||
"key.step_key": "Your key",
|
||||
"key.step_done": "Done",
|
||||
"key.heading": "Paste your API key",
|
||||
"key.desc": "U-Claw works out the rest by itself. Your key is saved on this drive only — it is never uploaded anywhere.",
|
||||
"key.placeholder": "sk-…",
|
||||
"key.show": "Show",
|
||||
"key.hide": "Hide",
|
||||
"key.continue": "Continue →",
|
||||
"key.checking_key": "Checking this key…",
|
||||
"key.ok": "✓ {provider} · connected in {ms}ms",
|
||||
"key.custom_provider": "Your endpoint",
|
||||
"key.no_key_title": "Do not have a key yet?",
|
||||
"key.no_key_desc": "Google Gemini is the quickest to get: sign in with a Google account, no card needed, and there is a free tier.",
|
||||
"key.get_gemini": "🔑 Get a free Gemini key",
|
||||
"key.get_openrouter": "🔑 OpenRouter — one key for many models",
|
||||
"key.advanced": "Advanced — set the endpoint manually",
|
||||
"key.base_url": "API endpoint",
|
||||
"key.model_name": "Model name",
|
||||
"key.advanced_hint": "Only needed for a self-hosted or unlisted provider. Leave blank to let U-Claw decide.",
|
||||
"key.saved": "Saved.",
|
||||
"key.err_empty": "Paste a key to continue.",
|
||||
"key.err_not_checked": "Hold on — still checking that key.",
|
||||
"key.err_rejected": "That key was not accepted. Check you copied all of it — keys are long and easy to cut short.",
|
||||
"key.err_quota": "This key has run out of credit. Top it up with your provider, or paste a different key.",
|
||||
"key.err_offline": "Cannot reach the internet. Check your Wi-Fi and try again.",
|
||||
"key.err_timeout": "The provider did not answer in time. Try again in a moment.",
|
||||
"key.err_model": "That key works, but the model it points to was not found. Set the model name under Advanced.",
|
||||
"key.err_provider_down": "The provider is having trouble right now. Try again shortly.",
|
||||
"key.err_unrecognised": "This key is not one U-Claw recognises. Fill in the endpoint and model under Advanced.",
|
||||
"key.err_unknown": "Could not check that key. Try again, or use Advanced to set the endpoint yourself.",
|
||||
"key.err_save": "Could not save. Make sure the drive is still plugged in, then try again.",
|
||||
"hub.title": "U-Claw Skills",
|
||||
"done.title": "You are set up",
|
||||
"done.subtitle": "Your model and key are saved on this drive.",
|
||||
"done.open": "🚀 Start chatting",
|
||||
"done.restart_note": "Chat app settings are saved now and take effect after U-Claw restarts.",
|
||||
"done.change_key": "Change model or key",
|
||||
"done.view_config": "View config file",
|
||||
"ch.title": "📱 Connect a chat app (optional)",
|
||||
"ch.desc": "Click a card to fill it in, or skip this entirely.",
|
||||
"ch.whatsapp_d": "Talk to U-Claw from WhatsApp",
|
||||
"ch.whatsapp_warning": "⚠️ This uses an unofficial protocol. Your WhatsApp account can be banned for it. Do not connect a number you rely on.",
|
||||
"ch.whatsapp_number": "Phone number",
|
||||
"ch.telegram_d": "Talk to U-Claw from Telegram",
|
||||
"ch.telegram_get": "→ Get one from @BotFather",
|
||||
"ch.slack_d": "Talk to U-Claw from your workspace",
|
||||
"ch.slack_get": "→ Create an app at api.slack.com",
|
||||
"ch.discord_d": "Talk to U-Claw from Discord",
|
||||
"ch.discord_get": "→ Create an app in the Discord developer portal",
|
||||
"ch.china_group": "Chat apps used mainly in China",
|
||||
"ch.wechat_d": "Scan a QR code to link a personal WeChat account",
|
||||
"ch.wechat_start": "Click this card to show the QR code",
|
||||
"ch.saved": "Chat app settings saved.",
|
||||
"ch.err_save": "Could not save the chat app settings. Check the drive is still plugged in.",
|
||||
"info.layout_title": "What is on the drive",
|
||||
"info.layout_desc": "How the folders are organised",
|
||||
"info.skills": "Skills",
|
||||
"info.skills_d": "Drop a SKILL.md in here and it is picked up automatically",
|
||||
"info.app": "Runtime",
|
||||
"info.app_d": "Node.js and the OpenClaw core",
|
||||
"info.data": "Your data",
|
||||
"info.data_d": "Your key and chat history. Stays on this drive.",
|
||||
"info.feedback_title": "Found a problem?",
|
||||
"info.feedback_desc": "U-Claw is open source. Report anything that breaks on GitHub — nothing is collected or uploaded from your machine automatically.",
|
||||
"info.feedback_link": "→ Open an issue on GitHub",
|
||||
"wx.getting_qr": "Fetching the QR code…",
|
||||
"wx.scan": "Scan the code above with WeChat",
|
||||
"wx.qr_failed": "Could not fetch the QR code",
|
||||
"wx.connected": "✅ WeChat connected",
|
||||
"wx.account": "Account",
|
||||
"wx.restart_needed": "One more thing: restart U-Claw (close it and open it again) before WeChat will work.",
|
||||
"wx.connected_toast": "WeChat connected. It works after U-Claw restarts.",
|
||||
"wx.qr_refreshed": "The code refreshed — scan it again",
|
||||
"wx.confirm_on_phone": "Scanned. Confirm on your phone…",
|
||||
"wx.qr_expired": "That code expired.",
|
||||
"wx.qr_retry": "Get a new one",
|
||||
"wx.failed": "Could not connect",
|
||||
"info.read_config_failed": "Could not read the config file:",
|
||||
"status.running": "U-Claw is running on port {port}",
|
||||
"status.open_dashboard": "Open it →",
|
||||
"status.not_running": "U-Claw is not running — start it with Windows-Start.bat or Mac-Start.command",
|
||||
"key.which_model": "Which model?",
|
||||
"start.opening_language": "Asking which language to use…",
|
||||
"persona.title": "What will you mostly use this for?",
|
||||
"persona.subtitle": "This sets up the right tools for you. You can change it later, and picking more than one is fine.",
|
||||
"persona.continue": "Continue →",
|
||||
"persona.skip": "Skip this",
|
||||
"persona.saving": "Setting things up…",
|
||||
"persona.err_offline": "U-Claw is not running yet. Start it, then open this page again.",
|
||||
"persona.err_save": "Could not save that. Check the drive is still plugged in, then try again.",
|
||||
"persona.developer": "Writing code",
|
||||
"persona.admin": "Documents and email",
|
||||
"persona.sales": "Talking to customers",
|
||||
"persona.marketing": "Content and social",
|
||||
"persona.finance": "Numbers and spreadsheets",
|
||||
"persona.boss": "Running a business",
|
||||
"persona.general": "Just having a look",
|
||||
"start.opening_persona": "Asking what you will use it for…",
|
||||
"tier.label": "How much do you want to see?",
|
||||
"tier.simple": "Just the essentials",
|
||||
"tier.standard": "A bit more control",
|
||||
"tier.expert": "Everything",
|
||||
"tier.changed_simple": "Switched to the simple view — advanced options are hidden.",
|
||||
"tier.changed_standard": "Switched to the standard view — you can now change models and connect more chat apps.",
|
||||
"tier.changed_expert": "Switched to the full view — everything is visible, including the config file.",
|
||||
"start.checking": "Something went wrong — checking…",
|
||||
"start.repaired": "Fixed. Trying again.",
|
||||
"start.diagnostics_written": "A report of what happened was saved to: {path}",
|
||||
"start.diagnostics_hint": "API keys have been removed from it. Send it to help@u-claw.org if you want a hand.",
|
||||
"skill.excel-helper.name": "Spreadsheets",
|
||||
"skill.excel-helper.desc": "Formulas, pivot tables, charts, cleaning messy data",
|
||||
"skill.word-writer.name": "Documents",
|
||||
"skill.word-writer.desc": "Reports, proposals, CVs — drafting and formatting",
|
||||
"skill.ppt-designer.name": "Slide decks",
|
||||
"skill.ppt-designer.desc": "Structure, layout and speaker notes",
|
||||
"skill.pdf-toolkit.name": "PDF tools",
|
||||
"skill.pdf-toolkit.desc": "Merge, split, extract text — all on this machine",
|
||||
"skill.image-compress.name": "Images",
|
||||
"skill.image-compress.desc": "Shrink, resize and convert — nothing is uploaded",
|
||||
"skill.qrcode-maker.name": "QR codes",
|
||||
"skill.qrcode-maker.desc": "Links, text and WiFi details, generated offline",
|
||||
"skill.web-to-markdown.name": "Save a web page",
|
||||
"skill.web-to-markdown.desc": "Turn any article into clean Markdown",
|
||||
"skill.linkedin-post.name": "LinkedIn posts",
|
||||
"skill.linkedin-post.desc": "Hooks and structure, without the LinkedIn voice",
|
||||
"skill.x-poster.name": "Posts for X",
|
||||
"skill.x-poster.desc": "Short posts and threads that stand on their own",
|
||||
"skill.tiktok-script.name": "TikTok scripts",
|
||||
"skill.tiktok-script.desc": "Hooks that survive the first second",
|
||||
"skill.youtube-script.name": "YouTube scripts",
|
||||
"skill.youtube-script.desc": "Titles, the first 30 seconds, and chapters",
|
||||
"skill.medium-writer.name": "Articles",
|
||||
"skill.medium-writer.desc": "Long-form structure, and cutting the padding",
|
||||
"skill.email-campaign.name": "Email campaigns",
|
||||
"skill.email-campaign.desc": "Subject lines, one clear ask, PDPA-safe",
|
||||
"skill.web-search.name": "Web search",
|
||||
"skill.web-search.desc": "Find current information and read the sources",
|
||||
"skill.sg-weather.name": "Singapore weather",
|
||||
"skill.sg-weather.desc": "Forecast by area and air quality, from NEA",
|
||||
"skill.sea-translate.name": "SEA translation",
|
||||
"skill.sea-translate.desc": "English, Chinese, Malay, Tamil — and register",
|
||||
"skill.claude-helper.name": "Better answers",
|
||||
"skill.claude-helper.desc": "How to ask, and when to check the answer",
|
||||
"skill.sg-transport.name": "Singapore transport",
|
||||
"skill.sg-transport.desc": "Bus arrivals, MRT alerts, carpark lots",
|
||||
"skill.meeting-notes.name": "Meeting notes",
|
||||
"skill.meeting-notes.desc": "Decisions and owners, ready to send",
|
||||
"cat.office": "Office",
|
||||
"cat.data": "Data",
|
||||
"cat.writing": "Writing",
|
||||
"cat.files": "Files",
|
||||
"cat.research": "Research",
|
||||
"cat.social": "Social",
|
||||
"cat.video": "Video",
|
||||
"cat.language": "Language",
|
||||
"cat.local": "Singapore",
|
||||
"cat.ai": "Using AI",
|
||||
"hub.lede": "These are on this drive already. Just ask for what you want — you do not have to name the skill.",
|
||||
"hub.all": "All",
|
||||
"hub.none": "Nothing in this category.",
|
||||
"hub.add_note": "Skills live in the skills/ folder on this drive. Dropping a SKILL.md in there adds one."
|
||||
},
|
||||
"zh-CN": {
|
||||
"start.banner": "U-Claw · 便携 AI 助手",
|
||||
"start.node_version": "Node.js {version}",
|
||||
"start.quarantine_removing": "正在解除 macOS 安全限制…",
|
||||
"start.cache_local": "缓存已放在本机硬盘:{path}",
|
||||
"start.config_migrating": "正在迁移你原来的设置…",
|
||||
"start.config_migrated": "设置已迁移。",
|
||||
"start.config_creating": "第一次使用,正在准备…",
|
||||
"start.config_created": "准备好了。",
|
||||
"start.deps_preparing": "正在准备,约 20 秒。",
|
||||
"start.deps_slow_drive": "这个 U 盘比较慢,可能要几分钟,放着就行。",
|
||||
"start.deps_done": "准备好了。",
|
||||
"start.no_proxy": "将直连你的模型地址:{hosts}",
|
||||
"start.wechat_installing": "正在安装微信插件…",
|
||||
"start.wechat_installed": "微信插件已安装。",
|
||||
"start.config_center_starting": "正在启动控制台…",
|
||||
"start.config_center_port": "控制台端口:{port}",
|
||||
"start.port_in_use": "端口 {port} 被占用,换下一个…",
|
||||
"start.gateway_starting": "正在启动 U-Claw,端口 {port}…",
|
||||
"start.opening_screen": "正在打开启动页…",
|
||||
"start.opening_config": "正在打开控制台…",
|
||||
"start.running_title": "U-Claw 已启动",
|
||||
"start.running_dashboard": "对话界面:{url}",
|
||||
"start.running_config": "控制台: {url}",
|
||||
"start.running_hint": "使用期间请不要关闭这个窗口。按 Ctrl+C 停止。",
|
||||
"start.first_run_wait": "第一次从 U 盘启动需要 30–90 秒解压组件。控制台已经打开,可以先选模型、填密钥。",
|
||||
"start.stopped": "U-Claw 已停止。",
|
||||
"start.exited_unexpectedly": "U-Claw 自己退出了(代码 {code})。",
|
||||
"error.node_missing.what": "U 盘里少了一个 U-Claw 需要的文件。",
|
||||
"error.node_missing.why": "通常是拷贝到 U 盘时没有复制完整。",
|
||||
"error.node_missing.action": "把 U-Claw 文件夹重新拷贝一遍,或运行 setup.sh 重建。",
|
||||
"error.unsupported_arch.what": "这台 Mac 的处理器不受支持({arch})。",
|
||||
"error.unsupported_arch.why": "U-Claw 只提供 Apple Silicon 和 Intel Mac 的版本。",
|
||||
"error.unsupported_arch.action": "换一台电脑试试。",
|
||||
"error.no_port.what": "U-Claw 找不到可用的端口来启动。",
|
||||
"error.no_port.why": "{from}–{to} 都被占用了 —— 可能已经有一个 U-Claw 在运行。",
|
||||
"error.no_port.action": "关掉已经在运行的那个窗口,再启动一次。",
|
||||
"error.deps_failed.what": "U-Claw 没能准备完成。",
|
||||
"error.deps_failed.why": "下载没有完成,通常是网络中断了。",
|
||||
"error.deps_failed.action": "检查一下 Wi-Fi,然后重新启动 U-Claw。",
|
||||
"error.press_enter": "按回车关闭这个窗口。",
|
||||
"loading.title": "正在启动 U-Claw",
|
||||
"loading.starting": "U-Claw 正在启动…",
|
||||
"loading.first_run": "第一次从 U 盘启动需要展开内置组件,稍等片刻,就绪后会提示你下一步。",
|
||||
"loading.waiting_gateway": "正在等待 U-Claw 启动…",
|
||||
"loading.ready": "U-Claw 已就绪",
|
||||
"loading.choose_next": "选择下一步 —— 直接开始聊天,或先去配置模型和渠道。",
|
||||
"loading.open_dashboard": "🚀 开始聊天",
|
||||
"loading.open_settings": "⚙️ 设置",
|
||||
"loading.settings_hint": "填写或更换 API 密钥,连接聊天软件。",
|
||||
"loading.no_model_hint": "还没配过模型?先打开设置填一个密钥。",
|
||||
"loading.slow_drive_note": "慢 U 盘首次启动通常 30–90 秒。如果迟迟没反应,可以先打开设置:",
|
||||
"loading.elapsed": "已等待 {seconds} 秒",
|
||||
"loading.taking_long": "启动比平时慢,可以先打开设置:",
|
||||
"welcome.title": "U-Claw 使用指南",
|
||||
"welcome.subtitle": "装在 U 盘里的 AI 助手 · 三步开始",
|
||||
"welcome.quickstart": "快速开始",
|
||||
"welcome.step1_title": "1. 启动 U-Claw",
|
||||
"welcome.step1_desc": "双击你电脑对应的那个文件:",
|
||||
"welcome.step2_title": "2. 填一个密钥",
|
||||
"welcome.step2_desc": "第一次启动会自动打开设置页。你需要一个 API 密钥才能开始 —— Google Gemini 最容易拿到:用 Google 账号登录即可,不用绑卡。",
|
||||
"welcome.step2_link": "去领取免费的 Gemini 密钥 →",
|
||||
"welcome.step3_title": "3. 开始对话",
|
||||
"welcome.step3_desc": "密钥保存后,对话窗口会自己打开。就这样。",
|
||||
"welcome.portable_note": "✅ 你的设置和聊天记录都存在盘上的 data/ 目录里,跟着盘走,Mac 和 Windows 通用。",
|
||||
"welcome.models_title": "用哪个模型?",
|
||||
"welcome.model_claude": "综合最强",
|
||||
"welcome.model_gpt": "用的人最多",
|
||||
"welcome.model_gemini": "有免费额度,注册最简单",
|
||||
"welcome.model_local": "离线 · 数据不出本机",
|
||||
"welcome.models_more": "更多选择在设置里,包括适合马来语、泰米尔语和 Singlish 的 SEA-LION。",
|
||||
"welcome.trouble_title": "遇到问题?",
|
||||
"welcome.trouble_lead": "💡 运行检查工具",
|
||||
"welcome.trouble_desc": "如果 U-Claw 启动不了,双击:",
|
||||
"welcome.open_settings": "打开设置",
|
||||
"welcome.open_docs": "查看文档",
|
||||
"nav.title": "U-Claw 启动导航",
|
||||
"nav.tagline": "便携 AI 助手 — 插上就能用",
|
||||
"nav.status_off": "U-Claw 尚未运行",
|
||||
"nav.open_console": "打开它 →",
|
||||
"nav.quickstart": "快速启动",
|
||||
"nav.doubleclick": "双击",
|
||||
"nav.step2": "第一次启动会自动打开设置页 —— 选一个模型,把密钥粘进去。",
|
||||
"nav.mac_gatekeeper": "⚠️ 如果 macOS 提示「无法验证开发者」:右键点这个文件,选「打开」。",
|
||||
"nav.config_shortcut": "📝 也可以双击 Config.html,它会带你到设置页。",
|
||||
"nav.win_smartscreen": "⚠️ 如果 Windows 弹安全警告:点「更多信息」,再点「仍要运行」。",
|
||||
"nav.everything": "其他功能",
|
||||
"nav.menu_opens": "打开完整菜单:",
|
||||
"nav.g_settings": "设置",
|
||||
"nav.g_settings_d": "模型、密钥和聊天软件",
|
||||
"nav.g_checkup": "检查修复",
|
||||
"nav.g_checkup_d": "找出并修复常见问题",
|
||||
"nav.g_backup": "备份",
|
||||
"nav.g_backup_d": "一键保存设置和记忆",
|
||||
"nav.g_skills": "技能",
|
||||
"nav.g_skills_d": "看看 U-Claw 能做什么",
|
||||
"nav.g_system": "系统信息",
|
||||
"nav.g_system_d": "版本、端口、运行状态",
|
||||
"nav.g_cli": "命令行",
|
||||
"nav.g_cli_d": "给进阶用户",
|
||||
"nav.models_title": "可以用的模型",
|
||||
"nav.model_sealion": "马来语、泰米尔语和 Singlish",
|
||||
"nav.model_local": "本地模型",
|
||||
"nav.model_more": "更多",
|
||||
"nav.model_more_d": "其他模型在设置里",
|
||||
"nav.more_title": "更多",
|
||||
"nav.link_guide": "使用指南",
|
||||
"nav.link_guide_d": "三步上手",
|
||||
"nav.link_skills": "技能",
|
||||
"nav.link_skills_d": "看看 U-Claw 能做什么",
|
||||
"nav.link_contact": "联系我们",
|
||||
"nav.link_site": "官网",
|
||||
"nav.status_on": "U-Claw 正在运行(端口 {port})",
|
||||
"nav.status_off_hint": "U-Claw 尚未运行 —— 请先双击启动文件",
|
||||
"key.page_title": "U-Claw 设置",
|
||||
"key.page_subtitle": "粘贴一个 API 密钥就可以了。",
|
||||
"key.checking": "检测中…",
|
||||
"key.step_key": "填密钥",
|
||||
"key.step_done": "完成",
|
||||
"key.heading": "粘贴你的 API 密钥",
|
||||
"key.desc": "剩下的 U-Claw 自己搞定。密钥只保存在这个 U 盘上,不会上传到任何地方。",
|
||||
"key.placeholder": "sk-…",
|
||||
"key.show": "显示",
|
||||
"key.hide": "隐藏",
|
||||
"key.continue": "继续 →",
|
||||
"key.checking_key": "正在检查这个密钥…",
|
||||
"key.ok": "✓ {provider} · 连接成功,用时 {ms} 毫秒",
|
||||
"key.custom_provider": "你的地址",
|
||||
"key.no_key_title": "还没有密钥?",
|
||||
"key.no_key_desc": "Google Gemini 最容易拿到:用 Google 账号登录即可,不用绑卡,还有免费额度。",
|
||||
"key.get_gemini": "🔑 领取免费的 Gemini 密钥",
|
||||
"key.get_openrouter": "🔑 OpenRouter —— 一个密钥用多种模型",
|
||||
"key.advanced": "高级 —— 手动填写接口地址",
|
||||
"key.base_url": "接口地址",
|
||||
"key.model_name": "模型名称",
|
||||
"key.advanced_hint": "只有自建或未收录的服务才需要填。留空则由 U-Claw 自动判断。",
|
||||
"key.saved": "已保存。",
|
||||
"key.err_empty": "先粘贴一个密钥。",
|
||||
"key.err_not_checked": "稍等,密钥还在检查中。",
|
||||
"key.err_rejected": "这个密钥没被接受。检查一下是不是没复制全 —— 密钥很长,容易少一截。",
|
||||
"key.err_quota": "这个密钥的额度用完了。去服务商那边充值,或者换一个密钥。",
|
||||
"key.err_offline": "连不上网络。检查一下 Wi-Fi 再试。",
|
||||
"key.err_timeout": "服务商没有及时响应。过一会儿再试。",
|
||||
"key.err_model": "密钥是好的,但它指向的模型没找到。在「高级」里填写模型名称。",
|
||||
"key.err_provider_down": "服务商那边现在有问题。稍后再试。",
|
||||
"key.err_unrecognised": "U-Claw 认不出这个密钥。请在「高级」里填写接口地址和模型名称。",
|
||||
"key.err_unknown": "没能检查这个密钥。再试一次,或者在「高级」里自己填接口地址。",
|
||||
"key.err_save": "保存失败。确认 U 盘还插着,然后再试一次。",
|
||||
"hub.title": "U-Claw 技能",
|
||||
"done.title": "配置完成",
|
||||
"done.subtitle": "模型和密钥已保存在这个 U 盘上。",
|
||||
"done.open": "🚀 开始聊天",
|
||||
"done.restart_note": "聊天软件的设置已保存,重启 U-Claw 后生效。",
|
||||
"done.change_key": "换模型或密钥",
|
||||
"done.view_config": "查看配置文件",
|
||||
"ch.title": "📱 连接聊天软件(可选)",
|
||||
"ch.desc": "点卡片展开填写,也可以直接跳过。",
|
||||
"ch.whatsapp_d": "用 WhatsApp 和 U-Claw 对话",
|
||||
"ch.whatsapp_warning": "⚠️ 这里用的是非官方协议,你的 WhatsApp 账号可能因此被封。不要接入你离不开的号码。",
|
||||
"ch.whatsapp_number": "手机号",
|
||||
"ch.telegram_d": "用 Telegram 和 U-Claw 对话",
|
||||
"ch.telegram_get": "→ 从 @BotFather 获取",
|
||||
"ch.slack_d": "在工作区里和 U-Claw 对话",
|
||||
"ch.slack_get": "→ 在 api.slack.com 创建应用",
|
||||
"ch.discord_d": "用 Discord 和 U-Claw 对话",
|
||||
"ch.discord_get": "→ 在 Discord 开发者后台创建应用",
|
||||
"ch.china_group": "主要在中国使用的聊天软件",
|
||||
"ch.wechat_d": "扫码接入个人微信",
|
||||
"ch.wechat_start": "点这张卡片开始扫码",
|
||||
"ch.saved": "聊天软件设置已保存。",
|
||||
"ch.err_save": "聊天软件设置没能保存。确认 U 盘还插着。",
|
||||
"info.layout_title": "U 盘里有什么",
|
||||
"info.layout_desc": "文件夹是怎么组织的",
|
||||
"info.skills": "技能",
|
||||
"info.skills_d": "把 SKILL.md 放进来就会自动加载",
|
||||
"info.app": "运行时",
|
||||
"info.app_d": "Node.js 和 OpenClaw 核心",
|
||||
"info.data": "你的数据",
|
||||
"info.data_d": "密钥和聊天记录,只留在这个盘上。",
|
||||
"info.feedback_title": "遇到问题?",
|
||||
"info.feedback_desc": "U-Claw 是开源项目。出问题欢迎去 GitHub 提 Issue —— 我们不会自动收集或上传你机器上的任何东西。",
|
||||
"info.feedback_link": "→ 去 GitHub 提 Issue",
|
||||
"wx.getting_qr": "正在获取二维码…",
|
||||
"wx.scan": "请用微信扫描上方二维码",
|
||||
"wx.qr_failed": "获取二维码失败",
|
||||
"wx.connected": "✅ 微信已连接",
|
||||
"wx.account": "账号",
|
||||
"wx.restart_needed": "还差一步:重启 U-Claw(关掉再打开),微信才能用。",
|
||||
"wx.connected_toast": "微信已连接,重启 U-Claw 后生效。",
|
||||
"wx.qr_refreshed": "二维码已刷新,请重新扫码",
|
||||
"wx.confirm_on_phone": "已扫码,请在手机上确认…",
|
||||
"wx.qr_expired": "二维码已过期。",
|
||||
"wx.qr_retry": "重新获取",
|
||||
"wx.failed": "连接失败",
|
||||
"info.read_config_failed": "读取配置文件失败:",
|
||||
"status.running": "U-Claw 正在运行,端口 {port}",
|
||||
"status.open_dashboard": "打开它 →",
|
||||
"status.not_running": "U-Claw 尚未运行 —— 请先运行 Windows-Start.bat 或 Mac-Start.command",
|
||||
"key.which_model": "用哪个模型?",
|
||||
"start.opening_language": "正在询问使用哪种语言…",
|
||||
"persona.title": "你主要用它做什么?",
|
||||
"persona.subtitle": "这会帮你把合适的工具装好。以后可以改,也可以多选。",
|
||||
"persona.continue": "继续 →",
|
||||
"persona.skip": "跳过",
|
||||
"persona.saving": "正在准备…",
|
||||
"persona.err_offline": "U-Claw 还没启动。先启动它,再打开这个页面。",
|
||||
"persona.err_save": "没能保存。确认 U 盘还插着,然后再试一次。",
|
||||
"persona.developer": "写代码",
|
||||
"persona.admin": "写文档、发邮件",
|
||||
"persona.sales": "跟客户打交道",
|
||||
"persona.marketing": "做内容、发社交媒体",
|
||||
"persona.finance": "算数、做表格",
|
||||
"persona.boss": "管公司",
|
||||
"persona.general": "先随便看看",
|
||||
"start.opening_persona": "正在询问你主要用它做什么…",
|
||||
"tier.label": "想看到多少?",
|
||||
"tier.simple": "只要最基本的",
|
||||
"tier.standard": "多一点控制",
|
||||
"tier.expert": "全部",
|
||||
"tier.changed_simple": "已切换到简洁模式 —— 高级选项已隐藏。",
|
||||
"tier.changed_standard": "已切换到标准模式 —— 现在可以换模型、接更多聊天软件了。",
|
||||
"tier.changed_expert": "已切换到完整模式 —— 所有东西都可见,包括配置文件。",
|
||||
"start.checking": "出了点问题,正在检查…",
|
||||
"start.repaired": "已修复,重试一次。",
|
||||
"start.diagnostics_written": "已把情况记录到:{path}",
|
||||
"start.diagnostics_hint": "里面的密钥已被去掉。需要帮忙的话,把它发到 help@u-claw.org。",
|
||||
"skill.excel-helper.name": "表格",
|
||||
"skill.excel-helper.desc": "公式、透视表、图表、清洗乱数据",
|
||||
"skill.word-writer.name": "文档",
|
||||
"skill.word-writer.desc": "报告、方案、简历 —— 起草和排版",
|
||||
"skill.ppt-designer.name": "幻灯片",
|
||||
"skill.ppt-designer.desc": "结构、版式和演讲要点",
|
||||
"skill.pdf-toolkit.name": "PDF 工具",
|
||||
"skill.pdf-toolkit.desc": "合并、拆分、提取文字 —— 全在本机",
|
||||
"skill.image-compress.name": "图片",
|
||||
"skill.image-compress.desc": "压缩、改尺寸、转格式 —— 不上传",
|
||||
"skill.qrcode-maker.name": "二维码",
|
||||
"skill.qrcode-maker.desc": "网址、文本、WiFi,离线生成",
|
||||
"skill.web-to-markdown.name": "保存网页",
|
||||
"skill.web-to-markdown.desc": "把文章转成干净的 Markdown",
|
||||
"skill.linkedin-post.name": "LinkedIn 帖子",
|
||||
"skill.linkedin-post.desc": "钩子和结构,不要那股 LinkedIn 腔",
|
||||
"skill.x-poster.name": "X 帖子",
|
||||
"skill.x-poster.desc": "能独立成立的短帖和 thread",
|
||||
"skill.tiktok-script.name": "TikTok 脚本",
|
||||
"skill.tiktok-script.desc": "扛得住第一秒的钩子",
|
||||
"skill.youtube-script.name": "YouTube 脚本",
|
||||
"skill.youtube-script.desc": "标题、前 30 秒、章节",
|
||||
"skill.medium-writer.name": "长文",
|
||||
"skill.medium-writer.desc": "长文结构,以及怎么删水分",
|
||||
"skill.email-campaign.name": "邮件营销",
|
||||
"skill.email-campaign.desc": "标题、一个明确的 ask、符合 PDPA",
|
||||
"skill.web-search.name": "网页搜索",
|
||||
"skill.web-search.desc": "找当前信息并真的读来源",
|
||||
"skill.sg-weather.name": "新加坡天气",
|
||||
"skill.sg-weather.desc": "按区预报和空气质量,来自 NEA",
|
||||
"skill.sea-translate.name": "东南亚翻译",
|
||||
"skill.sea-translate.desc": "英 / 中 / 马来 / 泰米尔 —— 以及语域",
|
||||
"skill.claude-helper.name": "问得更好",
|
||||
"skill.claude-helper.desc": "怎么问,以及什么时候该核对答案",
|
||||
"skill.sg-transport.name": "新加坡交通",
|
||||
"skill.sg-transport.desc": "巴士到站、地铁故障、停车位",
|
||||
"skill.meeting-notes.name": "会议纪要",
|
||||
"skill.meeting-notes.desc": "决定和负责人,写完就能发",
|
||||
"cat.office": "办公",
|
||||
"cat.data": "数据",
|
||||
"cat.writing": "写作",
|
||||
"cat.files": "文件",
|
||||
"cat.research": "资料",
|
||||
"cat.social": "社交媒体",
|
||||
"cat.video": "视频",
|
||||
"cat.language": "语言",
|
||||
"cat.local": "新加坡",
|
||||
"cat.ai": "用好 AI",
|
||||
"hub.lede": "这些已经在盘上了。直接说你想做什么就行,不用记技能名。",
|
||||
"hub.all": "全部",
|
||||
"hub.none": "这个分类下暂时没有。",
|
||||
"hub.add_note": "技能放在盘上的 skills/ 目录里。丢一个 SKILL.md 进去就多一个。"
|
||||
}
|
||||
};
|
||||
281
portable/lib/i18n/skills-data.js
Normal file
281
portable/lib/i18n/skills-data.js
Normal file
@@ -0,0 +1,281 @@
|
||||
/* GENERATED FILE — do not edit.
|
||||
* Source: skills/manifest.json
|
||||
* Regenerate: node lib/i18n/build-messages.mjs
|
||||
*/
|
||||
window.UCLAW_SKILLS = {
|
||||
"personas": [
|
||||
{
|
||||
"id": "developer",
|
||||
"tier": "expert",
|
||||
"emoji": "💻",
|
||||
"channel": null
|
||||
},
|
||||
{
|
||||
"id": "admin",
|
||||
"tier": "simple",
|
||||
"emoji": "📝",
|
||||
"channel": null
|
||||
},
|
||||
{
|
||||
"id": "sales",
|
||||
"tier": "simple",
|
||||
"emoji": "💬",
|
||||
"channel": "whatsapp"
|
||||
},
|
||||
{
|
||||
"id": "marketing",
|
||||
"tier": "standard",
|
||||
"emoji": "🎨",
|
||||
"channel": null
|
||||
},
|
||||
{
|
||||
"id": "finance",
|
||||
"tier": "standard",
|
||||
"emoji": "📊",
|
||||
"channel": null
|
||||
},
|
||||
{
|
||||
"id": "boss",
|
||||
"tier": "simple",
|
||||
"emoji": "👔",
|
||||
"channel": null
|
||||
},
|
||||
{
|
||||
"id": "general",
|
||||
"tier": "simple",
|
||||
"emoji": "🤷",
|
||||
"channel": null
|
||||
}
|
||||
],
|
||||
"skills": [
|
||||
{
|
||||
"id": "excel-helper",
|
||||
"categories": [
|
||||
"office",
|
||||
"data"
|
||||
],
|
||||
"personas": [
|
||||
"admin",
|
||||
"finance",
|
||||
"boss",
|
||||
"general"
|
||||
],
|
||||
"emoji": "📊"
|
||||
},
|
||||
{
|
||||
"id": "word-writer",
|
||||
"categories": [
|
||||
"office",
|
||||
"writing"
|
||||
],
|
||||
"personas": [
|
||||
"admin",
|
||||
"sales",
|
||||
"boss",
|
||||
"general"
|
||||
],
|
||||
"emoji": "📝"
|
||||
},
|
||||
{
|
||||
"id": "ppt-designer",
|
||||
"categories": [
|
||||
"office",
|
||||
"writing"
|
||||
],
|
||||
"personas": [
|
||||
"admin",
|
||||
"sales",
|
||||
"marketing",
|
||||
"boss"
|
||||
],
|
||||
"emoji": "📽️"
|
||||
},
|
||||
{
|
||||
"id": "pdf-toolkit",
|
||||
"categories": [
|
||||
"files"
|
||||
],
|
||||
"personas": [
|
||||
"admin",
|
||||
"finance",
|
||||
"general"
|
||||
],
|
||||
"emoji": "📄"
|
||||
},
|
||||
{
|
||||
"id": "image-compress",
|
||||
"categories": [
|
||||
"files"
|
||||
],
|
||||
"personas": [
|
||||
"marketing",
|
||||
"general"
|
||||
],
|
||||
"emoji": "🖼️"
|
||||
},
|
||||
{
|
||||
"id": "qrcode-maker",
|
||||
"categories": [
|
||||
"files"
|
||||
],
|
||||
"personas": [
|
||||
"marketing",
|
||||
"sales",
|
||||
"general"
|
||||
],
|
||||
"emoji": "🔳"
|
||||
},
|
||||
{
|
||||
"id": "web-to-markdown",
|
||||
"categories": [
|
||||
"research"
|
||||
],
|
||||
"personas": [
|
||||
"developer",
|
||||
"marketing",
|
||||
"general"
|
||||
],
|
||||
"emoji": "🔗"
|
||||
},
|
||||
{
|
||||
"id": "linkedin-post",
|
||||
"categories": [
|
||||
"social"
|
||||
],
|
||||
"personas": [
|
||||
"marketing",
|
||||
"sales",
|
||||
"boss"
|
||||
],
|
||||
"emoji": "💼"
|
||||
},
|
||||
{
|
||||
"id": "x-poster",
|
||||
"categories": [
|
||||
"social"
|
||||
],
|
||||
"personas": [
|
||||
"marketing"
|
||||
],
|
||||
"emoji": "🐦"
|
||||
},
|
||||
{
|
||||
"id": "tiktok-script",
|
||||
"categories": [
|
||||
"social",
|
||||
"video"
|
||||
],
|
||||
"personas": [
|
||||
"marketing"
|
||||
],
|
||||
"emoji": "🎬"
|
||||
},
|
||||
{
|
||||
"id": "youtube-script",
|
||||
"categories": [
|
||||
"social",
|
||||
"video"
|
||||
],
|
||||
"personas": [
|
||||
"marketing"
|
||||
],
|
||||
"emoji": "📺"
|
||||
},
|
||||
{
|
||||
"id": "medium-writer",
|
||||
"categories": [
|
||||
"writing"
|
||||
],
|
||||
"personas": [
|
||||
"marketing",
|
||||
"developer"
|
||||
],
|
||||
"emoji": "✍️"
|
||||
},
|
||||
{
|
||||
"id": "email-campaign",
|
||||
"categories": [
|
||||
"writing",
|
||||
"social"
|
||||
],
|
||||
"personas": [
|
||||
"marketing",
|
||||
"sales"
|
||||
],
|
||||
"emoji": "✉️"
|
||||
},
|
||||
{
|
||||
"id": "web-search",
|
||||
"categories": [
|
||||
"research"
|
||||
],
|
||||
"personas": [
|
||||
"developer",
|
||||
"marketing",
|
||||
"general",
|
||||
"finance"
|
||||
],
|
||||
"emoji": "🔍"
|
||||
},
|
||||
{
|
||||
"id": "sg-weather",
|
||||
"categories": [
|
||||
"local"
|
||||
],
|
||||
"personas": [
|
||||
"general",
|
||||
"sales"
|
||||
],
|
||||
"emoji": "🌦️"
|
||||
},
|
||||
{
|
||||
"id": "sea-translate",
|
||||
"categories": [
|
||||
"language"
|
||||
],
|
||||
"personas": [
|
||||
"sales",
|
||||
"admin",
|
||||
"marketing",
|
||||
"general",
|
||||
"boss"
|
||||
],
|
||||
"emoji": "🌏"
|
||||
},
|
||||
{
|
||||
"id": "claude-helper",
|
||||
"categories": [
|
||||
"ai"
|
||||
],
|
||||
"personas": [
|
||||
"developer",
|
||||
"finance"
|
||||
],
|
||||
"emoji": "🤖"
|
||||
},
|
||||
{
|
||||
"id": "sg-transport",
|
||||
"categories": [
|
||||
"local"
|
||||
],
|
||||
"personas": [
|
||||
"general",
|
||||
"sales"
|
||||
],
|
||||
"emoji": "🚇"
|
||||
},
|
||||
{
|
||||
"id": "meeting-notes",
|
||||
"categories": [
|
||||
"writing"
|
||||
],
|
||||
"personas": [
|
||||
"sales",
|
||||
"admin",
|
||||
"boss",
|
||||
"finance"
|
||||
],
|
||||
"emoji": "🗒️"
|
||||
}
|
||||
]
|
||||
};
|
||||
Reference in New Issue
Block a user