@raingor/pi-web-switch 0.2.0
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.ja.md +137 -0
- package/README.md +277 -0
- package/README.zh-CN.md +176 -0
- package/index.html +13 -0
- package/package.json +44 -0
- package/pi-package/index.ts +100 -0
- package/pi-package/skills/pi-web-switch/SKILL.md +60 -0
- package/public/pi.svg +4 -0
- package/server/pi-reader.ts +678 -0
- package/src/App.tsx +25 -0
- package/src/components/dashboard/DashboardPage.tsx +607 -0
- package/src/components/layout/AppShell.tsx +18 -0
- package/src/components/layout/Sidebar.tsx +116 -0
- package/src/components/models/ModelsPage.tsx +570 -0
- package/src/components/providers/ProvidersPage.tsx +466 -0
- package/src/components/sessions/MemoryPage.tsx +177 -0
- package/src/components/sessions/SessionsPage.tsx +347 -0
- package/src/components/settings/SettingsPage.tsx +351 -0
- package/src/components/ui/Badge.tsx +29 -0
- package/src/components/ui/EmptyState.tsx +20 -0
- package/src/components/ui/Modal.tsx +41 -0
- package/src/components/ui/StatCard.tsx +37 -0
- package/src/data/builtin-providers.ts +148 -0
- package/src/data/mock-config.ts +261 -0
- package/src/data/mock-usage.ts +153 -0
- package/src/index.css +217 -0
- package/src/lib/config.ts +56 -0
- package/src/lib/currency.ts +48 -0
- package/src/lib/i18n.tsx +98 -0
- package/src/lib/translations/en.ts +168 -0
- package/src/lib/translations/index.ts +14 -0
- package/src/lib/translations/ja.ts +158 -0
- package/src/lib/translations/zh-CN.ts +158 -0
- package/src/lib/translations/zh-TW.ts +158 -0
- package/src/lib/utils.ts +51 -0
- package/src/main.tsx +106 -0
- package/src/store/config-store.ts +459 -0
- package/src/types/index.ts +187 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +24 -0
- package/vite.config.ts +172 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// ─── Currency Switching ────────────────────────────────
|
|
2
|
+
// Simple state management for USD/CNY toggle, persisted in localStorage.
|
|
3
|
+
|
|
4
|
+
import { useState, useCallback } from "react";
|
|
5
|
+
|
|
6
|
+
export type CurrencyCode = "USD" | "CNY";
|
|
7
|
+
|
|
8
|
+
const STORAGE_KEY = "pi-web-switch-currency";
|
|
9
|
+
|
|
10
|
+
function loadCurrency(): CurrencyCode {
|
|
11
|
+
try {
|
|
12
|
+
const saved = localStorage.getItem(STORAGE_KEY);
|
|
13
|
+
if (saved === "USD" || saved === "CNY") return saved;
|
|
14
|
+
} catch {}
|
|
15
|
+
return "USD";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let _currency: CurrencyCode = loadCurrency();
|
|
19
|
+
let _listeners: Array<(c: CurrencyCode) => void> = [];
|
|
20
|
+
|
|
21
|
+
export function getCurrency(): CurrencyCode {
|
|
22
|
+
return _currency;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function setCurrency(code: CurrencyCode): void {
|
|
26
|
+
_currency = code;
|
|
27
|
+
try { localStorage.setItem(STORAGE_KEY, code); } catch {}
|
|
28
|
+
_listeners.forEach((fn) => fn(code));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function useCurrency() {
|
|
32
|
+
const [currency, setCur] = useState<CurrencyCode>(_currency);
|
|
33
|
+
|
|
34
|
+
const toggle = useCallback(() => {
|
|
35
|
+
const next: CurrencyCode = currency === "USD" ? "CNY" : "USD";
|
|
36
|
+
setCurrency(next);
|
|
37
|
+
setCur(next);
|
|
38
|
+
}, [currency]);
|
|
39
|
+
|
|
40
|
+
// Subscribe to external changes
|
|
41
|
+
useState(() => {
|
|
42
|
+
const handler = (c: CurrencyCode) => setCur(c);
|
|
43
|
+
_listeners.push(handler);
|
|
44
|
+
return () => { _listeners = _listeners.filter((fn) => fn !== handler); };
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return { currency, toggle, setCurrency: setCur };
|
|
48
|
+
}
|
package/src/lib/i18n.tsx
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// ─── Multi-language Translation System ──────────────────
|
|
2
|
+
// Uses React Context + hook, zero external dependencies.
|
|
3
|
+
|
|
4
|
+
import { createContext, useContext, useState, useCallback, type ReactNode } from "react";
|
|
5
|
+
|
|
6
|
+
export type LangCode = "en" | "zh-CN" | "zh-TW" | "ja";
|
|
7
|
+
|
|
8
|
+
export const LANGUAGES: { code: LangCode; label: string; nativeLabel: string }[] = [
|
|
9
|
+
{ code: "en", label: "English", nativeLabel: "English" },
|
|
10
|
+
{ code: "zh-CN", label: "简体中文", nativeLabel: "简体中文" },
|
|
11
|
+
{ code: "zh-TW", label: "繁體中文", nativeLabel: "繁體中文" },
|
|
12
|
+
{ code: "ja", label: "日本語", nativeLabel: "日本語" },
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
// ─── Translation Map ────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
type TranslationMap = Record<string, string | ((...args: string[]) => string)>;
|
|
18
|
+
export type Translations = Record<LangCode, TranslationMap>;
|
|
19
|
+
|
|
20
|
+
// ─── Context ────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
interface I18nContextValue {
|
|
23
|
+
lang: LangCode;
|
|
24
|
+
setLang: (code: LangCode) => void;
|
|
25
|
+
t: (key: string, ...args: string[]) => string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const I18nContext = createContext<I18nContextValue | null>(null);
|
|
29
|
+
|
|
30
|
+
const STORAGE_KEY = "pi-web-switch-lang";
|
|
31
|
+
|
|
32
|
+
function loadLang(): LangCode {
|
|
33
|
+
try {
|
|
34
|
+
const saved = localStorage.getItem(STORAGE_KEY);
|
|
35
|
+
if (saved && ["en", "zh-CN", "zh-TW", "ja"].includes(saved)) return saved as LangCode;
|
|
36
|
+
} catch {}
|
|
37
|
+
// Detect browser language
|
|
38
|
+
try {
|
|
39
|
+
const browserLang = navigator.language;
|
|
40
|
+
if (browserLang.startsWith("zh")) {
|
|
41
|
+
if (browserLang === "zh-TW" || browserLang === "zh-HK") return "zh-TW";
|
|
42
|
+
return "zh-CN";
|
|
43
|
+
}
|
|
44
|
+
if (browserLang.startsWith("ja")) return "ja";
|
|
45
|
+
} catch {}
|
|
46
|
+
return "en";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function I18nProvider({
|
|
50
|
+
children,
|
|
51
|
+
translations,
|
|
52
|
+
}: {
|
|
53
|
+
children: ReactNode;
|
|
54
|
+
translations: Translations;
|
|
55
|
+
}) {
|
|
56
|
+
const [lang, setLangState] = useState<LangCode>(loadLang);
|
|
57
|
+
|
|
58
|
+
const setLang = useCallback((code: LangCode) => {
|
|
59
|
+
setLangState(code);
|
|
60
|
+
try { localStorage.setItem(STORAGE_KEY, code); } catch {}
|
|
61
|
+
}, []);
|
|
62
|
+
|
|
63
|
+
const t = useCallback(
|
|
64
|
+
(key: string, ...args: string[]): string => {
|
|
65
|
+
const map = translations[lang];
|
|
66
|
+
let val = map?.[key];
|
|
67
|
+
if (val === undefined) {
|
|
68
|
+
// Fallback to English
|
|
69
|
+
val = translations["en"]?.[key];
|
|
70
|
+
}
|
|
71
|
+
if (val === undefined) return key;
|
|
72
|
+
if (typeof val === "function") return val(...args);
|
|
73
|
+
// Replace {0}, {1}, ... placeholders with actual arguments
|
|
74
|
+
if (args.length > 0) {
|
|
75
|
+
let result: string = val;
|
|
76
|
+
for (let i = 0; i < args.length; i++) {
|
|
77
|
+
const arg = args[i] ?? "";
|
|
78
|
+
result = result.replace(new RegExp(`\\{${i}\\}`, "g"), arg);
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
return val;
|
|
83
|
+
},
|
|
84
|
+
[lang, translations]
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<I18nContext.Provider value={{ lang, setLang, t }}>
|
|
89
|
+
{children}
|
|
90
|
+
</I18nContext.Provider>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function useTranslation() {
|
|
95
|
+
const ctx = useContext(I18nContext);
|
|
96
|
+
if (!ctx) throw new Error("useTranslation must be used within I18nProvider");
|
|
97
|
+
return ctx;
|
|
98
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// ─── English Translations ───────────────────────────────
|
|
2
|
+
// This is the source of truth — all other languages match these keys.
|
|
3
|
+
|
|
4
|
+
const en: Record<string, string> = {
|
|
5
|
+
// Sidebar
|
|
6
|
+
"nav.dashboard": "Dashboard",
|
|
7
|
+
"nav.models": "Models",
|
|
8
|
+
"nav.providers": "Providers",
|
|
9
|
+
"nav.sessions": "Sessions",
|
|
10
|
+
"nav.memory": "Memory",
|
|
11
|
+
"nav.settings": "Settings",
|
|
12
|
+
"app.subtitle": "Configuration Manager",
|
|
13
|
+
"app.version": "pi-switch v0.1.0",
|
|
14
|
+
|
|
15
|
+
// Dashboard
|
|
16
|
+
"dashboard.title": "Usage Statistics",
|
|
17
|
+
"dashboard.requests_count": "{0} requests · {1} total cost",
|
|
18
|
+
"dashboard.range.today": "Today",
|
|
19
|
+
"dashboard.range.7d": "7 Days",
|
|
20
|
+
"dashboard.range.30d": "30 Days",
|
|
21
|
+
"dashboard.range.custom": "Custom",
|
|
22
|
+
"dashboard.to": "to",
|
|
23
|
+
"dashboard.total_tokens": "Total Tokens",
|
|
24
|
+
"dashboard.total_requests": "Total Requests",
|
|
25
|
+
"dashboard.total_cost": "Total Cost",
|
|
26
|
+
"dashboard.cache_hit_rate": "Cache Hit Rate",
|
|
27
|
+
"dashboard.input": "Input",
|
|
28
|
+
"dashboard.output": "Output",
|
|
29
|
+
"dashboard.cache_create": "Cache Create",
|
|
30
|
+
"dashboard.cache_hit": "Cache Hit",
|
|
31
|
+
"dashboard.api_calls": "API calls made",
|
|
32
|
+
"dashboard.usd": "USD",
|
|
33
|
+
"dashboard.usage_trend": "Usage Trend",
|
|
34
|
+
"dashboard.tokens_k": "Tokens (K)",
|
|
35
|
+
"dashboard.cost_label": "Cost ($)",
|
|
36
|
+
"dashboard.request_log": "Request Log",
|
|
37
|
+
"dashboard.provider_stats": "Provider Stats",
|
|
38
|
+
"dashboard.model_stats": "Model Stats",
|
|
39
|
+
"dashboard.time": "Time",
|
|
40
|
+
"dashboard.provider": "Provider",
|
|
41
|
+
"dashboard.model": "Model",
|
|
42
|
+
"dashboard.cost": "Cost",
|
|
43
|
+
"dashboard.requests": "Requests",
|
|
44
|
+
"dashboard.status": "Status",
|
|
45
|
+
"dashboard.no_data": "No request data in this time range",
|
|
46
|
+
"dashboard.provider_stats_desc": "Provider statistics aggregated by provider",
|
|
47
|
+
"dashboard.model_stats_desc": "Model statistics aggregated by model",
|
|
48
|
+
|
|
49
|
+
// Models
|
|
50
|
+
"models.title": "Models",
|
|
51
|
+
"models.search_placeholder": "Search models...",
|
|
52
|
+
"models.filter_all": "All Providers",
|
|
53
|
+
"models.add_model": "Add Model",
|
|
54
|
+
"models.edit_model": "Edit Model",
|
|
55
|
+
"models.delete_model": "Delete Model",
|
|
56
|
+
"models.no_models": "No models found",
|
|
57
|
+
"models.enabled": "Enabled",
|
|
58
|
+
"models.disabled": "Disabled",
|
|
59
|
+
"models.enable": "Enable",
|
|
60
|
+
"models.disable": "Disable",
|
|
61
|
+
"models.capabilities": "Capabilities",
|
|
62
|
+
"models.reasoning": "Reasoning",
|
|
63
|
+
"models.image_input": "Image Input",
|
|
64
|
+
"models.context_window": "Context Window",
|
|
65
|
+
"models.max_tokens": "Max Tokens",
|
|
66
|
+
"models.cost_input": "Input",
|
|
67
|
+
"models.cost_output": "Output",
|
|
68
|
+
"models.cost_cache_read": "Cache Read",
|
|
69
|
+
"models.cost_cache_write": "Cache Write",
|
|
70
|
+
"models.save": "Save",
|
|
71
|
+
"models.cancel": "Cancel",
|
|
72
|
+
"models.delete_confirm": "Are you sure you want to delete this model?",
|
|
73
|
+
|
|
74
|
+
// Providers
|
|
75
|
+
"providers.title": "Providers",
|
|
76
|
+
"providers.add_provider": "Add Provider",
|
|
77
|
+
"providers.edit_provider": "Edit Provider",
|
|
78
|
+
"providers.delete_provider": "Delete Provider",
|
|
79
|
+
"providers.custom": "Custom",
|
|
80
|
+
"providers.builtin": "Built-in",
|
|
81
|
+
"providers.no_auth": "No Auth",
|
|
82
|
+
"providers.configured": "Configured",
|
|
83
|
+
"providers.api_key": "API Key",
|
|
84
|
+
"providers.base_url": "Base URL",
|
|
85
|
+
"providers.api_type": "API Type",
|
|
86
|
+
"providers.headers": "Headers",
|
|
87
|
+
"providers.auth_method": "Auth Method",
|
|
88
|
+
"providers.save": "Save",
|
|
89
|
+
"providers.cancel": "Cancel",
|
|
90
|
+
"providers.delete_confirm": "Are you sure you want to delete this provider?",
|
|
91
|
+
"providers.set_api_key": "Set API Key",
|
|
92
|
+
"providers.remove_api_key": "Remove API Key",
|
|
93
|
+
"providers.models_count": "{0} models",
|
|
94
|
+
|
|
95
|
+
// Sessions
|
|
96
|
+
"sessions.title": "Sessions",
|
|
97
|
+
"sessions.summary": "{0} sessions across {1} projects",
|
|
98
|
+
"sessions.filter_placeholder": "Filter by project name...",
|
|
99
|
+
"sessions.no_sessions": "No sessions found",
|
|
100
|
+
"sessions.last_active": "Last active {0}",
|
|
101
|
+
"sessions.sessions_count": "{0} sessions",
|
|
102
|
+
"sessions.messages": "{0} messages",
|
|
103
|
+
"sessions.delete_title": "Delete Session",
|
|
104
|
+
"sessions.delete_confirm": "Are you sure you want to delete this session?",
|
|
105
|
+
"sessions.delete_permanent": "This will permanently delete the session file from disk.",
|
|
106
|
+
"sessions.cancel": "Cancel",
|
|
107
|
+
"sessions.delete": "Delete",
|
|
108
|
+
"sessions.deleting": "Deleting...",
|
|
109
|
+
"sessions.protected": "Updated in the last 3 days — cannot delete",
|
|
110
|
+
"sessions.delete_failed": "Failed to delete session file",
|
|
111
|
+
"sessions.delete_error": "Error deleting session",
|
|
112
|
+
|
|
113
|
+
// Memory
|
|
114
|
+
"memory.title": "Memory",
|
|
115
|
+
"memory.summary": "pi-hermes-memory · {0} total lines across {1} files",
|
|
116
|
+
"memory.no_memory": "No memory files found",
|
|
117
|
+
"memory.no_memory_desc": "pi-hermes-memory extension is not installed",
|
|
118
|
+
"memory.project_memories": "Project Memories",
|
|
119
|
+
"memory.user_profile": "User Profile",
|
|
120
|
+
"memory.failure_records": "Failure Records",
|
|
121
|
+
"memory.lines": "{0} lines",
|
|
122
|
+
"memory.updated": "Updated {0}",
|
|
123
|
+
|
|
124
|
+
// Settings
|
|
125
|
+
"settings.title": "Settings",
|
|
126
|
+
"settings.defaults": "Defaults",
|
|
127
|
+
"settings.default_provider": "Default Provider",
|
|
128
|
+
"settings.default_model": "Default Model",
|
|
129
|
+
"settings.default_thinking": "Default Thinking Level",
|
|
130
|
+
"settings.project_trust": "Project Trust",
|
|
131
|
+
"settings.none": "— None —",
|
|
132
|
+
"settings.appearance": "Appearance",
|
|
133
|
+
"settings.light": "Light",
|
|
134
|
+
"settings.dark": "Dark",
|
|
135
|
+
"settings.system": "System",
|
|
136
|
+
"settings.hide_thinking": "Hide thinking blocks",
|
|
137
|
+
"settings.enabled_models": "Enabled Models",
|
|
138
|
+
"settings.no_models_enabled": "No models enabled. Enable models from the Models page.",
|
|
139
|
+
"settings.packages": "Extensions & Packages",
|
|
140
|
+
"settings.package_placeholder": "npm:package-name",
|
|
141
|
+
"settings.add": "Add",
|
|
142
|
+
"settings.no_packages": "No packages installed",
|
|
143
|
+
"settings.import_export": "Import & Export",
|
|
144
|
+
"settings.export": "Export Config",
|
|
145
|
+
"settings.import": "Import Config",
|
|
146
|
+
"settings.import_error": "Invalid config file format",
|
|
147
|
+
"settings.danger_zone": "Danger Zone",
|
|
148
|
+
"settings.reset": "Reset to Defaults",
|
|
149
|
+
"settings.reset_title": "Reset Configuration?",
|
|
150
|
+
"settings.reset_confirm": "This will reset all settings, auth keys, and custom providers to defaults. Changes are written directly to your pi config files (~/.pi/agent/). This action cannot be undone.",
|
|
151
|
+
"settings.cancel": "Cancel",
|
|
152
|
+
"settings.reset_action": "Reset",
|
|
153
|
+
|
|
154
|
+
// InitGate / Loading
|
|
155
|
+
"loading.config": "Loading pi configuration...",
|
|
156
|
+
"loading.initializing": "Initializing...",
|
|
157
|
+
"loading.error_title": "Failed to Load Configuration",
|
|
158
|
+
"loading.retry": "Retry",
|
|
159
|
+
|
|
160
|
+
// Language Switcher
|
|
161
|
+
"language.label": "Language",
|
|
162
|
+
"language.en": "English",
|
|
163
|
+
"language.zh-CN": "简体中文",
|
|
164
|
+
"language.zh-TW": "繁體中文",
|
|
165
|
+
"language.ja": "日本語",
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export default en;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import en from "./en";
|
|
2
|
+
import zhCN from "./zh-CN";
|
|
3
|
+
import zhTW from "./zh-TW";
|
|
4
|
+
import ja from "./ja";
|
|
5
|
+
import type { Translations } from "../i18n";
|
|
6
|
+
|
|
7
|
+
const translations: Translations = {
|
|
8
|
+
en,
|
|
9
|
+
"zh-CN": zhCN,
|
|
10
|
+
"zh-TW": zhTW,
|
|
11
|
+
ja,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default translations;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// ─── Japanese Translations ─────────────────────────────
|
|
2
|
+
|
|
3
|
+
const ja: Record<string, string> = {
|
|
4
|
+
"nav.dashboard": "ダッシュボード",
|
|
5
|
+
"nav.models": "モデル",
|
|
6
|
+
"nav.providers": "プロバイダー",
|
|
7
|
+
"nav.sessions": "セッション",
|
|
8
|
+
"nav.memory": "メモリ",
|
|
9
|
+
"nav.settings": "設定",
|
|
10
|
+
"app.subtitle": "設定マネージャー",
|
|
11
|
+
"app.version": "pi-switch v0.1.0",
|
|
12
|
+
|
|
13
|
+
"dashboard.title": "使用統計",
|
|
14
|
+
"dashboard.requests_count": "{0} リクエスト · 総コスト {1}",
|
|
15
|
+
"dashboard.range.today": "今日",
|
|
16
|
+
"dashboard.range.7d": "7日",
|
|
17
|
+
"dashboard.range.30d": "30日",
|
|
18
|
+
"dashboard.range.custom": "カスタム",
|
|
19
|
+
"dashboard.to": "から",
|
|
20
|
+
"dashboard.total_tokens": "消費 Tokens",
|
|
21
|
+
"dashboard.total_requests": "総リクエスト数",
|
|
22
|
+
"dashboard.total_cost": "総コスト",
|
|
23
|
+
"dashboard.cache_hit_rate": "キャッシュヒット率",
|
|
24
|
+
"dashboard.input": "入力",
|
|
25
|
+
"dashboard.output": "出力",
|
|
26
|
+
"dashboard.cache_create": "キャッシュ作成",
|
|
27
|
+
"dashboard.cache_hit": "キャッシュヒット",
|
|
28
|
+
"dashboard.api_calls": "API 呼び出し",
|
|
29
|
+
"dashboard.usd": "USD",
|
|
30
|
+
"dashboard.usage_trend": "使用傾向",
|
|
31
|
+
"dashboard.tokens_k": "Tokens (K)",
|
|
32
|
+
"dashboard.cost_label": "コスト ($)",
|
|
33
|
+
"dashboard.request_log": "リクエストログ",
|
|
34
|
+
"dashboard.provider_stats": "プロバイダー統計",
|
|
35
|
+
"dashboard.model_stats": "モデル統計",
|
|
36
|
+
"dashboard.time": "時間",
|
|
37
|
+
"dashboard.provider": "プロバイダー",
|
|
38
|
+
"dashboard.model": "モデル",
|
|
39
|
+
"dashboard.cost": "コスト",
|
|
40
|
+
"dashboard.requests": "リクエスト",
|
|
41
|
+
"dashboard.status": "ステータス",
|
|
42
|
+
"dashboard.no_data": "この期間にリクエストデータはありません",
|
|
43
|
+
"dashboard.provider_stats_desc": "プロバイダー別の集計統計",
|
|
44
|
+
"dashboard.model_stats_desc": "モデル別の集計統計",
|
|
45
|
+
|
|
46
|
+
"models.title": "モデル管理",
|
|
47
|
+
"models.search_placeholder": "モデルを検索...",
|
|
48
|
+
"models.filter_all": "全プロバイダー",
|
|
49
|
+
"models.add_model": "モデル追加",
|
|
50
|
+
"models.edit_model": "モデル編集",
|
|
51
|
+
"models.delete_model": "モデル削除",
|
|
52
|
+
"models.no_models": "モデルが見つかりません",
|
|
53
|
+
"models.enabled": "有効",
|
|
54
|
+
"models.disabled": "無効",
|
|
55
|
+
"models.enable": "有効化",
|
|
56
|
+
"models.disable": "無効化",
|
|
57
|
+
"models.capabilities": "機能",
|
|
58
|
+
"models.reasoning": "推論",
|
|
59
|
+
"models.image_input": "画像入力",
|
|
60
|
+
"models.context_window": "コンテキストウィンドウ",
|
|
61
|
+
"models.max_tokens": "最大 Tokens",
|
|
62
|
+
"models.cost_input": "入力",
|
|
63
|
+
"models.cost_output": "出力",
|
|
64
|
+
"models.cost_cache_read": "キャッシュ読み取り",
|
|
65
|
+
"models.cost_cache_write": "キャッシュ書き込み",
|
|
66
|
+
"models.save": "保存",
|
|
67
|
+
"models.cancel": "キャンセル",
|
|
68
|
+
"models.delete_confirm": "このモデルを削除してもよろしいですか?",
|
|
69
|
+
|
|
70
|
+
"providers.title": "プロバイダー管理",
|
|
71
|
+
"providers.add_provider": "プロバイダー追加",
|
|
72
|
+
"providers.edit_provider": "プロバイダー編集",
|
|
73
|
+
"providers.delete_provider": "プロバイダー削除",
|
|
74
|
+
"providers.custom": "カスタム",
|
|
75
|
+
"providers.builtin": "ビルトイン",
|
|
76
|
+
"providers.no_auth": "未設定",
|
|
77
|
+
"providers.configured": "設定済み",
|
|
78
|
+
"providers.api_key": "API Key",
|
|
79
|
+
"providers.base_url": "ベースURL",
|
|
80
|
+
"providers.api_type": "API タイプ",
|
|
81
|
+
"providers.headers": "ヘッダー",
|
|
82
|
+
"providers.auth_method": "認証方法",
|
|
83
|
+
"providers.save": "保存",
|
|
84
|
+
"providers.cancel": "キャンセル",
|
|
85
|
+
"providers.delete_confirm": "このプロバイダーを削除してもよろしいですか?",
|
|
86
|
+
"providers.set_api_key": "API Key 設定",
|
|
87
|
+
"providers.remove_api_key": "API Key 削除",
|
|
88
|
+
"providers.models_count": "{0} モデル",
|
|
89
|
+
|
|
90
|
+
"sessions.title": "セッション一覧",
|
|
91
|
+
"sessions.summary": "合計 {0} セッション、{1} プロジェクト",
|
|
92
|
+
"sessions.filter_placeholder": "プロジェクト名でフィルター...",
|
|
93
|
+
"sessions.no_sessions": "セッションが見つかりません",
|
|
94
|
+
"sessions.last_active": "最終アクティブ {0}",
|
|
95
|
+
"sessions.sessions_count": "{0} セッション",
|
|
96
|
+
"sessions.messages": "{0} メッセージ",
|
|
97
|
+
"sessions.delete_title": "セッション削除",
|
|
98
|
+
"sessions.delete_confirm": "このセッションを削除してもよろしいですか?",
|
|
99
|
+
"sessions.delete_permanent": "この操作はディスクからセッションファイルを完全に削除します。",
|
|
100
|
+
"sessions.cancel": "キャンセル",
|
|
101
|
+
"sessions.delete": "削除",
|
|
102
|
+
"sessions.deleting": "削除中...",
|
|
103
|
+
"sessions.protected": "3日以内に更新されたため削除できません",
|
|
104
|
+
"sessions.delete_failed": "セッションファイルの削除に失敗しました",
|
|
105
|
+
"sessions.delete_error": "削除中にエラーが発生しました",
|
|
106
|
+
|
|
107
|
+
"memory.title": "メモリ表示",
|
|
108
|
+
"memory.summary": "pi-hermes-memory · 合計 {0} 行、{1} ファイル",
|
|
109
|
+
"memory.no_memory": "メモリファイルが見つかりません",
|
|
110
|
+
"memory.no_memory_desc": "pi-hermes-memory 拡張機能がインストールされていません",
|
|
111
|
+
"memory.project_memories": "プロジェクトメモリ",
|
|
112
|
+
"memory.user_profile": "ユーザープロファイル",
|
|
113
|
+
"memory.failure_records": "障害記録",
|
|
114
|
+
"memory.lines": "{0} 行",
|
|
115
|
+
"memory.updated": "更新日 {0}",
|
|
116
|
+
|
|
117
|
+
"settings.title": "設定",
|
|
118
|
+
"settings.defaults": "デフォルト",
|
|
119
|
+
"settings.default_provider": "デフォルトプロバイダー",
|
|
120
|
+
"settings.default_model": "デフォルトモデル",
|
|
121
|
+
"settings.default_thinking": "デフォルト思考レベル",
|
|
122
|
+
"settings.project_trust": "プロジェクト信頼",
|
|
123
|
+
"settings.none": "— なし —",
|
|
124
|
+
"settings.appearance": "外観",
|
|
125
|
+
"settings.light": "ライト",
|
|
126
|
+
"settings.dark": "ダーク",
|
|
127
|
+
"settings.system": "システム",
|
|
128
|
+
"settings.hide_thinking": "思考ブロックを隠す",
|
|
129
|
+
"settings.enabled_models": "有効なモデル",
|
|
130
|
+
"settings.no_models_enabled": "有効なモデルはありません。「モデル」ページで有効化してください。",
|
|
131
|
+
"settings.packages": "拡張機能とパッケージ",
|
|
132
|
+
"settings.package_placeholder": "npm:package-name",
|
|
133
|
+
"settings.add": "追加",
|
|
134
|
+
"settings.no_packages": "パッケージがインストールされていません",
|
|
135
|
+
"settings.import_export": "インポートとエクスポート",
|
|
136
|
+
"settings.export": "設定をエクスポート",
|
|
137
|
+
"settings.import": "設定をインポート",
|
|
138
|
+
"settings.import_error": "無効な設定ファイル形式です",
|
|
139
|
+
"settings.danger_zone": "危険ゾーン",
|
|
140
|
+
"settings.reset": "デフォルトにリセット",
|
|
141
|
+
"settings.reset_title": "設定をリセットしますか?",
|
|
142
|
+
"settings.reset_confirm": "すべての設定、認証キー、カスタムプロバイダーをデフォルトにリセットします。変更は pi 設定ファイル (~/.pi/agent/) に直接書き込まれます。この操作は元に戻せません。",
|
|
143
|
+
"settings.cancel": "キャンセル",
|
|
144
|
+
"settings.reset_action": "リセット",
|
|
145
|
+
|
|
146
|
+
"loading.config": "pi 設定を読み込み中...",
|
|
147
|
+
"loading.initializing": "初期化中...",
|
|
148
|
+
"loading.error_title": "設定の読み込みに失敗しました",
|
|
149
|
+
"loading.retry": "再試行",
|
|
150
|
+
|
|
151
|
+
"language.label": "言語",
|
|
152
|
+
"language.en": "English",
|
|
153
|
+
"language.zh-CN": "简体中文",
|
|
154
|
+
"language.zh-TW": "繁體中文",
|
|
155
|
+
"language.ja": "日本語",
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export default ja;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// ─── Simplified Chinese Translations ────────────────────
|
|
2
|
+
|
|
3
|
+
const zhCN: Record<string, string> = {
|
|
4
|
+
"nav.dashboard": "仪表盘",
|
|
5
|
+
"nav.models": "模型",
|
|
6
|
+
"nav.providers": "提供商",
|
|
7
|
+
"nav.sessions": "会话",
|
|
8
|
+
"nav.memory": "记忆",
|
|
9
|
+
"nav.settings": "设置",
|
|
10
|
+
"app.subtitle": "配置管理器",
|
|
11
|
+
"app.version": "pi-switch v0.1.0",
|
|
12
|
+
|
|
13
|
+
"dashboard.title": "使用统计",
|
|
14
|
+
"dashboard.requests_count": "{0} 次请求 · 总成本 {1}",
|
|
15
|
+
"dashboard.range.today": "当天",
|
|
16
|
+
"dashboard.range.7d": "7天",
|
|
17
|
+
"dashboard.range.30d": "30天",
|
|
18
|
+
"dashboard.range.custom": "自定义",
|
|
19
|
+
"dashboard.to": "至",
|
|
20
|
+
"dashboard.total_tokens": "消耗 Tokens",
|
|
21
|
+
"dashboard.total_requests": "总请求数",
|
|
22
|
+
"dashboard.total_cost": "总成本",
|
|
23
|
+
"dashboard.cache_hit_rate": "缓存命中率",
|
|
24
|
+
"dashboard.input": "新增输入",
|
|
25
|
+
"dashboard.output": "Output",
|
|
26
|
+
"dashboard.cache_create": "创建",
|
|
27
|
+
"dashboard.cache_hit": "命中",
|
|
28
|
+
"dashboard.api_calls": "API 调用次数",
|
|
29
|
+
"dashboard.usd": "USD",
|
|
30
|
+
"dashboard.usage_trend": "使用趋势",
|
|
31
|
+
"dashboard.tokens_k": "Tokens (K)",
|
|
32
|
+
"dashboard.cost_label": "成本 ($)",
|
|
33
|
+
"dashboard.request_log": "请求日志",
|
|
34
|
+
"dashboard.provider_stats": "Provider 统计",
|
|
35
|
+
"dashboard.model_stats": "Model 统计",
|
|
36
|
+
"dashboard.time": "时间",
|
|
37
|
+
"dashboard.provider": "供应商",
|
|
38
|
+
"dashboard.model": "计费模型",
|
|
39
|
+
"dashboard.cost": "总成本",
|
|
40
|
+
"dashboard.requests": "请求数",
|
|
41
|
+
"dashboard.status": "状态",
|
|
42
|
+
"dashboard.no_data": "该时间范围内无请求数据",
|
|
43
|
+
"dashboard.provider_stats_desc": "按供应商聚合的统计数据",
|
|
44
|
+
"dashboard.model_stats_desc": "按模型聚合的统计数据",
|
|
45
|
+
|
|
46
|
+
"models.title": "模型管理",
|
|
47
|
+
"models.search_placeholder": "搜索模型...",
|
|
48
|
+
"models.filter_all": "全部提供商",
|
|
49
|
+
"models.add_model": "添加模型",
|
|
50
|
+
"models.edit_model": "编辑模型",
|
|
51
|
+
"models.delete_model": "删除模型",
|
|
52
|
+
"models.no_models": "未找到模型",
|
|
53
|
+
"models.enabled": "已启用",
|
|
54
|
+
"models.disabled": "已禁用",
|
|
55
|
+
"models.enable": "启用",
|
|
56
|
+
"models.disable": "禁用",
|
|
57
|
+
"models.capabilities": "能力",
|
|
58
|
+
"models.reasoning": "推理",
|
|
59
|
+
"models.image_input": "图片输入",
|
|
60
|
+
"models.context_window": "上下文窗口",
|
|
61
|
+
"models.max_tokens": "最大 Token",
|
|
62
|
+
"models.cost_input": "输入",
|
|
63
|
+
"models.cost_output": "输出",
|
|
64
|
+
"models.cost_cache_read": "缓存读取",
|
|
65
|
+
"models.cost_cache_write": "缓存写入",
|
|
66
|
+
"models.save": "保存",
|
|
67
|
+
"models.cancel": "取消",
|
|
68
|
+
"models.delete_confirm": "确定要删除此模型吗?",
|
|
69
|
+
|
|
70
|
+
"providers.title": "提供商管理",
|
|
71
|
+
"providers.add_provider": "添加提供商",
|
|
72
|
+
"providers.edit_provider": "编辑提供商",
|
|
73
|
+
"providers.delete_provider": "删除提供商",
|
|
74
|
+
"providers.custom": "自定义",
|
|
75
|
+
"providers.builtin": "内置",
|
|
76
|
+
"providers.no_auth": "未配置",
|
|
77
|
+
"providers.configured": "已配置",
|
|
78
|
+
"providers.api_key": "API Key",
|
|
79
|
+
"providers.base_url": "基础地址",
|
|
80
|
+
"providers.api_type": "API 类型",
|
|
81
|
+
"providers.headers": "请求头",
|
|
82
|
+
"providers.auth_method": "认证方式",
|
|
83
|
+
"providers.save": "保存",
|
|
84
|
+
"providers.cancel": "取消",
|
|
85
|
+
"providers.delete_confirm": "确定要删除此提供商吗?",
|
|
86
|
+
"providers.set_api_key": "设置 API Key",
|
|
87
|
+
"providers.remove_api_key": "移除 API Key",
|
|
88
|
+
"providers.models_count": "{0} 个模型",
|
|
89
|
+
|
|
90
|
+
"sessions.title": "会话列表",
|
|
91
|
+
"sessions.summary": "共 {0} 个会话,分布在 {1} 个项目",
|
|
92
|
+
"sessions.filter_placeholder": "按项目名称搜索...",
|
|
93
|
+
"sessions.no_sessions": "未找到会话",
|
|
94
|
+
"sessions.last_active": "最近活跃 {0}",
|
|
95
|
+
"sessions.sessions_count": "{0} 个会话",
|
|
96
|
+
"sessions.messages": "{0} 条消息",
|
|
97
|
+
"sessions.delete_title": "删除会话",
|
|
98
|
+
"sessions.delete_confirm": "确定要删除此会话吗?",
|
|
99
|
+
"sessions.delete_permanent": "这将永久删除磁盘上的会话文件。",
|
|
100
|
+
"sessions.cancel": "取消",
|
|
101
|
+
"sessions.delete": "删除",
|
|
102
|
+
"sessions.deleting": "删除中...",
|
|
103
|
+
"sessions.protected": "近 3 天有更新,无法删除",
|
|
104
|
+
"sessions.delete_failed": "删除会话文件失败",
|
|
105
|
+
"sessions.delete_error": "删除时发生错误",
|
|
106
|
+
|
|
107
|
+
"memory.title": "记忆查看",
|
|
108
|
+
"memory.summary": "pi-hermes-memory · 共 {0} 行,{1} 个文件",
|
|
109
|
+
"memory.no_memory": "未找到记忆文件",
|
|
110
|
+
"memory.no_memory_desc": "未安装 pi-hermes-memory 扩展",
|
|
111
|
+
"memory.project_memories": "项目记忆",
|
|
112
|
+
"memory.user_profile": "用户画像",
|
|
113
|
+
"memory.failure_records": "故障记录",
|
|
114
|
+
"memory.lines": "{0} 行",
|
|
115
|
+
"memory.updated": "更新于 {0}",
|
|
116
|
+
|
|
117
|
+
"settings.title": "设置",
|
|
118
|
+
"settings.defaults": "默认值",
|
|
119
|
+
"settings.default_provider": "默认提供商",
|
|
120
|
+
"settings.default_model": "默认模型",
|
|
121
|
+
"settings.default_thinking": "默认思考级别",
|
|
122
|
+
"settings.project_trust": "项目信任",
|
|
123
|
+
"settings.none": "— 无 —",
|
|
124
|
+
"settings.appearance": "外观",
|
|
125
|
+
"settings.light": "浅色",
|
|
126
|
+
"settings.dark": "深色",
|
|
127
|
+
"settings.system": "跟随系统",
|
|
128
|
+
"settings.hide_thinking": "隐藏思考过程",
|
|
129
|
+
"settings.enabled_models": "已启用模型",
|
|
130
|
+
"settings.no_models_enabled": "暂无已启用模型。请在「模型」页面启用。",
|
|
131
|
+
"settings.packages": "扩展与包",
|
|
132
|
+
"settings.package_placeholder": "npm:package-name",
|
|
133
|
+
"settings.add": "添加",
|
|
134
|
+
"settings.no_packages": "未安装任何包",
|
|
135
|
+
"settings.import_export": "导入与导出",
|
|
136
|
+
"settings.export": "导出配置",
|
|
137
|
+
"settings.import": "导入配置",
|
|
138
|
+
"settings.import_error": "无效的配置文件格式",
|
|
139
|
+
"settings.danger_zone": "危险区域",
|
|
140
|
+
"settings.reset": "重置为默认",
|
|
141
|
+
"settings.reset_title": "重置配置?",
|
|
142
|
+
"settings.reset_confirm": "此操作将重置所有设置、认证密钥和自定义提供商标为默认值。更改将直接写入你的 pi 配置文件 (~/.pi/agent/)。此操作不可撤销。",
|
|
143
|
+
"settings.cancel": "取消",
|
|
144
|
+
"settings.reset_action": "重置",
|
|
145
|
+
|
|
146
|
+
"loading.config": "正在加载 pi 配置...",
|
|
147
|
+
"loading.initializing": "正在初始化...",
|
|
148
|
+
"loading.error_title": "加载配置失败",
|
|
149
|
+
"loading.retry": "重试",
|
|
150
|
+
|
|
151
|
+
"language.label": "语言",
|
|
152
|
+
"language.en": "English",
|
|
153
|
+
"language.zh-CN": "简体中文",
|
|
154
|
+
"language.zh-TW": "繁體中文",
|
|
155
|
+
"language.ja": "日本語",
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export default zhCN;
|