zigmini 0.9.0-beta.3 → 1.0.0-beta.2
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.ko.md +36 -4
- package/README.md +36 -4
- package/assets/agent/gateway-rules.md +29 -19
- package/assets/android/zigmini.apk +0 -0
- package/assets/android/zigmini.apk.json +3 -3
- package/assets/build.json +1 -1
- package/docs/manual.ko.md +60 -11
- package/docs/manual.md +61 -12
- package/host/omo-bridge/agent-control.ts +274 -0
- package/host/omo-bridge/bridge.ts +1 -1
- package/host/omo-bridge/continuity-control.ts +1 -1
- package/host/omo-bridge/task-control.ts +26 -16
- package/host/omo-check/patches/omo-5.1.51-compaction-long-context.patch +92 -0
- package/host/omo-check/patches/omo-5.1.51-compaction-port.patch +2635 -0
- package/host/omo-check/patches/omo-5.1.51-compaction-recovery.patch +911 -0
- package/host/omo-check/patches/omo-5.1.51-gateway-port.manifest.json +363 -0
- package/host/omo-check/patches/omo-5.1.51-provider-failover.patch +50 -0
- package/host/omo-check/patches/omo-5.1.51-provider-port.patch +441 -0
- package/host/omo-check/patches/omo-5.1.51-rpc-port.patch +799 -0
- package/host/omo-check/patches/omo-5.1.51-runtime-compat.patch +31 -0
- package/package.json +3 -2
- package/src/agent/api.ts +215 -0
- package/src/agent/definition.ts +177 -0
- package/src/agent/fields.ts +42 -0
- package/src/agent/files.ts +192 -0
- package/src/agent/legacy-files.ts +46 -0
- package/src/agent/list.ts +21 -0
- package/src/agent-rules.ts +97 -13
- package/src/approvals.ts +6 -1
- package/src/cli/doctor.ts +7 -0
- package/src/cli/main.ts +38 -0
- package/src/cli/messages.ts +10 -2
- package/src/cli/rotate-main.ts +2 -1
- package/src/cli/rules.ts +70 -0
- package/src/cli/scan.ts +414 -0
- package/src/cli/security-import.ts +155 -0
- package/src/compact.ts +22 -0
- package/src/decisions.ts +6 -4
- package/src/engine/compat.json +3 -3
- package/src/engine/index.ts +1 -0
- package/src/engine/schema-guard.ts +12 -4
- package/src/engine/sdk.ts +8 -0
- package/src/formal-verification.ts +366 -0
- package/src/gc.ts +37 -6
- package/src/hub.ts +339 -79
- package/src/main.ts +95 -9
- package/src/maintenance.ts +1 -1
- package/src/manual.ts +9 -2
- package/src/profile-prompt.ts +73 -0
- package/src/profile.ts +33 -10
- package/src/protocol.ts +11 -2
- package/src/question-notifications.ts +4 -1
- package/src/reply-notifications.ts +7 -1
- package/src/repo-security-setting.ts +33 -0
- package/src/runtime/paths.ts +16 -0
- package/src/security/baseline.ts +172 -0
- package/src/security/dex-strings.ts +242 -0
- package/src/security/repo-scan.ts +369 -0
- package/src/security/revision-probe.ts +144 -0
- package/src/security/terms.ts +97 -0
- package/src/security-allow.ts +1 -0
- package/src/security-baseline.ts +113 -0
- package/src/security-check.ts +91 -16
- package/src/server-text.ts +38 -0
- package/src/store.ts +142 -16
- package/src/transcript.ts +7 -1
- package/src/ui-language.ts +33 -0
- package/src/update/check.ts +7 -3
- package/src/update/handoff-system.ts +24 -16
- package/src/update/handoff.ts +23 -12
- package/src/update/helper.ts +72 -36
- package/src/update/request.ts +46 -30
- package/src/update/state.ts +21 -11
- package/src/update/strategy.ts +12 -5
- package/src/update/target.ts +32 -15
- package/src/usage.ts +43 -20
- package/src/version.ts +39 -16
- package/src/voice/agents.ts +8 -3
- package/src/voice/install.ts +29 -18
- package/src/work-watch.ts +40 -18
- package/web/agent-icon.js +15 -9
- package/web/agents.d.ts +201 -0
- package/web/agents.js +813 -0
- package/web/app-download.js +32 -19
- package/web/app.js +1407 -278
- package/web/autocopy.js +6 -1
- package/web/boot.js +27 -8
- package/web/commands.js +20 -11
- package/web/decisions.js +70 -49
- package/web/devlog.js +25 -19
- package/web/diagram.js +8 -3
- package/web/enroll.js +43 -22
- package/web/gc.js +32 -19
- package/web/i18n/agent-icon.js +24 -0
- package/web/i18n/agents.js +48 -0
- package/web/i18n/app-download.js +26 -0
- package/web/i18n/autocopy.js +5 -0
- package/web/i18n/boot.js +24 -0
- package/web/i18n/commands.js +34 -0
- package/web/i18n/decisions.js +24 -0
- package/web/i18n/devlog.js +60 -0
- package/web/i18n/diagram.js +12 -0
- package/web/i18n/enroll.js +22 -0
- package/web/i18n/gc.js +38 -0
- package/web/i18n/lastsent.js +10 -0
- package/web/i18n/main.d.ts +4 -0
- package/web/i18n/main.js +527 -0
- package/web/i18n/manual.d.ts +4 -0
- package/web/i18n/manual.js +14 -0
- package/web/i18n/memo.js +30 -0
- package/web/i18n/notifications.js +16 -0
- package/web/i18n/profile.js +13 -0
- package/web/i18n/reference.js +26 -0
- package/web/i18n/security-inbox.js +40 -0
- package/web/i18n/slash.js +38 -0
- package/web/i18n/turn-stats.js +5 -0
- package/web/i18n/update.js +42 -0
- package/web/i18n/voice.js +28 -0
- package/web/i18n/wake.js +16 -0
- package/web/i18n/workid.js +10 -0
- package/web/i18n/workstatus.js +20 -0
- package/web/i18n.d.ts +20 -0
- package/web/i18n.js +63 -0
- package/web/index.html +156 -96
- package/web/lastsent.js +9 -4
- package/web/manual.d.ts +1 -1
- package/web/manual.js +11 -5
- package/web/memo.js +18 -13
- package/web/notifications.js +12 -7
- package/web/profile.js +42 -17
- package/web/reference.js +20 -15
- package/web/security-inbox.d.ts +18 -1
- package/web/security-inbox.js +173 -4
- package/web/slash.js +23 -13
- package/web/style.css +132 -3
- package/web/tooltip.js +5 -2
- package/web/turn-stats.js +6 -2
- package/web/update.js +31 -23
- package/web/voice.js +18 -8
- package/web/wake.d.ts +4 -0
- package/web/wake.js +7 -3
- package/web/workid.js +12 -2
- package/web/workstatus.js +36 -32
package/web/gc.js
CHANGED
|
@@ -1,20 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
import { onLanguageChange, registerStrings, t } from "./i18n.js";
|
|
2
|
+
import strings from "./i18n/gc.js";
|
|
3
|
+
|
|
4
|
+
registerStrings(strings);
|
|
5
|
+
|
|
6
|
+
// Improvement 66 (plan Todo 24): the settings cleanup area. Only decisions live here, with no DOM, so test/unit/gc-web.test.ts
|
|
2
7
|
// can exercise them. The gateway lists candidates at GET /api/gc and cleans only the ids the user ticked.
|
|
3
8
|
|
|
4
9
|
export const GC_PATH = "/api/gc";
|
|
5
10
|
export const GC_CLEAN_PATH = "/api/gc/clean";
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
export let KIND_LABELS;
|
|
12
|
+
export let GC_EMPTY_LINE = t("gc.empty");
|
|
13
|
+
export let GC_FAILED_LINE = t("gc.failed");
|
|
14
|
+
function refreshStrings() {
|
|
15
|
+
KIND_LABELS = Object.freeze({
|
|
16
|
+
"db-backup": t("gc.dbBackup"),
|
|
17
|
+
"omo-version": t("gc.omoVersion"),
|
|
18
|
+
"update-file": t("gc.updateFile"),
|
|
19
|
+
"temp-dir": t("gc.tempDir"),
|
|
20
|
+
"rpc-daemon": t("gc.rpcDaemon"),
|
|
21
|
+
"agent-trash": t("gc.agentTrash"),
|
|
22
|
+
});
|
|
23
|
+
GC_EMPTY_LINE = t("gc.empty");
|
|
24
|
+
GC_FAILED_LINE = t("gc.failed");
|
|
25
|
+
}
|
|
26
|
+
refreshStrings();
|
|
27
|
+
onLanguageChange(refreshStrings);
|
|
15
28
|
|
|
16
29
|
export function formatBytes(bytes) {
|
|
17
|
-
if (typeof bytes !== "number" || !Number.isFinite(bytes) || bytes < 0) return "
|
|
30
|
+
if (typeof bytes !== "number" || !Number.isFinite(bytes) || bytes < 0) return t("gc.unknownSize");
|
|
18
31
|
const units = [["GB", 1024 ** 3], ["MB", 1024 ** 2], ["KB", 1024]];
|
|
19
32
|
for (const [unit, size] of units) if (bytes >= size) return `${(bytes / size).toFixed(bytes >= 10 * size ? 0 : 1)}${unit}`;
|
|
20
33
|
return `${bytes}B`;
|
|
@@ -22,30 +35,30 @@ export function formatBytes(bytes) {
|
|
|
22
35
|
|
|
23
36
|
export function formatAge(ms) {
|
|
24
37
|
const minutes = Math.floor(Math.max(0, ms) / 60_000);
|
|
25
|
-
if (minutes >= 1440) return
|
|
26
|
-
if (minutes >= 60) return
|
|
27
|
-
return
|
|
38
|
+
if (minutes >= 1440) return t("gc.ageDays", { count: Math.floor(minutes / 1440) });
|
|
39
|
+
if (minutes >= 60) return t("gc.ageHours", { count: Math.floor(minutes / 60) });
|
|
40
|
+
return t("gc.ageMinutes", { count: minutes });
|
|
28
41
|
}
|
|
29
42
|
|
|
30
43
|
export function gcView(report) {
|
|
31
|
-
if (report === null || typeof report !== "object" || !Array.isArray(report.candidates)) return { summary:
|
|
44
|
+
if (report === null || typeof report !== "object" || !Array.isArray(report.candidates)) return { summary: t("gc.failed"), rows: [], error: true };
|
|
32
45
|
const rows = report.candidates.map((c) => ({
|
|
33
46
|
id: c.id,
|
|
34
47
|
label: `${KIND_LABELS[c.kind] ?? c.kind} · ${c.target.slice(c.target.lastIndexOf("/") + 1)}`,
|
|
35
48
|
sub: `${c.reason} · ${formatAge(c.ageMs)} · ${formatBytes(c.bytes)}`,
|
|
36
49
|
title: c.target,
|
|
37
50
|
}));
|
|
38
|
-
const summary = rows.length === 0 ?
|
|
51
|
+
const summary = rows.length === 0 ? t("gc.empty") : t("gc.summary", { count: rows.length, bytes: formatBytes(report.bytes) });
|
|
39
52
|
return { summary, rows, error: false };
|
|
40
53
|
}
|
|
41
54
|
|
|
42
|
-
// Improvement 142: the
|
|
55
|
+
// Improvement 142: the select-all box beside the summary. It is hidden with no rows, checked when every row is ticked and
|
|
43
56
|
// indeterminate when only some are.
|
|
44
57
|
export function selectAllState(ticked, total) {
|
|
45
58
|
return { hidden: total === 0, checked: total > 0 && ticked === total, indeterminate: ticked > 0 && ticked < total };
|
|
46
59
|
}
|
|
47
60
|
|
|
48
|
-
// A click on
|
|
61
|
+
// A click on select-all ticks every row unless every row was already ticked; then it clears them all.
|
|
49
62
|
export function selectAllTarget(ticked, total) {
|
|
50
63
|
return ticked < total;
|
|
51
64
|
}
|
|
@@ -58,5 +71,5 @@ export function cleanResultLine(result) {
|
|
|
58
71
|
const cleaned = result?.cleaned?.length ?? 0;
|
|
59
72
|
const failed = result?.failed?.length ?? 0;
|
|
60
73
|
const missing = result?.missing?.length ?? 0;
|
|
61
|
-
return
|
|
74
|
+
return t("gc.cleanResult", { cleaned, failed: failed > 0 ? t("gc.failedCount", { count: failed }) : "", missing: missing > 0 ? t("gc.missingCount", { count: missing }) : "" });
|
|
62
75
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
"icon.problem.type": "Only PNG, JPEG and WebP images can be used.",
|
|
4
|
+
"icon.problem.size": "The image is larger than 1 MB. Choose a smaller image.",
|
|
5
|
+
"icon.readFailed": "Could not read the image. Choose another image.",
|
|
6
|
+
"icon.editor.label": "Change the default agent icon",
|
|
7
|
+
"icon.editor.hint": "PNG, JPEG, WebP · up to 1 MB · the center is cropped to a square",
|
|
8
|
+
"icon.pick": "Choose image",
|
|
9
|
+
"icon.save": "Save",
|
|
10
|
+
"icon.reset": "Default icon",
|
|
11
|
+
"icon.cancel": "Cancel",
|
|
12
|
+
},
|
|
13
|
+
ko: {
|
|
14
|
+
"icon.problem.type": "PNG, JPEG, WebP 이미지만 쓸 수 있습니다.",
|
|
15
|
+
"icon.problem.size": "이미지가 1MB보다 큽니다. 더 작은 이미지를 고르세요.",
|
|
16
|
+
"icon.readFailed": "이미지를 읽지 못했습니다. 다른 이미지를 고르세요.",
|
|
17
|
+
"icon.editor.label": "기본 에이전트 아이콘 바꾸기",
|
|
18
|
+
"icon.editor.hint": "PNG, JPEG, WebP · 1MB 이하 · 가운데를 정사각형으로 자릅니다",
|
|
19
|
+
"icon.pick": "이미지 선택",
|
|
20
|
+
"icon.save": "저장",
|
|
21
|
+
"icon.reset": "기본 아이콘",
|
|
22
|
+
"icon.cancel": "취소",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
"agents.origin.package": "Package default", "agents.origin.defaults": "Shared defaults", "agents.origin.agent": "Agent", "agents.origin.none": "No value",
|
|
4
|
+
"agents.stale.label": "Definition changed · applies to new sessions", "agents.stale.title": "The definition changed. Open sessions still use the previous definition. Select to start a new session with the updated definition.",
|
|
5
|
+
"agents.delete.hint": "Enter the agent name exactly to delete it. The conversation will be hidden; the definition and knowledge stay in the archive for 30 days.",
|
|
6
|
+
"agents.empty.list": "No agents yet", "agents.empty.trash": "The archive is empty", "agents.empty.files": "No knowledge files", "agents.new.body": "You take on this agent's role. Describe its role, tone, tasks, and restrictions here.\n",
|
|
7
|
+
"agents.field.schema.label": "Schema version", "agents.field.schema.help": "Definition format version. The current version is 1.",
|
|
8
|
+
"agents.field.name.label": "Name", "agents.field.name.help": "Shown in the sidebar and conversation header.",
|
|
9
|
+
"agents.field.description.label": "One-line purpose", "agents.field.description.help": "Up to 120 characters. Shown in lists and main's agent-list tool.",
|
|
10
|
+
"agents.field.icon.label": "Icon", "agents.field.icon.help": "One emoji.",
|
|
11
|
+
"agents.field.model.label": "Model", "agents.field.model.help": "Leave empty to use the gateway's current model. Fill in both fields or leave both empty.",
|
|
12
|
+
"agents.field.model.provider.label": "Provider", "agents.field.model.modelId.label": "Model ID",
|
|
13
|
+
"agents.field.thinking.label": "Thinking level", "agents.field.skills.label": "Allowed skills", "agents.field.skills.help": "Separate with commas or new lines. Skills outside this list are hidden from this agent's / menu.",
|
|
14
|
+
"agents.field.tools.label": "Tools", "agents.field.tools.web.label": "Web research (web_search, webfetch)", "agents.field.tools.bash.label": "Shell (prohibited)", "agents.field.tools.eval.label": "Code execution (prohibited)",
|
|
15
|
+
"agents.field.notify.label": "App notification when the reply ends", "agents.field.rules.label": "Rules", "agents.field.rules.gateway.label": "Include gateway rules", "agents.field.rules.install.label": "Include installation rules (rules.md)",
|
|
16
|
+
"agents.field.memory.label": "Long-term memory", "agents.field.memory.maxBytes.label": "MEMORY.md limit (bytes)", "agents.field.memory.maxBytes.help": "From 0 to 32768.",
|
|
17
|
+
"agents.error.required": "{label}: A value is required", "agents.error.integer": "{label}: Enter an integer", "agents.error.range": "{label}: Enter a value from {min} to {max}", "agents.error.option": "{label}: Choose one of {options}",
|
|
18
|
+
"agents.validation.name.required": "Enter a name", "agents.validation.description.required": "Enter a one-line purpose", "agents.validation.defaults.name": "Shared defaults cannot include a name", "agents.validation.defaults.description": "Shared defaults cannot include a one-line purpose",
|
|
19
|
+
"agents.validation.description.length": "The one-line purpose must be at most {max} characters (currently {count})", "agents.validation.memory.range": "MEMORY.md limit must be from 0 to {max}", "agents.validation.schema": "Schema version must be 1", "agents.validation.thinking": "Thinking level must be one of {levels}",
|
|
20
|
+
"agents.validation.model.pair": "Fill in both the provider and model ID, or leave both empty", "agents.validation.forbidden": "{name} cannot be used", "agents.validation.size": "Definition exceeds {max} bytes (currently {size})",
|
|
21
|
+
"agents.error.name_mismatch": "The names do not match. Enter the agent name exactly", "agents.error.agent_busy": "A turn is running or a question is open. Try again when it finishes",
|
|
22
|
+
"agents.error.agent_not_found": "Agent not found", "agents.error.invalid_agent_definition": "Invalid definition", "agents.error.invalid_request": "Invalid request", "agents.error.too_large": "File is too large", "agents.error.missing_file": "Choose a file to upload", "agents.error.invalid_filename": "This file name is not allowed", "agents.error.file_exists": "A file with this name already exists", "agents.error.exists": "An agent with this ID already exists and cannot be restored", "agents.error.invalid_trash_entry": "Invalid archive entry", "agents.error.forbidden": "This device cannot make changes", "agents.error.method_not_allowed": "Request method is not allowed",
|
|
23
|
+
"agents.error.rejected": "Request rejected", "agents.file.folder": "Folder",
|
|
24
|
+
},
|
|
25
|
+
ko: {
|
|
26
|
+
"agents.origin.package": "패키지 기본값", "agents.origin.defaults": "공통", "agents.origin.agent": "에이전트", "agents.origin.none": "값 없음",
|
|
27
|
+
"agents.stale.label": "정의 변경 · 새 세션부터 적용", "agents.stale.title": "정의가 바뀌었습니다. 열린 세션은 이전 정의를 씁니다. 선택하면 새 세션을 시작해 바뀐 정의를 적용합니다.",
|
|
28
|
+
"agents.delete.hint": "삭제하려면 에이전트 이름을 정확히 입력하세요. 대화는 숨기고 정의와 지식은 보관함에 30일 동안 둡니다.",
|
|
29
|
+
"agents.empty.list": "아직 에이전트가 없습니다", "agents.empty.trash": "보관함이 비었습니다", "agents.empty.files": "지식 파일이 없습니다", "agents.new.body": "너는 이 에이전트의 역할을 맡는다. 역할과 말투, 해야 할 일과 하지 말아야 할 일을 여기에 적는다.\n",
|
|
30
|
+
"agents.field.schema.label": "스키마 버전", "agents.field.schema.help": "정의 형식의 버전입니다. 현재 버전은 1입니다.",
|
|
31
|
+
"agents.field.name.label": "이름", "agents.field.name.help": "사이드바와 대화 머리줄에 표시됩니다.",
|
|
32
|
+
"agents.field.description.label": "목적 한 줄", "agents.field.description.help": "120자 이하입니다. 목록과 main의 에이전트 목록 도구에 표시됩니다.",
|
|
33
|
+
"agents.field.icon.label": "아이콘", "agents.field.icon.help": "이모지 하나입니다.",
|
|
34
|
+
"agents.field.model.label": "모델", "agents.field.model.help": "비우면 게이트웨이의 현재 모델을 씁니다. 두 항목을 모두 채우거나 모두 비우세요.",
|
|
35
|
+
"agents.field.model.provider.label": "제공자", "agents.field.model.modelId.label": "모델 ID",
|
|
36
|
+
"agents.field.thinking.label": "사고 수준", "agents.field.skills.label": "허용할 스킬", "agents.field.skills.help": "쉼표나 줄바꿈으로 나눕니다. 목록에 없는 스킬은 이 에이전트의 / 메뉴에 표시되지 않습니다.",
|
|
37
|
+
"agents.field.tools.label": "도구", "agents.field.tools.web.label": "웹 리서치 (web_search, webfetch)", "agents.field.tools.bash.label": "셸 (금지)", "agents.field.tools.eval.label": "코드 실행 (금지)",
|
|
38
|
+
"agents.field.notify.label": "답변이 끝나면 앱 알림", "agents.field.rules.label": "규칙", "agents.field.rules.gateway.label": "게이트웨이 규칙 포함", "agents.field.rules.install.label": "설치 규칙(rules.md) 포함",
|
|
39
|
+
"agents.field.memory.label": "장기 메모", "agents.field.memory.maxBytes.label": "MEMORY.md 상한 (바이트)", "agents.field.memory.maxBytes.help": "0부터 32768까지입니다.",
|
|
40
|
+
"agents.error.required": "{label}: 값을 입력하세요", "agents.error.integer": "{label}: 정수를 입력하세요", "agents.error.range": "{label}: {min}부터 {max}까지 입력하세요", "agents.error.option": "{label}: {options} 중 하나를 선택하세요",
|
|
41
|
+
"agents.validation.name.required": "이름을 입력하세요", "agents.validation.description.required": "목적을 한 줄로 입력하세요", "agents.validation.defaults.name": "공통 기본값에는 이름을 둘 수 없습니다", "agents.validation.defaults.description": "공통 기본값에는 목적 한 줄을 둘 수 없습니다",
|
|
42
|
+
"agents.validation.description.length": "목적 한 줄은 {max}자 이하여야 합니다 (현재 {count}자)", "agents.validation.memory.range": "MEMORY.md 상한은 0부터 {max}까지여야 합니다", "agents.validation.schema": "스키마 버전은 1이어야 합니다", "agents.validation.thinking": "사고 수준은 {levels} 중 하나여야 합니다",
|
|
43
|
+
"agents.validation.model.pair": "제공자와 모델 ID를 모두 입력하거나 모두 비우세요", "agents.validation.forbidden": "{name}은(는) 사용할 수 없습니다", "agents.validation.size": "정의가 {max}바이트를 넘습니다 (현재 {size}바이트)",
|
|
44
|
+
"agents.error.name_mismatch": "이름이 다릅니다. 에이전트 이름을 똑같이 입력하세요", "agents.error.agent_busy": "진행 중인 턴이나 열린 질문이 있어 지금은 할 수 없습니다. 끝난 뒤 다시 시도하세요",
|
|
45
|
+
"agents.error.agent_not_found": "에이전트를 찾지 못했습니다", "agents.error.invalid_agent_definition": "정의가 올바르지 않습니다", "agents.error.invalid_request": "요청이 올바르지 않습니다", "agents.error.too_large": "파일이 너무 큽니다", "agents.error.missing_file": "올릴 파일을 고르세요", "agents.error.invalid_filename": "파일 이름을 쓸 수 없습니다", "agents.error.file_exists": "같은 이름의 파일이 이미 있습니다", "agents.error.exists": "같은 ID의 에이전트가 이미 있어 되살리지 못했습니다", "agents.error.invalid_trash_entry": "보관함 항목이 올바르지 않습니다", "agents.error.forbidden": "이 기기에서는 쓸 수 없습니다", "agents.error.method_not_allowed": "허용되지 않는 요청입니다",
|
|
46
|
+
"agents.error.rejected": "요청이 거절됐습니다", "agents.file.folder": "폴더",
|
|
47
|
+
},
|
|
48
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
"appDownload.installHint": "Allow installation from unknown sources. Scan the QR code with your phone camera, download the APK, then install it.",
|
|
4
|
+
"appDownload.loading": "Creating download QR code…",
|
|
5
|
+
"appDownload.expired": "The download QR code expired. Create a new one and scan it.",
|
|
6
|
+
"appDownload.apkUnavailable": "No app (APK) is available to download from this installation.",
|
|
7
|
+
"appDownload.accessUrlUnknown": "The access address is unknown. Connect the Mac to Wi-Fi, then create a new link.",
|
|
8
|
+
"appDownload.qrUnavailable": "Could not load the QR library. Reload the page.",
|
|
9
|
+
"appDownload.network": "Could not connect to the gateway. Try again shortly.",
|
|
10
|
+
"appDownload.error": "Could not create the download QR code ({error}). Select Create new to try again.",
|
|
11
|
+
"appDownload.version": "Zigmini {version}",
|
|
12
|
+
"appDownload.countdown": "Time remaining: {time}",
|
|
13
|
+
},
|
|
14
|
+
ko: {
|
|
15
|
+
"appDownload.installHint": "출처를 알 수 없는 앱 설치를 허용해야 합니다. 휴대전화 카메라로 QR 코드를 찍어 APK를 내려받은 뒤 설치하세요.",
|
|
16
|
+
"appDownload.loading": "내려받기 QR 코드를 만드는 중…",
|
|
17
|
+
"appDownload.expired": "내려받기 QR 코드가 만료되었습니다. 새로 만든 뒤 다시 찍으세요.",
|
|
18
|
+
"appDownload.apkUnavailable": "이 설치에서는 내려받을 앱(APK)이 없습니다.",
|
|
19
|
+
"appDownload.accessUrlUnknown": "접속 주소를 알 수 없습니다. 맥을 Wi-Fi에 연결한 뒤 새로 만드세요.",
|
|
20
|
+
"appDownload.qrUnavailable": "QR 라이브러리를 불러오지 못했습니다. 페이지를 새로 고치세요.",
|
|
21
|
+
"appDownload.network": "게이트웨이에 연결하지 못했습니다. 잠시 후 다시 시도하세요.",
|
|
22
|
+
"appDownload.error": "내려받기 QR 코드를 만들지 못했습니다 ({error}). 새로 만들기를 눌러 다시 시도하세요.",
|
|
23
|
+
"appDownload.version": "지그미니 {version}",
|
|
24
|
+
"appDownload.countdown": "남은 시간: {time}",
|
|
25
|
+
},
|
|
26
|
+
};
|
package/web/i18n/boot.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
"boot.title": "This device must be registered",
|
|
4
|
+
"boot.request": "Request registration",
|
|
5
|
+
"boot.pending": "Approve the request shown on the Mac's Zigmini web screen within {seconds} seconds. Check that the number matches. ({name})",
|
|
6
|
+
"boot.locked": "Registration is locked after 3 failed requests. Unlock it on the Mac before requesting again.",
|
|
7
|
+
"boot.denied": "Registration was denied or not approved within 30 seconds.",
|
|
8
|
+
"boot.first": "This is the first connection from this phone.",
|
|
9
|
+
"boot.hint": "{head} After you request registration, the Mac must approve it within 30 seconds. ({left} requests left)",
|
|
10
|
+
"boot.busy": "Another registration request is being processed. Try again in a moment.",
|
|
11
|
+
"boot.failed": "Could not send the request: {reason}",
|
|
12
|
+
},
|
|
13
|
+
ko: {
|
|
14
|
+
"boot.title": "이 기기를 등록해야 합니다",
|
|
15
|
+
"boot.request": "등록 요청",
|
|
16
|
+
"boot.pending": "맥의 웹 지그미니 화면에 뜬 요청을 {seconds}초 안에 승인해 주세요. 같은 번호인지 확인하세요. ({name})",
|
|
17
|
+
"boot.locked": "등록 요청이 3번 실패해 잠겼습니다. 맥에서 잠금을 풀어야 다시 요청할 수 있습니다.",
|
|
18
|
+
"boot.denied": "등록이 거절됐거나 30초 안에 승인되지 않았습니다.",
|
|
19
|
+
"boot.first": "이 폰에서 처음 접속했습니다.",
|
|
20
|
+
"boot.hint": "{head} 등록을 요청하면 맥에서 30초 안에 승인해야 합니다. (남은 요청 {left}번)",
|
|
21
|
+
"boot.busy": "다른 등록 요청이 처리 중입니다. 잠시 후 다시 시도하세요.",
|
|
22
|
+
"boot.failed": "요청하지 못했습니다: {reason}",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// The words web/commands.js understands. Unlike display strings, these are matched in BOTH languages whatever the UI
|
|
2
|
+
// language is (a user may type either), so commands.js reads both sides of this dictionary. A value is a comma list.
|
|
3
|
+
export default {
|
|
4
|
+
en: {
|
|
5
|
+
"commands.tts.names": "/tts,tts",
|
|
6
|
+
"commands.wake.names": "/wake,wake",
|
|
7
|
+
"commands.clap.names": "/clap,clap",
|
|
8
|
+
"commands.on": "on",
|
|
9
|
+
"commands.off": "off",
|
|
10
|
+
"commands.status": "/options",
|
|
11
|
+
"commands.readFull": "/read",
|
|
12
|
+
"commands.closeEars": "/closeears",
|
|
13
|
+
"commands.devices": "/devices",
|
|
14
|
+
"commands.devices.prefix": "/devices",
|
|
15
|
+
"commands.devices.delete": "delete,remove",
|
|
16
|
+
"commands.mode": "mode",
|
|
17
|
+
"commands.particle": "=",
|
|
18
|
+
},
|
|
19
|
+
ko: {
|
|
20
|
+
"commands.tts.names": "음성답변,음성응답",
|
|
21
|
+
"commands.wake.names": "호출어대기,호출어,웨이크워드",
|
|
22
|
+
"commands.clap.names": "박수감지,박수",
|
|
23
|
+
"commands.on": "켜,켜줘,켜기,켜라,켜주세요,활성화,활성화해,활성화해줘,활성화해주세요,활성화시켜,활성화시켜줘",
|
|
24
|
+
"commands.off": "꺼,꺼줘,끄기,꺼라,꺼주세요,비활성화,비활성화해,비활성화해줘,비활성화해주세요,비활성화시켜,비활성화시켜줘",
|
|
25
|
+
"commands.status": "/옵션,옵션,옵션상태",
|
|
26
|
+
"commands.readFull": "전체읽어줘,전체읽어,전체다읽어줘,전부읽어줘,다읽어줘,전체읽어주세요,전체듣기",
|
|
27
|
+
"commands.closeEars": "귀닫아,귀닫아줘,귀좀닫아,귀좀닫아줘,귀닫아라",
|
|
28
|
+
"commands.devices": "/기기,기기목록",
|
|
29
|
+
"commands.devices.prefix": "/기기",
|
|
30
|
+
"commands.devices.delete": "삭제,지워,지워줘",
|
|
31
|
+
"commands.mode": "모드",
|
|
32
|
+
"commands.particle": "을,를",
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
"decisions.dismiss.hide.prompt": "Remove this from the inbox. The question and answer history will remain.", "decisions.dismiss.hide.confirm": "Delete",
|
|
4
|
+
"decisions.dismiss.cancel.prompt": "This question is still waiting for an answer. Removing it sends a cancellation to the work that asked it. That work may continue without an answer or stop.", "decisions.dismiss.cancel.confirm": "Cancel question and delete",
|
|
5
|
+
"decisions.question.multi": " (multiple selections allowed)", "decisions.question.optional": " (optional)", "decisions.confirm.yes": "Yes", "decisions.confirm.no": "No",
|
|
6
|
+
"decisions.blocked": "The security check blocked this request. It was not sent.", "decisions.status.pending": "Needs an answer", "decisions.status.submitted": "Sending",
|
|
7
|
+
"decisions.binding.live": "Waiting for an answer", "decisions.binding.expired": "Expired", "decisions.binding.closed": "Request ended", "decisions.binding.unknown": "Status unknown", "decisions.binding.answer": "Waiting for an answer",
|
|
8
|
+
"decisions.work.submitted": "Received", "decisions.work.running": "Running", "decisions.work.waiting": "Waiting", "decisions.work.waiting_input": "Waiting for an answer", "decisions.work.completed": "Completed", "decisions.work.failed": "Failed", "decisions.work.cancelled": "Cancelled", "decisions.work.unknown": "Status unknown",
|
|
9
|
+
"decisions.route.live_response": "Send to the active request", "decisions.route.follow_up_command": "Send as a follow-up instruction",
|
|
10
|
+
"decisions.reason.receipt_unknown": "Delivery was not confirmed", "decisions.reason.user_deferred": "You chose to answer later", "decisions.reason.source_changed": "The question changed", "decisions.reason.recheck_incomplete": "The status check has not finished", "decisions.reason.engine_wait_closed": "The original request ended without an answer", "decisions.reason.engine_wait_cancelled": "The original request was cancelled", "decisions.reason.request_missing": "The original request was not found", "decisions.reason.owner_disconnected": "The responsible session disconnected", "decisions.reason.binding_unknown": "The original request status is unknown", "decisions.reason.owner_unknown": "The current responsible session is unknown", "decisions.reason.parked": "The responsible session is paused", "decisions.reason.command_pending": "Sending the follow-up instruction", "decisions.reason.timeout": "The deadline passed", "decisions.reason.report_only": "The current owner asked this question again", "decisions.reason.main_released": "This question is waiting for an answer", "decisions.reason.instructions_changed": "A new instruction was added after the question", "decisions.reason.context_changed": "A new instruction was added after the question", "decisions.reason.recheck_requested": "A status check was requested", "decisions.reason.request_permission_requested": "A new permission request was sent",
|
|
11
|
+
"decisions.wait.work_ended": "This work is {status}, so it cannot continue. You can only view the original request and its history.", "decisions.wait.requested": "{reason}. Waiting for the responsible session to respond.", "decisions.wait.answer_sending": "Sending the answer.", "decisions.wait.recheck": "{reason}. Check the current status.", "decisions.wait.live": "Waiting for an answer.", "decisions.wait.permission_expired": "The permission request expired. The previous approval will not be reused. A new approval is required for the current action.", "decisions.wait.expired": "The deadline passed, but a decision is still required. Your answer will continue with the current work status.", "decisions.wait.report_only": "The current owner asked this question again. Your answer will be sent as given.", "decisions.wait.main_released": "This question is waiting for an answer. The conversation continues while it waits. Your answer will be sent as given.", "decisions.wait.unknown": "{reason}. Check the current status.", "decisions.wait.work_status": "Work status: {status}{reason}.",
|
|
12
|
+
},
|
|
13
|
+
ko: {
|
|
14
|
+
"decisions.dismiss.hide.prompt": "확인함에서 지웁니다. 질문과 답변 기록은 남습니다.", "decisions.dismiss.hide.confirm": "삭제",
|
|
15
|
+
"decisions.dismiss.cancel.prompt": "아직 답을 기다리는 질문입니다. 지우면 질문을 낸 작업에 취소를 전달합니다. 그 작업은 답 없이 계속되거나 멈출 수 있습니다.", "decisions.dismiss.cancel.confirm": "질문 취소하고 삭제",
|
|
16
|
+
"decisions.question.multi": " (여러 개 선택 가능)", "decisions.question.optional": " (선택)", "decisions.confirm.yes": "예", "decisions.confirm.no": "아니오",
|
|
17
|
+
"decisions.blocked": "보안검사에서 차단해 요청을 보내지 않았습니다.", "decisions.status.pending": "확인 필요", "decisions.status.submitted": "전달 중",
|
|
18
|
+
"decisions.binding.live": "답 기다리는 중", "decisions.binding.expired": "기한 만료", "decisions.binding.closed": "요청 종료", "decisions.binding.unknown": "상태 불명", "decisions.binding.answer": "답변 대기",
|
|
19
|
+
"decisions.work.submitted": "접수됨", "decisions.work.running": "실행 중", "decisions.work.waiting": "대기 중", "decisions.work.waiting_input": "답변 기다리는 중", "decisions.work.completed": "완료", "decisions.work.failed": "실패", "decisions.work.cancelled": "취소됨", "decisions.work.unknown": "상태 불명",
|
|
20
|
+
"decisions.route.live_response": "실행 중인 요청에 바로 전달", "decisions.route.follow_up_command": "후속 지시로 전달",
|
|
21
|
+
"decisions.reason.receipt_unknown": "전달 확인을 받지 못했습니다", "decisions.reason.user_deferred": "나중에 답하기로 미뤘습니다", "decisions.reason.source_changed": "질문 내용이 바뀌었습니다", "decisions.reason.recheck_incomplete": "재확인 결과가 아직 오지 않았습니다", "decisions.reason.engine_wait_closed": "원래 요청이 답 없이 끝났습니다", "decisions.reason.engine_wait_cancelled": "원래 요청이 취소됐습니다", "decisions.reason.request_missing": "원래 요청을 찾을 수 없습니다", "decisions.reason.owner_disconnected": "담당 세션 연결이 끊겼습니다", "decisions.reason.binding_unknown": "원래 요청 상태를 알 수 없습니다", "decisions.reason.owner_unknown": "현재 담당 세션을 확인할 수 없습니다", "decisions.reason.parked": "담당 세션이 잠시 멈춰 있습니다", "decisions.reason.command_pending": "후속 지시를 보내는 중입니다", "decisions.reason.timeout": "기한이 지났습니다", "decisions.reason.report_only": "현재 담당이 다시 낸 질문입니다", "decisions.reason.main_released": "답을 기다리는 질문입니다", "decisions.reason.instructions_changed": "질문 이후 새 지시가 추가됐습니다", "decisions.reason.context_changed": "질문 이후 새 지시가 추가됐습니다", "decisions.reason.recheck_requested": "현재 상황 확인을 요청했습니다", "decisions.reason.request_permission_requested": "새 승인 요청을 보냈습니다",
|
|
22
|
+
"decisions.wait.work_ended": "작업이 {status} 상태라 더 실행할 수 없습니다. 원문과 이력만 볼 수 있습니다.", "decisions.wait.requested": "{reason}. 담당 세션의 응답을 기다립니다.", "decisions.wait.answer_sending": "답변을 전달하는 중입니다.", "decisions.wait.recheck": "{reason}. 현재 상황을 확인해 주세요.", "decisions.wait.live": "지금 답을 기다리고 있습니다.", "decisions.wait.permission_expired": "승인 요청 기한이 지났습니다. 이전 승인은 다시 쓰지 않습니다. 현재 실행 내용에 대해 새 승인을 받아야 합니다.", "decisions.wait.expired": "기한은 지났지만 결정은 아직 필요합니다. 답하면 현재 작업 상황에 맞춰 이어서 전달합니다.", "decisions.wait.report_only": "현재 담당이 다시 낸 질문입니다. 답하면 그대로 전달합니다.", "decisions.wait.main_released": "답을 기다리는 질문입니다. 그동안 대화는 멈추지 않습니다. 답하면 그대로 전달합니다.", "decisions.wait.unknown": "{reason}. 현재 상황을 확인해 주세요.", "decisions.wait.work_status": "작업 상태: {status}{reason}.",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
"devlog.turnEnd": "Reply completed: {status}{error}",
|
|
4
|
+
"devlog.yes": "Yes",
|
|
5
|
+
"devlog.no": "No",
|
|
6
|
+
"devlog.cancel": "Cancelled",
|
|
7
|
+
"devlog.turnStarted": "Task started",
|
|
8
|
+
"devlog.turnCompleted": "Reply completed · {status}",
|
|
9
|
+
"devlog.engineStatus": "Engine {status}{detail}",
|
|
10
|
+
"devlog.snapshot": "{conversations} conversations · {approvals} approvals pending · engine {engine}",
|
|
11
|
+
"devlog.history": "{count} events in {conversation}",
|
|
12
|
+
"devlog.newConversation": "New conversation: {title}",
|
|
13
|
+
"devlog.profile": "Nickname {nickname}{agent}",
|
|
14
|
+
"devlog.agent": "agent",
|
|
15
|
+
"devlog.voiceOff": "Voice off",
|
|
16
|
+
"devlog.voiceOn": "Voice on",
|
|
17
|
+
"devlog.voiceInstall": "Voice install {state} {index}/{total} {message}",
|
|
18
|
+
"devlog.versionAvailable": "Version {latest} is available (current: {current})",
|
|
19
|
+
"devlog.updateProgress": "Update {from} → {to}: {label}",
|
|
20
|
+
"devlog.updateResult": "Update {result} {from} → {to}",
|
|
21
|
+
"devlog.success": "succeeded",
|
|
22
|
+
"devlog.rollback": "failed, rolled back",
|
|
23
|
+
"devlog.failure": "failed",
|
|
24
|
+
"devlog.memo": "Memo: {count} characters{size}",
|
|
25
|
+
"devlog.wakeHeard": "\"{text}\"{armed}{speaking}",
|
|
26
|
+
"devlog.armed": "listening for wake word",
|
|
27
|
+
"devlog.speaking": "voice reply in progress",
|
|
28
|
+
"devlog.clapWakeOff": "Two claps → wake word off",
|
|
29
|
+
"devlog.clapWakeOn": "Two claps → wake word on",
|
|
30
|
+
},
|
|
31
|
+
ko: {
|
|
32
|
+
"devlog.turnEnd": "응답 완료: {status}{error}",
|
|
33
|
+
"devlog.yes": "예",
|
|
34
|
+
"devlog.no": "아니오",
|
|
35
|
+
"devlog.cancel": "취소",
|
|
36
|
+
"devlog.turnStarted": "작업 시작",
|
|
37
|
+
"devlog.turnCompleted": "응답 완료 · {status}",
|
|
38
|
+
"devlog.engineStatus": "엔진 {status}{detail}",
|
|
39
|
+
"devlog.snapshot": "대화 {conversations} · 승인 대기 {approvals} · 엔진 {engine}",
|
|
40
|
+
"devlog.history": "{conversation} 기록 {count}건",
|
|
41
|
+
"devlog.newConversation": "새 대화 {title}",
|
|
42
|
+
"devlog.profile": "닉네임 {nickname}{agent}",
|
|
43
|
+
"devlog.agent": "에이전트",
|
|
44
|
+
"devlog.voiceOff": "음성 꺼짐",
|
|
45
|
+
"devlog.voiceOn": "음성 켜짐",
|
|
46
|
+
"devlog.voiceInstall": "음성 설치 {state} {index}/{total} {message}",
|
|
47
|
+
"devlog.versionAvailable": "새 버전 {latest} (현재 {current})",
|
|
48
|
+
"devlog.updateProgress": "업데이트 {from} → {to}: {label}",
|
|
49
|
+
"devlog.updateResult": "업데이트 {result} {from} → {to}",
|
|
50
|
+
"devlog.success": "성공",
|
|
51
|
+
"devlog.rollback": "실패, 되돌림",
|
|
52
|
+
"devlog.failure": "실패",
|
|
53
|
+
"devlog.memo": "쪽지 {count}자{size}",
|
|
54
|
+
"devlog.wakeHeard": "\"{text}\"{armed}{speaking}",
|
|
55
|
+
"devlog.armed": "말씀하세요 상태",
|
|
56
|
+
"devlog.speaking": "음성 답변 중",
|
|
57
|
+
"devlog.clapWakeOff": "박수 두 번 → 호출어 끔",
|
|
58
|
+
"devlog.clapWakeOn": "박수 두 번 → 호출어 켬",
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
"diagram.title.default": "Diagram",
|
|
4
|
+
"diagram.region": "{title}. Diagram area, scroll with the arrow keys.",
|
|
5
|
+
"diagram.source": "Diagram source",
|
|
6
|
+
},
|
|
7
|
+
ko: {
|
|
8
|
+
"diagram.title.default": "다이어그램",
|
|
9
|
+
"diagram.region": "{title}. 다이어그램 영역, 방향키로 스크롤할 수 있습니다.",
|
|
10
|
+
"diagram.source": "다이어그램 원문",
|
|
11
|
+
},
|
|
12
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
"enroll.button.renew": "Create new QR code", "enroll.button.revoke": "Revoke registration", "enroll.button.revoke.armed": "Select again to revoke",
|
|
4
|
+
"enroll.hint": "Scan this QR code with the Zigmini app on your phone. Each QR code works once for 10 minutes.",
|
|
5
|
+
"enroll.loading": "Creating QR code…", "enroll.expired": "The QR code expired. Create a new one and scan it.", "enroll.devices.empty": "No registered devices.", "enroll.contact.none": "No connection history",
|
|
6
|
+
"enroll.error.access_url_unknown": "The connection address is unknown. Connect your Mac to Wi-Fi, then create a new QR code.",
|
|
7
|
+
"enroll.error.qr_unavailable": "Could not load the QR library. Refresh the page.", "enroll.error.network": "Could not connect to the gateway. Try creating a new QR code shortly.",
|
|
8
|
+
"enroll.error.generic": "Could not create the QR code ({error}). Select Create new QR code.",
|
|
9
|
+
"enroll.device.approved": "Approved", "enroll.device.pending": "Approval pending", "enroll.device.denied": "Denied", "enroll.device.model.unknown": "Model unknown",
|
|
10
|
+
"enroll.countdown": "{time} remaining", "enroll.contact.now": "Connected just now", "enroll.contact.minutes": "Connected {count} min ago", "enroll.contact.hours": "Connected {count} hr ago", "enroll.contact.days": "Connected {count} days ago",
|
|
11
|
+
},
|
|
12
|
+
ko: {
|
|
13
|
+
"enroll.button.renew": "새로 만들기", "enroll.button.revoke": "등록 취소", "enroll.button.revoke.armed": "다시 누르면 취소",
|
|
14
|
+
"enroll.hint": "폰의 지그미니 앱에서 이 QR을 찍으세요. QR 하나는 10분 동안 한 번만 쓸 수 있습니다.",
|
|
15
|
+
"enroll.loading": "QR을 만드는 중…", "enroll.expired": "QR이 만료되었습니다. 새로 만들어 다시 찍으세요.", "enroll.devices.empty": "등록된 기기가 없습니다.", "enroll.contact.none": "접속 기록 없음",
|
|
16
|
+
"enroll.error.access_url_unknown": "접속 주소를 알 수 없습니다. 맥이 Wi-Fi에 연결되어 있는지 확인한 뒤 새로 만드세요.",
|
|
17
|
+
"enroll.error.qr_unavailable": "QR 라이브러리를 불러오지 못했습니다. 페이지를 새로 고치세요.", "enroll.error.network": "게이트웨이에 연결하지 못했습니다. 잠시 후 새로 만드세요.",
|
|
18
|
+
"enroll.error.generic": "QR을 만들지 못했습니다 ({error}). 새로 만들기를 누르세요.",
|
|
19
|
+
"enroll.device.approved": "승인됨", "enroll.device.pending": "승인 대기", "enroll.device.denied": "거절됨", "enroll.device.model.unknown": "모델 정보 없음",
|
|
20
|
+
"enroll.countdown": "남은 시간 {time}", "enroll.contact.now": "방금 접속", "enroll.contact.minutes": "{count}분 전 접속", "enroll.contact.hours": "{count}시간 전 접속", "enroll.contact.days": "{count}일 전 접속",
|
|
21
|
+
},
|
|
22
|
+
};
|
package/web/i18n/gc.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
"gc.dbBackup": "Database backup",
|
|
4
|
+
"gc.omoVersion": "Engine version folder",
|
|
5
|
+
"gc.updateFile": "Leftover update files",
|
|
6
|
+
"gc.tempDir": "Temporary folder",
|
|
7
|
+
"gc.rpcDaemon": "Previous RPC daemon",
|
|
8
|
+
"gc.agentTrash": "Archived agent folder",
|
|
9
|
+
"gc.empty": "There are no items to clean up",
|
|
10
|
+
"gc.failed": "Could not load cleanup candidates",
|
|
11
|
+
"gc.unknownSize": "Unknown size",
|
|
12
|
+
"gc.ageDays": "{count} days",
|
|
13
|
+
"gc.ageHours": "{count} hours",
|
|
14
|
+
"gc.ageMinutes": "{count} minutes",
|
|
15
|
+
"gc.summary": "{count} candidates · {bytes}",
|
|
16
|
+
"gc.cleanResult": "Cleaned {cleaned}{failed}{missing}",
|
|
17
|
+
"gc.failedCount": ", {count} failed",
|
|
18
|
+
"gc.missingCount": ", {count} are no longer candidates",
|
|
19
|
+
},
|
|
20
|
+
ko: {
|
|
21
|
+
"gc.dbBackup": "DB 백업",
|
|
22
|
+
"gc.omoVersion": "엔진 버전 폴더",
|
|
23
|
+
"gc.updateFile": "업데이트 남은 파일",
|
|
24
|
+
"gc.tempDir": "임시 폴더",
|
|
25
|
+
"gc.rpcDaemon": "이전 RPC 데몬",
|
|
26
|
+
"gc.agentTrash": "에이전트 보관 폴더",
|
|
27
|
+
"gc.empty": "정리할 항목이 없습니다",
|
|
28
|
+
"gc.failed": "정리 후보를 읽지 못했습니다",
|
|
29
|
+
"gc.unknownSize": "크기 알 수 없음",
|
|
30
|
+
"gc.ageDays": "{count}일",
|
|
31
|
+
"gc.ageHours": "{count}시간",
|
|
32
|
+
"gc.ageMinutes": "{count}분",
|
|
33
|
+
"gc.summary": "후보 {count}개 · {bytes}",
|
|
34
|
+
"gc.cleanResult": "정리함 {cleaned}개{failed}{missing}",
|
|
35
|
+
"gc.failedCount": ", 실패 {count}개",
|
|
36
|
+
"gc.missingCount": ", 이미 후보가 아닌 항목 {count}개",
|
|
37
|
+
},
|
|
38
|
+
};
|