@koishi-ce/client 1.0.3 → 1.1.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.
Files changed (56) hide show
  1. package/README.md +2 -2
  2. package/app/home/home.vue +4 -1
  3. package/app/home/index.ts +2 -1
  4. package/app/home/welcome.vue +9 -26
  5. package/app/index.ts +8 -2
  6. package/app/layout/header.vue +12 -4
  7. package/app/layout/layout.vue +4 -1
  8. package/app/layout/menu-item.vue +3 -1
  9. package/app/settings/index.ts +3 -2
  10. package/app/settings/settings.vue +9 -7
  11. package/app/settings/theme.vue +4 -1
  12. package/app/status/loading.vue +7 -2
  13. package/app/theme/activity/button.vue +4 -1
  14. package/app/theme/activity/index.vue +12 -4
  15. package/app/theme/activity/item.vue +18 -4
  16. package/app/theme/activity/separator.vue +44 -12
  17. package/app/theme/blank.vue +7 -1
  18. package/app/theme/index.ts +7 -2
  19. package/app/theme/index.vue +6 -2
  20. package/app/theme/menu/menu-item.vue +10 -4
  21. package/app/theme/menu/menu.vue +9 -4
  22. package/client/components/chat/overlay.vue +38 -13
  23. package/client/components/common/k-hint.vue +3 -1
  24. package/client/components/dynamic.vue +2 -1
  25. package/client/components/icons/index.ts +7 -2
  26. package/client/components/index.ts +8 -2
  27. package/client/components/link.ts +5 -2
  28. package/client/components/perms.vue +22 -5
  29. package/client/components/slot.ts +19 -4
  30. package/client/context.ts +12 -4
  31. package/client/data.ts +57 -26
  32. package/client/index.ts +2 -1
  33. package/client/locales/de-DE.yml +47 -0
  34. package/client/locales/en-US.yml +47 -0
  35. package/client/locales/fr-FR.yml +47 -0
  36. package/client/locales/ja-JP.yml +47 -0
  37. package/client/locales/ru-RU.yml +47 -0
  38. package/client/locales/zh-CN.yml +47 -0
  39. package/client/locales/zh-TW.yml +47 -0
  40. package/client/plugins/action.ts +46 -13
  41. package/client/plugins/i18n.ts +118 -3
  42. package/client/plugins/loader.ts +67 -45
  43. package/client/plugins/router.ts +34 -11
  44. package/client/plugins/setting.ts +60 -16
  45. package/client/plugins/theme.ts +51 -11
  46. package/client/utils.ts +7 -2
  47. package/lib/bin.mjs +3 -3
  48. package/lib/{client-CaTn_gVG.mjs → client-C97iYPCr.mjs} +1 -1
  49. package/lib/index.d.ts +3 -4
  50. package/lib/index.mjs +1 -1
  51. package/lib/{src-DXaM1Kgh.mjs → src-BOakssV3.mjs} +2 -2
  52. package/package.json +3 -3
  53. package/src/bin.ts +10 -3
  54. package/src/index.ts +59 -15
  55. package/app/home/welcome.en-US.yml +0 -13
  56. package/app/home/welcome.zh-CN.yml +0 -13
@@ -18,19 +18,19 @@
18
18
  <k-icon name="chevron-right"/>
19
19
  </span>
20
20
  <span class="button bottom" @click.stop>
21
- <el-tooltip placement="top" content="缩小" :offset="20">
21
+ <el-tooltip placement="top" :content="t('overlay.zoomOut')" :offset="20">
22
22
  <k-icon name="search-minus" @click="scale -= 0.2"/>
23
23
  </el-tooltip>
24
- <el-tooltip placement="top" content="放大" :offset="20">
24
+ <el-tooltip placement="top" :content="t('overlay.zoomIn')" :offset="20">
25
25
  <k-icon name="search-plus" @click="scale += 0.2"/>
26
26
  </el-tooltip>
27
- <el-tooltip placement="top" content="复原" :offset="20">
27
+ <el-tooltip placement="top" :content="t('overlay.reset')" :offset="20">
28
28
  <k-icon name="expand" @click="scale = 1, rotate = 0"/>
29
29
  </el-tooltip>
30
- <el-tooltip placement="top" content="逆时针旋转" :offset="20">
30
+ <el-tooltip placement="top" :content="t('overlay.rotateLeft')" :offset="20">
31
31
  <k-icon name="undo" @click="rotate -= 90"/>
32
32
  </el-tooltip>
33
- <el-tooltip placement="top" content="逆时针旋转" :offset="20">
33
+ <el-tooltip placement="top" :content="t('overlay.rotateRight')" :offset="20">
34
34
  <k-icon name="redo" @click="rotate += 90"/>
35
35
  </el-tooltip>
36
36
  </span>
@@ -42,9 +42,18 @@
42
42
  </template>
43
43
 
44
44
  <script lang="ts" setup>
45
- import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
45
+ import {
46
+ computed,
47
+ onBeforeUnmount,
48
+ onMounted,
49
+ ref,
50
+ watch,
51
+ } from "vue";
52
+ import { useI18n } from "vue-i18n";
46
53
  import { shared } from "./utils";
47
54
 
55
+ const { t } = useI18n();
56
+
48
57
  // 用户手动调整的缩放与旋转量(复原即回到 1 / 0)
49
58
  const scale = ref(1);
50
59
  const rotate = ref(0);
@@ -58,7 +67,9 @@ const transform = computed(() => {
58
67
  const siblings = computed(() => {
59
68
  if (!shared.overlayImage) return;
60
69
  const elements = Array.from(
61
- document.querySelectorAll<HTMLImageElement>(".chat-image"),
70
+ document.querySelectorAll<HTMLImageElement>(
71
+ ".chat-image",
72
+ ),
62
73
  );
63
74
  const index = elements.indexOf(shared.overlayImage);
64
75
  return {
@@ -69,10 +80,15 @@ const siblings = computed(() => {
69
80
 
70
81
  // 初始(适配屏幕)缩放比:按视口剩余空间把图片等比缩小,不放大
71
82
  const defaultScale = computed(() => {
72
- const { naturalHeight, naturalWidth } = shared.overlayImage;
83
+ const { naturalHeight, naturalWidth } =
84
+ shared.overlayImage;
73
85
  const maxHeight = innerHeight - paddingVertical * 2;
74
86
  const maxWidth = innerWidth - paddingHorizontal * 2;
75
- return Math.min(1, maxHeight / naturalHeight, maxWidth / naturalWidth);
87
+ return Math.min(
88
+ 1,
89
+ maxHeight / naturalHeight,
90
+ maxWidth / naturalWidth,
91
+ );
76
92
  });
77
93
 
78
94
  // 切换/关闭查看器时重置手动缩放与旋转;
@@ -96,7 +112,10 @@ function setImage(el: HTMLImageElement) {
96
112
  }
97
113
 
98
114
  /** 把大图元素摆到原图片所在的位置与尺寸(关闭时的"飞回"动画终点) */
99
- function moveToOrigin(el: HTMLImageElement, origin = shared.overlayImage) {
115
+ function moveToOrigin(
116
+ el: HTMLImageElement,
117
+ origin = shared.overlayImage,
118
+ ) {
100
119
  const { height, width } = origin;
101
120
  const { left, top } = origin.getBoundingClientRect();
102
121
  el.style.width = `${width}px`;
@@ -112,7 +131,8 @@ const paddingHorizontal = 0;
112
131
 
113
132
  /** 把图片按适配缩放比居中摆放到视口中央 */
114
133
  function moveToCenter(el: HTMLImageElement) {
115
- const { naturalHeight, naturalWidth } = shared.overlayImage;
134
+ const { naturalHeight, naturalWidth } =
135
+ shared.overlayImage;
116
136
  const scale = defaultScale.value;
117
137
  const width = naturalWidth * scale;
118
138
  const height = naturalHeight * scale;
@@ -136,13 +156,18 @@ function onKeyDown(ev: KeyboardEvent) {
136
156
  ev.preventDefault();
137
157
  if (ev.key === "ArrowUp" || ev.key === "ArrowLeft") {
138
158
  setImage(siblings.value.prev);
139
- } else if (ev.key === "ArrowDown" || ev.key === "ArrowRight") {
159
+ } else if (
160
+ ev.key === "ArrowDown" ||
161
+ ev.key === "ArrowRight"
162
+ ) {
140
163
  setImage(siblings.value.next);
141
164
  } else if (ev.key === "Escape") {
142
165
  setImage(null);
143
166
  } else if (ev.key === "Enter") {
144
167
  // 关闭并把页面滚动到原图所在位置,便于继续浏览消息
145
- shared.overlayImage.offsetParent.scrollIntoView({ behavior: "smooth" });
168
+ shared.overlayImage.offsetParent.scrollIntoView({
169
+ behavior: "smooth",
170
+ });
146
171
  setImage(null);
147
172
  }
148
173
  }
@@ -32,7 +32,9 @@ const props = defineProps({
32
32
  const emit = defineEmits(["update:modelValue"]);
33
33
 
34
34
  // modelValue 被显式传入时才呈现手型光标并响应点击(开关语义)
35
- const pointer = computed(() => props.modelValue !== undefined);
35
+ const pointer = computed(
36
+ () => props.modelValue !== undefined,
37
+ );
36
38
 
37
39
  function onClick() {
38
40
  if (!pointer.value) return;
@@ -58,7 +58,8 @@ defineEmits(["update:modelValue"]);
58
58
  // 按本地 schema 标注的名称,从服务端下发的 schema 仓库中取出完整定义;
59
59
  // 元信息做一层合并,保留本地的 meta 覆盖权
60
60
  const inner = computed(() => {
61
- const hydrated = store.schema?.[props.schema?.meta.extra?.name];
61
+ const hydrated =
62
+ store.schema?.[props.schema?.meta.extra?.name];
62
63
  return hydrated && new Schema(hydrated);
63
64
  });
64
65
  </script>
@@ -116,7 +116,10 @@ register("undo", Undo);
116
116
  register("user", User);
117
117
 
118
118
  /** 向注册表登记一个图标(markRaw 避免组件被响应式代理) */
119
- export function register(name: string, component: Component) {
119
+ export function register(
120
+ name: string,
121
+ component: Component,
122
+ ) {
120
123
  registry[name] = markRaw(component);
121
124
  }
122
125
 
@@ -129,7 +132,9 @@ export function install(app: App) {
129
132
  name: String,
130
133
  },
131
134
  render(props: { name?: string }) {
132
- const component = props.name ? registry[props.name] : undefined;
135
+ const component = props.name
136
+ ? registry[props.name]
137
+ : undefined;
133
138
  return component && h(component);
134
139
  },
135
140
  }),
@@ -15,10 +15,16 @@
15
15
  // 无法解析(无 paths),故直接相对导入工作区内该包的浏览器端入口,
16
16
  // 与构建器 collectWorkspaceAliases 的映射目标一致
17
17
 
18
- import Element, { ElLoading, ElMessage, ElMessageBox } from "element-plus";
18
+ import Element, {
19
+ ElLoading,
20
+ ElMessage,
21
+ ElMessageBox,
22
+ } from "element-plus";
19
23
  import Markdown from "marked-vue";
20
24
  import type { App } from "vue";
21
- import components, { SchemaBase } from "../../../components/client/index.ts";
25
+ import components, {
26
+ SchemaBase,
27
+ } from "../../../components/client/index.ts";
22
28
 
23
29
  import { store } from "../data";
24
30
  import ChatImage from "./chat/image.vue";
@@ -21,7 +21,9 @@ const KActivityLink = defineComponent({
21
21
  setup(props, { slots }) {
22
22
  const ctx = useContext();
23
23
  return () => {
24
- const activity = props.id ? ctx.$router.pages[props.id] : undefined;
24
+ const activity = props.id
25
+ ? ctx.$router.pages[props.id]
26
+ : undefined;
25
27
  return h(
26
28
  RouterLink,
27
29
  {
@@ -30,7 +32,8 @@ const KActivityLink = defineComponent({
30
32
  activity?.path.replace(/:.+/, "")) as string,
31
33
  },
32
34
  {
33
- default: () => slots["default"]?.() ?? activity?.name,
35
+ default: () =>
36
+ slots["default"]?.() ?? activity?.name,
34
37
  },
35
38
  );
36
39
  };
@@ -32,7 +32,10 @@
32
32
  // schemastery-vue 链接(它是 components 的依赖,Bun 隔离布局下不跨包可见)
33
33
 
34
34
  import { store } from "@koishi-ce/client";
35
- import { type Schema, SchemaBase } from "@koishi-ce/components";
35
+ import {
36
+ type Schema,
37
+ SchemaBase,
38
+ } from "@koishi-ce/components";
36
39
  import type { CascaderOption } from "element-plus";
37
40
  import { computed, type PropType } from "vue";
38
41
 
@@ -53,15 +56,29 @@ const config = SchemaBase.useModel();
53
56
  * 逐段查找/创建级联节点;中间段(还有下级时)标记为 disabled,
54
57
  * 因为 el-cascader 的父节点勾选会影响子级,而中间段并非真实权限。
55
58
  */
56
- function addNode(nodes: CascaderOption[], path: string[], prefix = "") {
59
+ function addNode(
60
+ nodes: CascaderOption[],
61
+ path: string[],
62
+ prefix = "",
63
+ ) {
57
64
  const name = path.shift();
58
- let node = nodes.find((node) => node.value === prefix + name);
65
+ let node = nodes.find(
66
+ (node) => node.value === prefix + name,
67
+ );
59
68
  if (!node) {
60
- node = { value: prefix + name, label: name, disabled: !!path.length };
69
+ node = {
70
+ value: prefix + name,
71
+ label: name,
72
+ disabled: !!path.length,
73
+ };
61
74
  nodes.push(node);
62
75
  }
63
76
  if (!path.length) return;
64
- addNode((node.children ||= []), path, `${prefix + name}:`);
77
+ addNode(
78
+ (node.children ||= []),
79
+ path,
80
+ `${prefix + name}:`,
81
+ );
65
82
  }
66
83
 
67
84
  // 由全部权限名构建级联选项树
@@ -2,7 +2,12 @@
2
2
  // Copyright (c) 2019-present Shigma and Koishijs contributors.
3
3
  // Copyright (c) 2026-present Koishi-CE contributors.
4
4
 
5
- import { type App, type Component, defineComponent, h } from "vue";
5
+ import {
6
+ type App,
7
+ type Component,
8
+ defineComponent,
9
+ h,
10
+ } from "vue";
6
11
  import { useContext } from "../context";
7
12
 
8
13
  /** 插槽条目的基础形状:参与排序的组件 */
@@ -47,10 +52,15 @@ export const KSlot = defineComponent({
47
52
  ? []
48
53
  : [...(slots["default"]?.() || [])]
49
54
  .filter((node) => node.type === KSlotItem)
50
- .map((node) => ({ node, order: node.props?.["order"] || 0 }));
55
+ .map((node) => ({
56
+ node,
57
+ order: node.props?.["order"] || 0,
58
+ }));
51
59
  // external:ctx.slot() 注册的视图,disabled 的不渲染
52
60
  const external = [
53
- ...(props.name ? ctx.$router.views[props.name] || [] : []),
61
+ ...(props.name
62
+ ? ctx.$router.views[props.name] || []
63
+ : []),
54
64
  ]
55
65
  .filter((item) => !item.disabled?.())
56
66
  .map((item) => ({
@@ -85,7 +95,12 @@ function defineSlotComponent(name: string) {
85
95
  return defineComponent({
86
96
  inheritAttrs: false,
87
97
  setup(_, { slots, attrs }) {
88
- return () => h(KSlot, { name, data: attrs, single: true }, slots);
98
+ return () =>
99
+ h(
100
+ KSlot,
101
+ { name, data: attrs, single: true },
102
+ slots,
103
+ );
89
104
  },
90
105
  });
91
106
  }
package/client/context.ts CHANGED
@@ -26,7 +26,8 @@ import ThemeService from "./plugins/theme";
26
26
  // —— 布局相关的 Context 类型扩展 ——
27
27
 
28
28
  /** 前端侧事件表:在 cordis 事件的基础上扩展本库自定义事件 */
29
- export interface Events<C extends Context = Context> extends cordis.Events<C> {}
29
+ export interface Events<C extends Context = Context>
30
+ extends cordis.Events<C> {}
30
31
 
31
32
  /**
32
33
  * 前端 Context 接口:各服务插件通过 `declare module "../context"`
@@ -84,7 +85,10 @@ export class Context extends cordis.Context {
84
85
  this.app = createApp(
85
86
  defineComponent({
86
87
  setup: () => () => [
87
- h(resolveComponent("k-slot"), { name: "root", single: true }),
88
+ h(resolveComponent("k-slot"), {
89
+ name: "root",
90
+ single: true,
91
+ }),
88
92
  h(resolveComponent("k-slot"), { name: "global" }),
89
93
  ],
90
94
  }),
@@ -115,12 +119,16 @@ export class Context extends cordis.Context {
115
119
  */
116
120
  addEventListener<K extends keyof WindowEventMap>(
117
121
  type: K,
118
- listener: (this: Window, ev: WindowEventMap[K]) => unknown,
122
+ listener: (
123
+ this: Window,
124
+ ev: WindowEventMap[K],
125
+ ) => unknown,
119
126
  options?: boolean | AddEventListenerOptions,
120
127
  ) {
121
128
  return this.effect(() => {
122
129
  window.addEventListener(type, listener, options);
123
- return () => window.removeEventListener(type, listener, options);
130
+ return () =>
131
+ window.removeEventListener(type, listener, options);
124
132
  });
125
133
  }
126
134
 
package/client/data.ts CHANGED
@@ -3,7 +3,10 @@
3
3
  // Copyright (c) 2026-present Koishi-CE contributors.
4
4
 
5
5
  /// <reference path="./shims.d.ts" />
6
- import type { Promisify, Universal } from "@koishi-ce/koishi";
6
+ import type {
7
+ Promisify,
8
+ Universal,
9
+ } from "@koishi-ce/koishi";
7
10
  import type {
8
11
  ClientConfig,
9
12
  Console,
@@ -43,7 +46,8 @@ export function withProxy(url: string) {
43
46
  /** 当前与服务端的 WebSocket 连接(未连接时为 null) */
44
47
  export const socket = ref<Universal.WebSocket | null>(null);
45
48
  /** 按事件名登记的推送监听器(receive 注册) */
46
- const listeners: Record<string, (data: unknown) => void> = {};
49
+ const listeners: Record<string, (data: unknown) => void> =
50
+ {};
47
51
  /** 按报文 id 暂存的 RPC 应答钩子 [resolve, reject](send 写入) */
48
52
  const responseHooks: Record<
49
53
  string,
@@ -93,19 +97,26 @@ type StoreValue = Store[keyof Store];
93
97
 
94
98
  // 服务端整表推送:直接覆盖 store 中对应键
95
99
  // (key 为联合类型时直写 store[key] 会被要求交叉类型,故经 Record 视图写入)
96
- receive<{ key: keyof Store; value: unknown }>("data", ({ key, value }) => {
97
- (store as Record<keyof Store, StoreValue>)[key] = value as StoreValue;
98
- });
100
+ receive<{ key: keyof Store; value: unknown }>(
101
+ "data",
102
+ ({ key, value }) => {
103
+ (store as Record<keyof Store, StoreValue>)[key] =
104
+ value as StoreValue;
105
+ },
106
+ );
99
107
 
100
108
  // 服务端增量推送:数组做追加,对象做浅合并
101
- receive<{ key: keyof Store; value: unknown }>("patch", ({ key, value }) => {
102
- const current = store[key];
103
- if (Array.isArray(current)) {
104
- (current as unknown[]).push(...(value as unknown[]));
105
- } else if (current) {
106
- Object.assign(current, value);
107
- }
108
- });
109
+ receive<{ key: keyof Store; value: unknown }>(
110
+ "patch",
111
+ ({ key, value }) => {
112
+ const current = store[key];
113
+ if (Array.isArray(current)) {
114
+ (current as unknown[]).push(...(value as unknown[]));
115
+ } else if (current) {
116
+ Object.assign(current, value);
117
+ }
118
+ },
119
+ );
109
120
 
110
121
  // RPC 应答分发:按报文 id 找到 send() 留下的 resolve/reject 并结算
111
122
  receive<{ id: string; value?: unknown; error?: unknown }>(
@@ -131,7 +142,10 @@ receive<{ id: string; value?: unknown; error?: unknown }>(
131
142
  * @param ctx 根 Context,用于把消息转发为 cordis 事件
132
143
  * @param callback 创建 WebSocket 实例的工厂函数
133
144
  */
134
- export function connect(ctx: Context, callback: () => Universal.WebSocket) {
145
+ export function connect(
146
+ ctx: Context,
147
+ callback: () => Universal.WebSocket,
148
+ ) {
135
149
  const value = callback();
136
150
 
137
151
  let sendTimer: number;
@@ -142,8 +156,14 @@ export function connect(ctx: Context, callback: () => Universal.WebSocket) {
142
156
  if (!global.heartbeat) return;
143
157
  clearTimeout(sendTimer);
144
158
  clearTimeout(closeTimer);
145
- sendTimer = +setTimeout(() => send("ping"), global.heartbeat.interval);
146
- closeTimer = +setTimeout(() => value?.close(), global.heartbeat.timeout);
159
+ sendTimer = +setTimeout(
160
+ () => send("ping"),
161
+ global.heartbeat.interval,
162
+ );
163
+ closeTimer = +setTimeout(
164
+ () => value?.close(),
165
+ global.heartbeat.timeout,
166
+ );
147
167
  };
148
168
 
149
169
  const reconnect = () => {
@@ -152,10 +172,14 @@ export function connect(ctx: Context, callback: () => Universal.WebSocket) {
152
172
  for (const key in store) {
153
173
  (store as Record<string, unknown>)[key] = undefined;
154
174
  }
155
- console.log("[koishi] websocket disconnected, will retry in 1s...");
175
+ console.log(
176
+ "[koishi] websocket disconnected, will retry in 1s...",
177
+ );
156
178
  setTimeout(() => {
157
179
  connect(ctx, callback).then(location.reload, () => {
158
- console.log("[koishi] websocket disconnected, will retry in 1s...");
180
+ console.log(
181
+ "[koishi] websocket disconnected, will retry in 1s...",
182
+ );
159
183
  });
160
184
  }, 1000);
161
185
  };
@@ -163,7 +187,12 @@ export function connect(ctx: Context, callback: () => Universal.WebSocket) {
163
187
  value.addEventListener("message", (ev) => {
164
188
  refresh();
165
189
  const data = JSON.parse(ev.data);
166
- console.debug("↓%c", "color:purple", data.type, data.body);
190
+ console.debug(
191
+ "↓%c",
192
+ "color:purple",
193
+ data.type,
194
+ data.body,
195
+ );
167
196
  if (data.type in listeners) {
168
197
  listeners[data.type]?.(data.body);
169
198
  }
@@ -172,11 +201,13 @@ export function connect(ctx: Context, callback: () => Universal.WebSocket) {
172
201
 
173
202
  value.addEventListener("close", reconnect);
174
203
 
175
- return new Promise<Universal.WebSocket.Event>((resolve, reject) => {
176
- value.addEventListener("open", (event) => {
177
- socket.value = markRaw(value);
178
- resolve(event);
179
- });
180
- value.addEventListener("error", reject);
181
- });
204
+ return new Promise<Universal.WebSocket.Event>(
205
+ (resolve, reject) => {
206
+ value.addEventListener("open", (event) => {
207
+ socket.value = markRaw(value);
208
+ resolve(event);
209
+ });
210
+ value.addEventListener("error", reject);
211
+ },
212
+ );
182
213
  }
package/client/index.ts CHANGED
@@ -37,7 +37,8 @@ export const ScopeStatus = {
37
37
  DISPOSED: 4,
38
38
  } as const;
39
39
 
40
- export type ScopeStatus = (typeof ScopeStatus)[keyof typeof ScopeStatus];
40
+ export type ScopeStatus =
41
+ (typeof ScopeStatus)[keyof typeof ScopeStatus];
41
42
  export * from "./components";
42
43
  export * from "./context";
43
44
  export * from "./data";
@@ -0,0 +1,47 @@
1
+ # SPDX-License-Identifier: AGPL-3.0-only
2
+ # Copyright (c) 2019-present Shigma and Koishijs contributors.
3
+ # Copyright (c) 2026-present Koishi-CE contributors.
4
+
5
+ pages:
6
+ home: Willkommen
7
+ settings: Benutzereinstellungen
8
+ home:
9
+ connecting: Verbindung zum Koishi-Server wird hergestellt...
10
+ welcome:
11
+ title: Willkommen bei Koishi!
12
+ description: Ihr Chatbot ist einsatzbereit. Wählen Sie eine der Optionen unten, um Ihre Koishi-Reise zu beginnen.
13
+ docs:
14
+ title: Dokumentation
15
+ description: Lesen Sie die offizielle Dokumentation. Sie enthält alles, was Sie wissen möchten.
16
+ forum:
17
+ title: Forum
18
+ description: Tauschen Sie sich im Forum mit anderen Nutzern aus. Wenn Probleme auftreten, finden Sie dort Hilfe.
19
+ settings:
20
+ general: Allgemeine Einstellungen
21
+ appearance: Erscheinungsbild
22
+ status: Statusleisten-Einstellungen
23
+ loading:
24
+ page: Seitenkomponenten werden geladen
25
+ data: Daten werden geladen...
26
+ blank:
27
+ hint: Wenn Sie diese Seite sehen, wurde das Konsolen-Plugin erfolgreich geladen, aber es sind noch keine Konsolen-Erweiterungen installiert.
28
+ menu:
29
+ resetActivity: Aktivitätsleiste zurücksetzen
30
+ overlay:
31
+ zoomOut: Verkleinern
32
+ zoomIn: Vergrößern
33
+ reset: Zurücksetzen
34
+ rotateLeft: Gegen den Uhrzeigersinn drehen
35
+ rotateRight: Im Uhrzeigersinn drehen
36
+ schema:
37
+ settings:
38
+ $description: Allgemeine Einstellungen
39
+ locale: Spracheinstellungen.
40
+ theme:
41
+ $description: Design-Einstellungen
42
+ mode: Design-Präferenz.
43
+ mode-auto: System folgen
44
+ mode-dark: Dunkel
45
+ mode-light: Hell
46
+ dark: Dunkles Design.
47
+ light: Helles Design.
@@ -0,0 +1,47 @@
1
+ # SPDX-License-Identifier: AGPL-3.0-only
2
+ # Copyright (c) 2019-present Shigma and Koishijs contributors.
3
+ # Copyright (c) 2026-present Koishi-CE contributors.
4
+
5
+ pages:
6
+ home: Welcome
7
+ settings: User Settings
8
+ home:
9
+ connecting: Connecting to the Koishi server...
10
+ welcome:
11
+ title: Welcome to Koishi!
12
+ description: Your chatbot is ready to go. Pick any option below to start your Koishi journey.
13
+ docs:
14
+ title: Documentation
15
+ description: Read the official documentation, which contains everything you want to know.
16
+ forum:
17
+ title: Forum
18
+ description: Talk with other users on the forum. If you run into problems, you can always ask for help there.
19
+ settings:
20
+ general: General Settings
21
+ appearance: Appearance
22
+ status: Status Bar Settings
23
+ loading:
24
+ page: Loading page components
25
+ data: Loading data...
26
+ blank:
27
+ hint: If you are seeing this page, the console plugin has loaded successfully, but no console extensions are installed yet.
28
+ menu:
29
+ resetActivity: Reset Activity Bar
30
+ overlay:
31
+ zoomOut: Zoom out
32
+ zoomIn: Zoom in
33
+ reset: Reset
34
+ rotateLeft: Rotate counterclockwise
35
+ rotateRight: Rotate clockwise
36
+ schema:
37
+ settings:
38
+ $description: General Settings
39
+ locale: Language settings.
40
+ theme:
41
+ $description: Theme Settings
42
+ mode: Theme preference.
43
+ mode-auto: Follow system
44
+ mode-dark: Dark
45
+ mode-light: Light
46
+ dark: Dark theme.
47
+ light: Light theme.
@@ -0,0 +1,47 @@
1
+ # SPDX-License-Identifier: AGPL-3.0-only
2
+ # Copyright (c) 2019-present Shigma and Koishijs contributors.
3
+ # Copyright (c) 2026-present Koishi-CE contributors.
4
+
5
+ pages:
6
+ home: Accueil
7
+ settings: Paramètres utilisateur
8
+ home:
9
+ connecting: Connexion au serveur Koishi...
10
+ welcome:
11
+ title: Bienvenue sur Koishi !
12
+ description: Votre chatbot est prêt. Choisissez une option ci-dessous pour commencer votre aventure Koishi.
13
+ docs:
14
+ title: Documentation
15
+ description: "Lisez la documentation officielle : elle contient tout ce que vous voulez savoir."
16
+ forum:
17
+ title: Forum
18
+ description: Échangez avec d'autres utilisateurs sur le forum. Si vous rencontrez des problèmes, vous pouvez y demander de l'aide.
19
+ settings:
20
+ general: Paramètres généraux
21
+ appearance: Apparence
22
+ status: Paramètres de la barre d'état
23
+ loading:
24
+ page: Chargement des composants de la page
25
+ data: Chargement des données...
26
+ blank:
27
+ hint: Si vous voyez cette page, le plugin console s'est chargé avec succès, mais aucune extension de console n'est installée.
28
+ menu:
29
+ resetActivity: Réinitialiser la barre d'activités
30
+ overlay:
31
+ zoomOut: Réduire
32
+ zoomIn: Agrandir
33
+ reset: Réinitialiser
34
+ rotateLeft: Pivoter dans le sens antihoraire
35
+ rotateRight: Pivoter dans le sens horaire
36
+ schema:
37
+ settings:
38
+ $description: Paramètres généraux
39
+ locale: Paramètres de langue.
40
+ theme:
41
+ $description: Paramètres du thème
42
+ mode: Préférence de thème.
43
+ mode-auto: Suivre le système
44
+ mode-dark: Sombre
45
+ mode-light: Clair
46
+ dark: Thème sombre.
47
+ light: Thème clair.
@@ -0,0 +1,47 @@
1
+ # SPDX-License-Identifier: AGPL-3.0-only
2
+ # Copyright (c) 2019-present Shigma and Koishijs contributors.
3
+ # Copyright (c) 2026-present Koishi-CE contributors.
4
+
5
+ pages:
6
+ home: ホーム
7
+ settings: ユーザー設定
8
+ home:
9
+ connecting: Koishi サーバーに接続しています……
10
+ welcome:
11
+ title: Koishi へようこそ!
12
+ description: ボットの準備が整いました。以下の選択肢からどれかを選んで、Koishi の旅を始めましょう。
13
+ docs:
14
+ title: ドキュメントを読む
15
+ description: 公式ドキュメントを読み始めましょう。知りたいことがすべて書かれています。
16
+ forum:
17
+ title: フォーラムへ
18
+ description: フォーラムで他のユーザーと交流しましょう。問題が起きたときは、ここで助けを求めることができます。
19
+ settings:
20
+ general: 一般設定
21
+ appearance: 外観設定
22
+ status: ステータスバー設定
23
+ loading:
24
+ page: ページコンポーネントを読み込み中
25
+ data: データを読み込み中……
26
+ blank:
27
+ hint: このページが表示されている場合、コンソールプラグインの読み込みには成功していますが、コンソール拡張がまだインストールされていません。
28
+ menu:
29
+ resetActivity: アクティビティバーをリセット
30
+ overlay:
31
+ zoomOut: 縮小
32
+ zoomIn: 拡大
33
+ reset: リセット
34
+ rotateLeft: 反時計回りに回転
35
+ rotateRight: 時計回りに回転
36
+ schema:
37
+ settings:
38
+ $description: 一般設定
39
+ locale: 言語設定。
40
+ theme:
41
+ $description: テーマ設定
42
+ mode: テーマの設定。
43
+ mode-auto: システムに従う
44
+ mode-dark: ダーク
45
+ mode-light: ライト
46
+ dark: ダークテーマ。
47
+ light: ライトテーマ。