@zhin.js/plugin-word-riddle 1.1.15 → 1.1.17

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.
@@ -1,17 +1,17 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
3
  import { messageFromCommandInput, normalizeRiddleAction } from '@zhin.js/game-kit';
4
- import { RIDDLE_HELP, runRiddleCommand } from "../../../lib/riddle-command.js";
4
+ import { getRiddleHelp, runRiddleCommand } from "../../../lib/riddle-command.js";
5
5
  import { resolveGameServices } from "../../../lib/runtime-store.js";
6
6
  export default defineCommand({
7
7
  description: 'Word Riddle',
8
8
  params: { action: { type: 'string', default: '' } },
9
- async execute({ params, input, use, owner }) {
9
+ async execute({ params, input, use, locale, formatCommand }) {
10
10
  const action = normalizeRiddleAction(String(params.action ?? ''));
11
11
  if (!action || action === 'help')
12
- return RIDDLE_HELP;
12
+ return getRiddleHelp({ locale, formatCommand });
13
13
  const services = resolveGameServices({ use });
14
- const message = messageFromCommandInput(input);
14
+ const message = messageFromCommandInput(input, { locale, formatCommand });
15
15
  return runRiddleCommand(services, message, action);
16
16
  },
17
17
  });
@@ -1,16 +1,16 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
2
  import { messageFromCommandInput, normalizeRiddleAction } from '@zhin.js/game-kit';
3
- import { RIDDLE_HELP, runRiddleCommand } from '../../../src/riddle-command.js';
3
+ import { getRiddleHelp, runRiddleCommand } from '../../../src/riddle-command.js';
4
4
  import { resolveGameServices } from '../../../src/runtime-store.js';
5
5
 
6
6
  export default defineCommand({
7
7
  description: 'Word Riddle',
8
8
  params: { action: { type: 'string', default: '' } },
9
- async execute({ params, input, use, owner }) {
9
+ async execute({ params, input, use, locale, formatCommand }) {
10
10
  const action = normalizeRiddleAction(String(params.action ?? ''));
11
- if (!action || action === 'help') return RIDDLE_HELP;
11
+ if (!action || action === 'help') return getRiddleHelp({ locale, formatCommand });
12
12
  const services = resolveGameServices({ use });
13
- const message = messageFromCommandInput(input);
13
+ const message = messageFromCommandInput(input, { locale, formatCommand });
14
14
  return runRiddleCommand(services, message, action);
15
15
  },
16
16
  });
package/lib/engine.d.ts CHANGED
@@ -1,8 +1,9 @@
1
+ import { type Locale } from 'zhin.js/i18n';
1
2
  import { getRiddleById, type RiddleEntry, type RiddleType } from './riddle-provider.js';
2
3
  export type { RiddleType };
3
4
  export declare const RIDDLE_PREFIX = "riddle";
4
5
  export declare function normalizeAnswer(raw: string): string;
5
6
  export declare function answersFor(entry: RiddleEntry): string[];
6
7
  export declare function checkAnswer(entry: RiddleEntry, raw: string): boolean;
7
- export declare function typeLabel(type: RiddleType): string;
8
+ export declare function typeLabel(type: RiddleType, locale?: Locale): string;
8
9
  export { getRiddleById };
package/lib/engine.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMessages } from 'zhin.js/i18n';
1
2
  import { getRiddleById, } from './riddle-provider.js';
2
3
  export const RIDDLE_PREFIX = 'riddle';
3
4
  export function normalizeAnswer(raw) {
@@ -13,8 +14,12 @@ export function checkAnswer(entry, raw) {
13
14
  return false;
14
15
  return answersFor(entry).some((x) => x === a);
15
16
  }
16
- export function typeLabel(type) {
17
- return type === 'char' ? '字谜' : '猜成语';
17
+ export function typeLabel(type, locale) {
18
+ return type === 'char' ? messages(locale, 'text1') : messages(locale, 'text2');
18
19
  }
19
20
  export { getRiddleById };
21
+ const messages = createMessages({
22
+ text1: { 'zh-CN': "字谜", en: "Chinese Character Riddles" },
23
+ text2: { 'zh-CN': "猜成语", en: "Chinese Idiom Riddles" },
24
+ });
20
25
  //# sourceMappingURL=engine.js.map
package/lib/engine.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,GAGd,MAAM,sBAAsB,CAAC;AAI9B,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAEtC,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAkB,EAAE,GAAW;IACzD,MAAM,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrB,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAgB;IACxC,OAAO,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AACxC,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAe,MAAM,cAAc,CAAC;AAC3D,OAAO,EACL,aAAa,GAGd,MAAM,sBAAsB,CAAC;AAI9B,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAEtC,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAkB,EAAE,GAAW;IACzD,MAAM,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrB,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAgB,EAAE,MAAe;IACzD,OAAO,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACjF,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,2BAA2B,EAAE;IACzD,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,uBAAuB,EAAE;CACvD,CAAC,CAAC"}
package/lib/game-flow.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMessages, resolveLocale } from 'zhin.js/i18n';
1
2
  import { answersFor, checkAnswer, getRiddleById, normalizeAnswer, RIDDLE_PREFIX, typeLabel, } from './engine.js';
2
3
  import { currentRiddleId, parseQueue, } from './session-service.js';
3
4
  import { buildRiddleView, MAX_WRONG } from './view.js';
@@ -23,24 +24,27 @@ async function advanceQuestion(services, session) {
23
24
  export async function startGame(services, message, mode) {
24
25
  const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
25
26
  const active = await services.getActiveByChannel(ch);
27
+ const locale = resolveLocale(active ? active.locale : message.locale);
26
28
  if (active) {
27
29
  if (active.player_id === message.$sender.id) {
28
- return `你已有进行中的猜谜(${typeLabel(active.mode)}),发送「猜谜 继续」刷新。`;
30
+ return messages(locale, 'text1', { p0: typeLabel(active.mode, locale) });
29
31
  }
30
- return `本频道 ${active.player_name} 正在猜谜。`;
32
+ return messages(locale, 'text2', { p0: active.player_name });
31
33
  }
32
34
  const session = await services.createSession(message, mode);
33
35
  return renderView(message, session);
34
36
  }
35
37
  export async function continueGame(services, message) {
36
38
  const session = await services.getActiveForUser(`${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`, message.$sender.id);
39
+ const locale = resolveLocale(session ? session.locale : message.locale);
37
40
  if (!session)
38
- return '你没有进行中的猜谜,发送「猜谜 开始」。';
41
+ return messages(locale, 'text3');
39
42
  return renderView(message, session);
40
43
  }
41
44
  export async function processAnswerText(services, message, raw) {
42
45
  const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
43
46
  const session = await services.getActiveForUser(ch, message.$sender.id);
47
+ const locale = resolveLocale(session ? session.locale : message.locale);
44
48
  if (!session || session.status !== 'active')
45
49
  return null;
46
50
  const riddleId = currentRiddleId(session);
@@ -50,7 +54,7 @@ export async function processAnswerText(services, message, raw) {
50
54
  // 格式不合规(字数与答案不符)只提示、不扣失误:避免闲聊(「好的」「谢谢」)被累计判负
51
55
  const normalized = normalizeAnswer(raw);
52
56
  if (!answersFor(entry).some((a) => a.length === normalized.length)) {
53
- return `本题答案应为 ${entry.answer.length} 个字(这条不算失误)。`;
57
+ return messages(locale, 'text4', { p0: entry.answer.length });
54
58
  }
55
59
  if (checkAnswer(entry, raw)) {
56
60
  const streak = session.streak + 1;
@@ -64,8 +68,8 @@ export async function processAnswerText(services, message, raw) {
64
68
  const after = await advanceQuestion(services, (await services.getById(session.id)));
65
69
  const explain = entry.explanation ? `\n📖 ${entry.explanation}` : '';
66
70
  return renderView(message, after, [
67
- `✅ 正确!答案:**${entry.answer}**${explain}`,
68
- `+${10 + Math.min(streak, 5)} 分`,
71
+ messages(locale, 'text5', { p0: entry.answer, p1: explain }),
72
+ messages(locale, 'text6', { p0: 10 + Math.min(streak, 5) }),
69
73
  ]);
70
74
  }
71
75
  const wrong = session.wrong_count + 1;
@@ -73,20 +77,21 @@ export async function processAnswerText(services, message, raw) {
73
77
  await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
74
78
  const after = await advanceQuestion(services, (await services.getById(session.id)));
75
79
  return renderView(message, after, [
76
- `❌ 本题答案:**${entry.answer}**`,
77
- '失误过多,自动下一题。',
80
+ messages(locale, 'text7', { p0: entry.answer }),
81
+ messages(locale, 'text8'),
78
82
  ]);
79
83
  }
80
84
  await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
81
85
  const updated = (await services.getById(session.id));
82
- return renderView(message, updated, ['❌ 不对,再想想!']);
86
+ return renderView(message, updated, [messages(locale, 'text9')]);
83
87
  }
84
88
  export async function handleChoice(services, message, sessionId, choiceId) {
85
89
  const session = await services.getById(sessionId);
90
+ const locale = resolveLocale(session ? session.locale : message.locale);
86
91
  if (!session)
87
- return '会话不存在。';
92
+ return messages(locale, 'text10');
88
93
  if (session.player_id !== message.$sender.id)
89
- return '这是别人的猜谜。';
94
+ return messages(locale, 'text11');
90
95
  if (choiceId === 'restart_char') {
91
96
  await services.updateSession(session.id, { status: 'aborted' });
92
97
  return (await startGame(services, message, 'char')) ?? null;
@@ -96,32 +101,53 @@ export async function handleChoice(services, message, sessionId, choiceId) {
96
101
  return (await startGame(services, message, 'idiom')) ?? null;
97
102
  }
98
103
  if (session.status !== 'active')
99
- return '本轮已结束。';
104
+ return messages(locale, 'text12');
100
105
  const riddleId = currentRiddleId(session);
101
106
  const entry = riddleId ? getRiddleById(riddleId) : undefined;
102
107
  if (!entry)
103
- return '题目丢失。';
108
+ return messages(locale, 'text13');
104
109
  if (choiceId === 'hint') {
105
- const hint = entry.hint ?? `答案共 ${entry.answer.length} 个字`;
110
+ const hint = entry.hint ?? messages(locale, 'text14', { p0: entry.answer.length });
106
111
  await services.updateSession(session.id, { hints_used: session.hints_used + 1, streak: 0 });
107
112
  const updated = (await services.getById(session.id));
108
113
  return renderView(message, updated, [
109
- `💡 提示:${hint}`,
110
- '(连击清零)',
114
+ messages(locale, 'text15', { p0: hint }),
115
+ messages(locale, 'text16'),
111
116
  ]);
112
117
  }
113
118
  if (choiceId === 'skip') {
114
119
  await services.updateSession(session.id, { streak: 0 });
115
120
  const after = await advanceQuestion(services, session);
116
121
  return renderView(message, after, [
117
- `⏭️ 跳过,答案:**${entry.answer}**`,
122
+ messages(locale, 'text17', { p0: entry.answer }),
118
123
  ]);
119
124
  }
120
125
  if (choiceId === 'quit') {
121
126
  await services.updateSession(session.id, { status: 'aborted' });
122
- return '已结束猜谜。';
127
+ return messages(locale, 'text18');
123
128
  }
124
- return '未知操作。';
129
+ return messages(locale, 'text19');
125
130
  }
126
131
  export { RIDDLE_PREFIX };
132
+ const messages = createMessages({
133
+ text1: { 'zh-CN': "你已有进行中的猜谜({p0}),请使用当前对局的操作入口继续。", en: "You already have an active riddle game ({p0}). Continue using its controls." },
134
+ text2: { 'zh-CN': "本频道 {p0} 正在猜谜。", en: "{p0} is solving riddles in this channel." },
135
+ text3: { 'zh-CN': "你没有进行中的猜谜。", en: "You have no active riddle game." },
136
+ text4: { 'zh-CN': "本题答案应为 {p0} 个字(这条不算失误)。", en: "The answer has {p0} characters (this does not count as a mistake)." },
137
+ text5: { 'zh-CN': "✅ 正确!答案:**{p0}**{p1}", en: "✅ Correct! Answer: **{p0}**{p1}" },
138
+ text6: { 'zh-CN': "+{p0} 分", en: "+{p0} points" },
139
+ text7: { 'zh-CN': "❌ 本题答案:**{p0}**", en: "❌ Answer: **{p0}**" },
140
+ text8: { 'zh-CN': "失误过多,自动下一题。", en: "Too many mistakes. Moving to the next riddle." },
141
+ text9: { 'zh-CN': "❌ 不对,再想想!", en: "❌ Not quite. Try again!" },
142
+ text10: { 'zh-CN': "会话不存在。", en: "This game no longer exists." },
143
+ text11: { 'zh-CN': "这是别人的猜谜。", en: "This riddle game belongs to another player." },
144
+ text12: { 'zh-CN': "本轮已结束。", en: "This round has ended." },
145
+ text13: { 'zh-CN': "题目丢失。", en: "The riddle is unavailable." },
146
+ text14: { 'zh-CN': "答案共 {p0} 个字", en: "The answer has {p0} characters" },
147
+ text15: { 'zh-CN': "💡 提示:{p0}", en: "💡 Hint: {p0}" },
148
+ text16: { 'zh-CN': "(连击清零)", en: "(Streak reset)" },
149
+ text17: { 'zh-CN': "⏭️ 跳过,答案:**{p0}**", en: "⏭️ Skipped. Answer: **{p0}**" },
150
+ text18: { 'zh-CN': "已结束猜谜。", en: "The riddle game has ended." },
151
+ text19: { 'zh-CN': "未知操作。", en: "Unknown action." },
152
+ });
127
153
  //# sourceMappingURL=game-flow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"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"}
package/lib/models.d.ts CHANGED
@@ -4,6 +4,7 @@ declare module '@zhin.js/core' {
4
4
  interface Models {
5
5
  word_riddle_sessions: {
6
6
  id: string;
7
+ locale?: 'zh-CN' | 'en' | null;
7
8
  adapter: string;
8
9
  endpoint: string;
9
10
  channel_type: string;
@@ -27,5 +28,7 @@ declare module '@zhin.js/core' {
27
28
  }
28
29
  export type RiddleSessionRow = Models['word_riddle_sessions'];
29
30
  export declare function defineHostTables(db: {
30
- define: (name: string, definition: Record<string, unknown>) => void;
31
+ define: (name: string, definition: Record<string, unknown>, options?: {
32
+ readonly addColumns?: readonly string[];
33
+ }) => void;
31
34
  }): void;
package/lib/models.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export function defineHostTables(db) {
2
2
  db.define('word_riddle_sessions', {
3
3
  id: { type: 'text', primary: true },
4
+ locale: { type: 'text', nullable: true },
4
5
  adapter: { type: 'text', nullable: false },
5
6
  endpoint: { type: 'text', nullable: false },
6
7
  channel_type: { type: 'text', nullable: false },
@@ -19,6 +20,6 @@ export function defineHostTables(db) {
19
20
  status: { type: 'text', default: 'active' },
20
21
  updated_at: { type: 'bigint', default: 0 },
21
22
  created_at: { type: 'bigint', default: 0 },
22
- });
23
+ }, { addColumns: ['locale'] });
23
24
  }
24
25
  //# sourceMappingURL=models.js.map
package/lib/models.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAiCA,MAAM,UAAU,gBAAgB,CAC9B,EAA2E;IAE3E,EAAE,CAAC,MAAM,CAAC,sBAAsB,EAAE;QAChC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QACnC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC1C,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC3C,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC/C,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC7C,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC9C,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC5C,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QAC1C,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;QACvC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QACtC,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACtC,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACtC,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACvC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC5C,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC3C,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC5C,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC3C,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;QAC1C,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;KAC3C,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAkCA,MAAM,UAAU,gBAAgB,CAC9B,EAAkI;IAElI,EAAE,CAAC,MAAM,CAAC,sBAAsB,EAAE;QAChC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QACnC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;QACxC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC1C,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC3C,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC/C,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC7C,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC9C,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC5C,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QAC1C,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;QACvC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QACtC,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACtC,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACtC,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACvC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC5C,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC3C,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC5C,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC3C,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;QAC1C,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;KAC3C,EAAE,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjC,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { type GameMessageLike, type GameReply } from '@zhin.js/game-kit';
2
2
  import type { SessionService } from './session-service.js';
3
+ export declare function getRiddleHelp(message?: Pick<GameMessageLike, 'locale' | 'formatCommand'>): string;
3
4
  export declare const RIDDLE_HELP: string;
4
5
  export declare function runRiddleCommand(services: SessionService, message: GameMessageLike, action: string): Promise<GameReply>;
@@ -1,20 +1,27 @@
1
- import { channelKey, } from '@zhin.js/game-kit';
1
+ import { formatGameHelp, gameCommandFeedback, gameCommandHint, channelKey } from '@zhin.js/game-kit';
2
+ import { createMessages } from 'zhin.js/i18n';
2
3
  import { continueGame, startGame } from './game-flow.js';
3
4
  import { riddleCount } from './riddles-catalog.js';
4
5
  import { typeLabel } from './engine.js';
5
6
  const counts = riddleCount();
6
- export const RIDDLE_HELP = [
7
- '🧩 猜谜(字谜 + 猜成语)',
8
- `字谜 ${counts.char.toLocaleString('zh-CN')} 题 · 成语 ${counts.idiom.toLocaleString('zh-CN')} 题`,
9
- '猜谜 / riddle — 帮助',
10
- '猜谜 开始 — 字谜模式',
11
- '猜谜 字谜 — 字谜模式',
12
- '猜谜 成语 — 猜成语模式',
13
- '猜谜 继续 — 刷新界面',
14
- '猜谜 放弃 — 结束',
15
- '',
16
- '进行中直接回复答案;连击加分,提示/失误会清零连击。',
17
- ].join('\n');
7
+ const messages = createMessages({
8
+ counts: { 'zh-CN': '字谜 {chars} 题 · 成语 {idioms} 题', en: '{chars} character riddles · {idioms} idiom riddles' },
9
+ char: { 'zh-CN': '{command} — 字谜模式', en: '{command} — Chinese character riddles' },
10
+ idiom: { 'zh-CN': '{command} — 猜成语模式', en: '{command} — Chinese idiom riddles' },
11
+ instructions: { 'zh-CN': '进行中直接回复答案;连击加分,提示/失误会清零连击。', en: 'Reply with the answer during play. Streaks earn bonus points; hints and mistakes reset the streak.' },
12
+ active: { 'zh-CN': '进行中:{mode} · 得分 {score} · 连击 {streak}', en: 'Playing: {mode} · Score {score} · Streak {streak}' },
13
+ quit: { 'zh-CN': '已放弃猜谜。', en: 'You quit the riddle game.' },
14
+ });
15
+ export function getRiddleHelp(message = {}) {
16
+ const locale = message.locale ?? 'zh-CN';
17
+ const command = message.formatCommand?.('riddle');
18
+ return [formatGameHelp(message, { 'zh-CN': '🧩 猜谜(字谜 + 猜成语)', en: '🧩 Chinese Character and Idiom Riddles' }, 'riddle', ['start', 'continue', 'quit']),
19
+ messages(locale, 'counts', { chars: counts.char.toLocaleString(locale), idioms: counts.idiom.toLocaleString(locale) }),
20
+ ...(command ? [messages(locale, 'char', { command: command + ' char' }), messages(locale, 'idiom', { command: command + ' idiom' })] : []),
21
+ messages(locale, 'instructions'),
22
+ ].join('\n');
23
+ }
24
+ export const RIDDLE_HELP = getRiddleHelp();
18
25
  function parseMode(action) {
19
26
  if (action === 'char' || action === '字谜')
20
27
  return 'char';
@@ -29,12 +36,12 @@ export async function runRiddleCommand(services, message, action) {
29
36
  const userId = message.$sender.id;
30
37
  if (!action || action === 'help') {
31
38
  const active = await services.getActiveByChannel(ch);
32
- const lines = [RIDDLE_HELP, ''];
39
+ const lines = [getRiddleHelp(message), ''];
33
40
  if (active) {
34
- lines.push(`进行中:${typeLabel(active.mode)} · 得分 ${active.score} · 连击 ${active.streak}`);
41
+ lines.push(messages(active.locale ?? undefined, 'active', { mode: typeLabel(active.mode, active.locale ?? undefined), score: active.score, streak: active.streak }));
35
42
  }
36
43
  else {
37
- lines.push('暂无对局,发送「猜谜 开始」。');
44
+ lines.push(gameCommandFeedback(message, 'noGame'), gameCommandHint(message, 'riddle'));
38
45
  }
39
46
  return lines.join('\n');
40
47
  }
@@ -47,10 +54,10 @@ export async function runRiddleCommand(services, message, action) {
47
54
  if (action === 'quit' || action === '放弃') {
48
55
  const row = await services.getActiveForUser(ch, userId);
49
56
  if (!row)
50
- return '你没有进行中的猜谜。';
57
+ return gameCommandFeedback(message, 'noGame');
51
58
  await services.updateSession(row.id, { status: 'aborted' });
52
- return '已放弃猜谜。';
59
+ return messages(row.locale ?? undefined, 'quit');
53
60
  }
54
- return `未知子命令:${action}\n\n${RIDDLE_HELP}`;
61
+ return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getRiddleHelp(message);
55
62
  }
56
63
  //# sourceMappingURL=riddle-command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"riddle-command.js","sourceRoot":"","sources":["../src/riddle-command.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,GAGX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAmB,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;AAE7B,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,iBAAiB;IACjB,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,WAAW,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI;IAC5F,kBAAkB;IAClB,cAAc;IACd,cAAc;IACd,eAAe;IACf,cAAc;IACd,YAAY;IACZ,EAAE;IACF,4BAA4B;CAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,SAAS,SAAS,CAAC,MAAc;IAC/B,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IACxD,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC;IAC1D,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IACzD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAwB,EACxB,OAAwB,EACxB,MAAc;IAEd,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;IAElC,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAChC,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,CAAC,IAAI,CAAC,OAAO,SAAS,CAAC,MAAM,CAAC,IAAkB,CAAC,SAAS,MAAM,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACvG,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/B,IAAI,IAAI;QAAE,OAAO,CAAC,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAElE,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAC7C,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,GAAG;YAAE,OAAO,YAAY,CAAC;QAC9B,MAAM,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,SAAS,MAAM,OAAO,WAAW,EAAE,CAAC;AAC7C,CAAC"}
1
+ {"version":3,"file":"riddle-command.js","sourceRoot":"","sources":["../src/riddle-command.ts"],"names":[],"mappings":"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"}
@@ -26,6 +26,7 @@ export class SessionService extends BaseSessionService {
26
26
  const queue = pickRoundQueue(mode).map((r) => r.id);
27
27
  const row = {
28
28
  id: generateSessionId(),
29
+ locale: message.locale ?? 'zh-CN',
29
30
  adapter: String(message.$adapter),
30
31
  endpoint: message.$endpoint,
31
32
  channel_type: message.$channel.type,
@@ -1 +1 @@
1
- {"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,iBAAiB,GAGlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AAKvE,MAAM,UAAU,UAAU,CAAC,KAAkC;IAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;IACzF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,OAAO,cAAe,SAAQ,kBAAoC;IACtE,YAAY,EAAkB;QAC5B,KAAK,CAAC,EAAsD,EAAE;YAC5D,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,sBAAsB;YAC7B,UAAU,EAAE,CAAC,WAAW,CAAC;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAwB,EAAE,IAAgB;QAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,GAAG,GAAqB;YAC5B,EAAE,EAAE,iBAAiB,EAAE;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YACjC,QAAQ,EAAE,OAAO,CAAC,SAAS;YAC3B,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;YACnC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE;YAC/B,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC;YAChC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;YAC/D,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAC5B,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,CAAC;YACd,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,GAAG;SAChB,CAAC;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,EAAkB;IAC/C,OAAO,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAGD,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,iBAAiB,GAGlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AAKvE,MAAM,UAAU,UAAU,CAAC,KAAkC;IAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;IACzF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,OAAO,cAAe,SAAQ,kBAAoC;IACtE,YAAY,EAAkB;QAC5B,KAAK,CAAC,EAAsD,EAAE;YAC5D,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,sBAAsB;YAC7B,UAAU,EAAE,CAAC,WAAW,CAAC;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAwB,EAAE,IAAgB;QAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,GAAG,GAAqB;YAC5B,EAAE,EAAE,iBAAiB,EAAE;YACvB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO;YACjC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YACjC,QAAQ,EAAE,OAAO,CAAC,SAAS;YAC3B,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;YACnC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE;YAC/B,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC;YAChC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;YAC/D,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAC5B,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,CAAC;YACd,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,GAAG;SAChB,CAAC;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,EAAkB;IAC/C,OAAO,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAGD,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACtC,CAAC"}
package/lib/view.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMessages } from 'zhin.js/i18n';
1
2
  import { buildChoiceKeyboard } from '@zhin.js/game-kit';
2
3
  import { getRiddleById, RIDDLE_PREFIX, typeLabel } from './engine.js';
3
4
  import { currentRiddleId, parseQueue } from './session-service.js';
@@ -8,33 +9,33 @@ export function buildRiddleView(session, eventLines = [], channelType) {
8
9
  const riddleId = currentRiddleId(session);
9
10
  const entry = riddleId ? getRiddleById(riddleId) : undefined;
10
11
  const lines = [
11
- `🧩 **${typeLabel(session.mode)}**`,
12
+ `🧩 **${typeLabel(session.mode, session.locale ?? undefined)}**`,
12
13
  '',
13
- `进度 ${Math.min(session.index + 1, queue.length)}/${queue.length} · 得分 **${session.score}** · 连击 **${session.streak}**(最佳 ${session.best_streak})`,
14
+ messages(session.locale ?? undefined, 'text1', { p0: Math.min(session.index + 1, queue.length), p1: queue.length, p2: session.score, p3: session.streak, p4: session.best_streak }),
14
15
  ];
15
16
  if (terminal) {
16
- lines.push('', '🎊 **本轮题目已全部完成!**', `最终得分:**${session.score}**`);
17
+ lines.push('', messages(session.locale ?? undefined, 'text2'), messages(session.locale ?? undefined, 'text3', { p0: session.score }));
17
18
  }
18
19
  else if (entry) {
19
20
  lines.push('', `❓ ${entry.question}`);
20
21
  if (session.wrong_count > 0) {
21
- lines.push(`⚠️ 本题失误 ${session.wrong_count}/${MAX_WRONG}`);
22
+ lines.push(messages(session.locale ?? undefined, 'text4', { p0: session.wrong_count, p1: MAX_WRONG }));
22
23
  }
23
- lines.push('', session.mode === 'char' ? '请回复一个汉字。' : '请回复四字成语。');
24
+ lines.push('', session.mode === 'char' ? messages(session.locale ?? undefined, 'text5') : messages(session.locale ?? undefined, 'text6'));
24
25
  }
25
26
  if (eventLines.length)
26
27
  lines.push('', ...eventLines);
27
28
  if (!entry && !terminal)
28
- return '题目加载失败,请重新开始。';
29
+ return messages(session.locale ?? undefined, 'text7');
29
30
  const choices = terminal
30
31
  ? [
31
- { id: 'restart_char', label: '🔤 再来字谜', style: 'primary', keepEnabledWhenTerminal: true },
32
- { id: 'restart_idiom', label: '📜 再来成语', style: 'primary', keepEnabledWhenTerminal: true },
32
+ { id: 'restart_char', label: messages(session.locale ?? undefined, 'text8'), style: 'primary', keepEnabledWhenTerminal: true },
33
+ { id: 'restart_idiom', label: messages(session.locale ?? undefined, 'text9'), style: 'primary', keepEnabledWhenTerminal: true },
33
34
  ]
34
35
  : [
35
- { id: 'hint', label: '💡 提示', style: 'secondary' },
36
- { id: 'skip', label: '⏭️ 跳过', style: 'secondary' },
37
- { id: 'quit', label: '🏳️ 结束', style: 'danger' },
36
+ { id: 'hint', label: messages(session.locale ?? undefined, 'text10'), style: 'secondary' },
37
+ { id: 'skip', label: messages(session.locale ?? undefined, 'text11'), style: 'secondary' },
38
+ { id: 'quit', label: messages(session.locale ?? undefined, 'text12'), style: 'danger' },
38
39
  ];
39
40
  return buildChoiceKeyboard({
40
41
  gamePrefix: RIDDLE_PREFIX,
@@ -43,10 +44,25 @@ export function buildRiddleView(session, eventLines = [], channelType) {
43
44
  choices,
44
45
  terminal,
45
46
  buttonsPerRow: terminal ? 2 : 3,
46
- fallbackHint: '回复答案,或 1提示 2跳过 3结束',
47
+ fallbackHint: messages(session.locale ?? undefined, 'text13'),
47
48
  interactionProfile: terminal ? 'terminal' : 'gameplay',
48
49
  channelType,
49
50
  });
50
51
  }
51
52
  export { MAX_WRONG };
53
+ const messages = createMessages({
54
+ text1: { 'zh-CN': "进度 {p0}/{p1} · 得分 **{p2}** · 连击 **{p3}**(最佳 {p4})", en: "Progress {p0}/{p1} · Score **{p2}** · Streak **{p3}** (best {p4})" },
55
+ text2: { 'zh-CN': "🎊 **本轮题目已全部完成!**", en: "🎊 **All riddles completed!**" },
56
+ text3: { 'zh-CN': "最终得分:**{p0}**", en: "Final score: **{p0}**" },
57
+ text4: { 'zh-CN': "⚠️ 本题失误 {p0}/{p1}", en: "⚠️ Mistakes on this riddle: {p0}/{p1}" },
58
+ text5: { 'zh-CN': "请回复一个汉字。", en: "Reply with one Chinese character." },
59
+ text6: { 'zh-CN': "请回复四字成语。", en: "Reply with a four-character Chinese idiom." },
60
+ text7: { 'zh-CN': "题目加载失败,请重新开始。", en: "The riddle could not be loaded. Please start again." },
61
+ text8: { 'zh-CN': "🔤 再来字谜", en: "🔤 More character riddles" },
62
+ text9: { 'zh-CN': "📜 再来成语", en: "📜 More idiom riddles" },
63
+ text10: { 'zh-CN': "💡 提示", en: "💡 Hint" },
64
+ text11: { 'zh-CN': "⏭️ 跳过", en: "⏭️ Skip" },
65
+ text12: { 'zh-CN': "🏳️ 结束", en: "🏳️ End" },
66
+ text13: { 'zh-CN': "回复答案,或 1提示 2跳过 3结束", en: "Reply with your answer, or 1 Hint · 2 Skip · 3 End" },
67
+ });
52
68
  //# sourceMappingURL=view.js.map
package/lib/view.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,20 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineGameCommandAliasMiddleware, isRiddleAction, messageFromCommandInput, normalizeRiddleAction, } from '@zhin.js/game-kit';
3
- import { RIDDLE_HELP, runRiddleCommand } from "../../lib/riddle-command.js";
3
+ import { getRiddleHelp, runRiddleCommand } from "../../lib/riddle-command.js";
4
4
  import { resolveGameServices } from "../../lib/runtime-store.js";
5
5
  export default defineGameCommandAliasMiddleware({
6
6
  aliases: ['猜谜', 'riddle'],
7
7
  async run(action, input, context) {
8
+ const message = messageFromCommandInput(input, {
9
+ formatCommand: (path) => context.input.formatCommand?.(path, context.owner.id),
10
+ });
8
11
  const normalized = normalizeRiddleAction(String(action ?? ''));
9
12
  if (normalized === 'help')
10
- return RIDDLE_HELP;
13
+ return getRiddleHelp(message);
11
14
  // action 无法识别:放行给后续中间件,避免劫持普通聊天
12
15
  if (!isRiddleAction(normalized))
13
16
  return null;
14
17
  const services = resolveGameServices(context);
15
- const message = messageFromCommandInput(input);
16
18
  return runRiddleCommand(services, message, normalized);
17
19
  },
18
20
  });
@@ -4,18 +4,20 @@ import {
4
4
  messageFromCommandInput,
5
5
  normalizeRiddleAction,
6
6
  } from '@zhin.js/game-kit';
7
- import { RIDDLE_HELP, runRiddleCommand } from '../../src/riddle-command.js';
7
+ import { getRiddleHelp, runRiddleCommand } from '../../src/riddle-command.js';
8
8
  import { resolveGameServices } from '../../src/runtime-store.js';
9
9
 
10
10
  export default defineGameCommandAliasMiddleware({
11
11
  aliases: ['猜谜', 'riddle'],
12
12
  async run(action, input, context) {
13
+ const message = messageFromCommandInput(input, {
14
+ formatCommand: (path) => context.input.formatCommand?.(path, context.owner.id),
15
+ });
13
16
  const normalized = normalizeRiddleAction(String(action ?? ''));
14
- if (normalized === 'help') return RIDDLE_HELP;
17
+ if (normalized === 'help') return getRiddleHelp(message);
15
18
  // action 无法识别:放行给后续中间件,避免劫持普通聊天
16
19
  if (!isRiddleAction(normalized)) return null;
17
20
  const services = resolveGameServices(context);
18
- const message = messageFromCommandInput(input);
19
21
  return runRiddleCommand(services, message, normalized);
20
22
  },
21
23
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-word-riddle",
3
- "version": "1.1.15",
3
+ "version": "1.1.17",
4
4
  "description": "Zhin.js 猜谜 — 字谜与猜成语 (Plugin Runtime)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -24,13 +24,13 @@
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
26
  "chinese-idiom-chengyu": "^1.1.0",
27
- "@zhin.js/core": "1.1.50",
28
- "@zhin.js/game-kit": "1.1.15"
27
+ "@zhin.js/core": "1.1.52",
28
+ "@zhin.js/game-kit": "1.1.17"
29
29
  },
30
30
  "devDependencies": {
31
31
  "typescript": "^6.0.3",
32
32
  "vitest": "^4.1.10",
33
- "zhin.js": "1.1.15"
33
+ "zhin.js": "1.1.17"
34
34
  },
35
35
  "repository": {
36
36
  "type": "git",
@@ -67,9 +67,9 @@
67
67
  "plugins": []
68
68
  },
69
69
  "peerDependencies": {
70
- "@zhin.js/command": "^1.1.10",
71
- "@zhin.js/middleware": "^1.1.9",
72
- "zhin.js": "^1.1.15"
70
+ "@zhin.js/command": "^1.1.11",
71
+ "@zhin.js/middleware": "^1.1.10",
72
+ "zhin.js": "^1.1.17"
73
73
  },
74
74
  "peerDependenciesMeta": {
75
75
  "@zhin.js/command": {
package/plugin.js CHANGED
@@ -15,6 +15,10 @@ export default defineGamePlugin({
15
15
  displayName: 'Word Riddle',
16
16
  },
17
17
  game: {
18
+ commandPath: 'riddle',
19
+ titleI18n: { en: 'Word Riddle' },
20
+ descriptionI18n: { en: 'Solve Chinese character and idiom riddles' },
21
+ quickStartI18n: { en: 'start' },
18
22
  id: 'riddle',
19
23
  title: '猜谜',
20
24
  icon: '🧩',
package/src/engine.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMessages, type Locale } from 'zhin.js/i18n';
1
2
  import {
2
3
  getRiddleById,
3
4
  type RiddleEntry,
@@ -23,8 +24,13 @@ export function checkAnswer(entry: RiddleEntry, raw: string): boolean {
23
24
  return answersFor(entry).some((x) => x === a);
24
25
  }
25
26
 
26
- export function typeLabel(type: RiddleType): string {
27
- return type === 'char' ? '字谜' : '猜成语';
27
+ export function typeLabel(type: RiddleType, locale?: Locale): string {
28
+ return type === 'char' ? messages(locale, 'text1') : messages(locale, 'text2');
28
29
  }
29
30
 
30
31
  export { getRiddleById };
32
+
33
+ const messages = createMessages({
34
+ text1: { 'zh-CN': "字谜", en: "Chinese Character Riddles" },
35
+ text2: { 'zh-CN': "猜成语", en: "Chinese Idiom Riddles" },
36
+ });
package/src/game-flow.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMessages, resolveLocale } from 'zhin.js/i18n';
1
2
  import type { GameMessageLike, GameReply } from '@zhin.js/game-kit';
2
3
  import {
3
4
  answersFor,
@@ -50,11 +51,12 @@ export async function startGame(
50
51
  ): Promise<GameReply | undefined> {
51
52
  const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
52
53
  const active = await services.getActiveByChannel(ch);
54
+ const locale = resolveLocale(active ? active.locale : message.locale);
53
55
  if (active) {
54
56
  if (active.player_id === message.$sender.id) {
55
- return `你已有进行中的猜谜(${typeLabel(active.mode as RiddleType)}),发送「猜谜 继续」刷新。`;
57
+ return messages(locale, 'text1', { p0: typeLabel(active.mode as RiddleType, locale) });
56
58
  }
57
- return `本频道 ${active.player_name} 正在猜谜。`;
59
+ return messages(locale, 'text2', { p0: active.player_name });
58
60
  }
59
61
 
60
62
  const session = await services.createSession(message, mode);
@@ -69,7 +71,8 @@ export async function continueGame(
69
71
  `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`,
70
72
  message.$sender.id,
71
73
  );
72
- if (!session) return '你没有进行中的猜谜,发送「猜谜 开始」。';
74
+ const locale = resolveLocale(session ? session.locale : message.locale);
75
+ if (!session) return messages(locale, 'text3');
73
76
  return renderView(message, session);
74
77
  }
75
78
 
@@ -80,6 +83,7 @@ export async function processAnswerText(
80
83
  ): Promise<GameReply | null> {
81
84
  const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
82
85
  const session = await services.getActiveForUser(ch, message.$sender.id);
86
+ const locale = resolveLocale(session ? session.locale : message.locale);
83
87
  if (!session || session.status !== 'active') return null;
84
88
 
85
89
  const riddleId = currentRiddleId(session);
@@ -89,7 +93,7 @@ export async function processAnswerText(
89
93
  // 格式不合规(字数与答案不符)只提示、不扣失误:避免闲聊(「好的」「谢谢」)被累计判负
90
94
  const normalized = normalizeAnswer(raw);
91
95
  if (!answersFor(entry).some((a) => a.length === normalized.length)) {
92
- return `本题答案应为 ${entry.answer.length} 个字(这条不算失误)。`;
96
+ return messages(locale, 'text4', { p0: entry.answer.length });
93
97
  }
94
98
 
95
99
  if (checkAnswer(entry, raw)) {
@@ -104,8 +108,8 @@ export async function processAnswerText(
104
108
  const after = await advanceQuestion(services, (await services.getById(session.id))!);
105
109
  const explain = entry.explanation ? `\n📖 ${entry.explanation}` : '';
106
110
  return renderView(message, after, [
107
- `✅ 正确!答案:**${entry.answer}**${explain}`,
108
- `+${10 + Math.min(streak, 5)} 分`,
111
+ messages(locale, 'text5', { p0: entry.answer, p1: explain }),
112
+ messages(locale, 'text6', { p0: 10 + Math.min(streak, 5) }),
109
113
  ]);
110
114
  }
111
115
 
@@ -114,14 +118,14 @@ export async function processAnswerText(
114
118
  await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
115
119
  const after = await advanceQuestion(services, (await services.getById(session.id))!);
116
120
  return renderView(message, after, [
117
- `❌ 本题答案:**${entry.answer}**`,
118
- '失误过多,自动下一题。',
121
+ messages(locale, 'text7', { p0: entry.answer }),
122
+ messages(locale, 'text8'),
119
123
  ]);
120
124
  }
121
125
 
122
126
  await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
123
127
  const updated = (await services.getById(session.id))!;
124
- return renderView(message, updated, ['❌ 不对,再想想!']);
128
+ return renderView(message, updated, [messages(locale, 'text9')]);
125
129
  }
126
130
 
127
131
  export async function handleChoice(
@@ -131,8 +135,9 @@ export async function handleChoice(
131
135
  choiceId: string,
132
136
  ): Promise<GameReply | null> {
133
137
  const session = await services.getById(sessionId);
134
- if (!session) return '会话不存在。';
135
- if (session.player_id !== message.$sender.id) return '这是别人的猜谜。';
138
+ const locale = resolveLocale(session ? session.locale : message.locale);
139
+ if (!session) return messages(locale, 'text10');
140
+ if (session.player_id !== message.$sender.id) return messages(locale, 'text11');
136
141
 
137
142
  if (choiceId === 'restart_char') {
138
143
  await services.updateSession(session.id, { status: 'aborted' });
@@ -143,19 +148,19 @@ export async function handleChoice(
143
148
  return (await startGame(services, message, 'idiom')) ?? null;
144
149
  }
145
150
 
146
- if (session.status !== 'active') return '本轮已结束。';
151
+ if (session.status !== 'active') return messages(locale, 'text12');
147
152
 
148
153
  const riddleId = currentRiddleId(session);
149
154
  const entry = riddleId ? getRiddleById(riddleId) : undefined;
150
- if (!entry) return '题目丢失。';
155
+ if (!entry) return messages(locale, 'text13');
151
156
 
152
157
  if (choiceId === 'hint') {
153
- const hint = entry.hint ?? `答案共 ${entry.answer.length} 个字`;
158
+ const hint = entry.hint ?? messages(locale, 'text14', { p0: entry.answer.length });
154
159
  await services.updateSession(session.id, { hints_used: session.hints_used + 1, streak: 0 });
155
160
  const updated = (await services.getById(session.id))!;
156
161
  return renderView(message, updated, [
157
- `💡 提示:${hint}`,
158
- '(连击清零)',
162
+ messages(locale, 'text15', { p0: hint }),
163
+ messages(locale, 'text16'),
159
164
  ]);
160
165
  }
161
166
 
@@ -163,16 +168,38 @@ export async function handleChoice(
163
168
  await services.updateSession(session.id, { streak: 0 });
164
169
  const after = await advanceQuestion(services, session);
165
170
  return renderView(message, after, [
166
- `⏭️ 跳过,答案:**${entry.answer}**`,
171
+ messages(locale, 'text17', { p0: entry.answer }),
167
172
  ]);
168
173
  }
169
174
 
170
175
  if (choiceId === 'quit') {
171
176
  await services.updateSession(session.id, { status: 'aborted' });
172
- return '已结束猜谜。';
177
+ return messages(locale, 'text18');
173
178
  }
174
179
 
175
- return '未知操作。';
180
+ return messages(locale, 'text19');
176
181
  }
177
182
 
178
183
  export { RIDDLE_PREFIX };
184
+
185
+ const messages = createMessages({
186
+ text1: { 'zh-CN': "你已有进行中的猜谜({p0}),请使用当前对局的操作入口继续。", en: "You already have an active riddle game ({p0}). Continue using its controls." },
187
+ text2: { 'zh-CN': "本频道 {p0} 正在猜谜。", en: "{p0} is solving riddles in this channel." },
188
+ text3: { 'zh-CN': "你没有进行中的猜谜。", en: "You have no active riddle game." },
189
+ text4: { 'zh-CN': "本题答案应为 {p0} 个字(这条不算失误)。", en: "The answer has {p0} characters (this does not count as a mistake)." },
190
+ text5: { 'zh-CN': "✅ 正确!答案:**{p0}**{p1}", en: "✅ Correct! Answer: **{p0}**{p1}" },
191
+ text6: { 'zh-CN': "+{p0} 分", en: "+{p0} points" },
192
+ text7: { 'zh-CN': "❌ 本题答案:**{p0}**", en: "❌ Answer: **{p0}**" },
193
+ text8: { 'zh-CN': "失误过多,自动下一题。", en: "Too many mistakes. Moving to the next riddle." },
194
+ text9: { 'zh-CN': "❌ 不对,再想想!", en: "❌ Not quite. Try again!" },
195
+ text10: { 'zh-CN': "会话不存在。", en: "This game no longer exists." },
196
+ text11: { 'zh-CN': "这是别人的猜谜。", en: "This riddle game belongs to another player." },
197
+ text12: { 'zh-CN': "本轮已结束。", en: "This round has ended." },
198
+ text13: { 'zh-CN': "题目丢失。", en: "The riddle is unavailable." },
199
+ text14: { 'zh-CN': "答案共 {p0} 个字", en: "The answer has {p0} characters" },
200
+ text15: { 'zh-CN': "💡 提示:{p0}", en: "💡 Hint: {p0}" },
201
+ text16: { 'zh-CN': "(连击清零)", en: "(Streak reset)" },
202
+ text17: { 'zh-CN': "⏭️ 跳过,答案:**{p0}**", en: "⏭️ Skipped. Answer: **{p0}**" },
203
+ text18: { 'zh-CN': "已结束猜谜。", en: "The riddle game has ended." },
204
+ text19: { 'zh-CN': "未知操作。", en: "Unknown action." },
205
+ });
package/src/models.ts CHANGED
@@ -6,6 +6,7 @@ declare module '@zhin.js/core' {
6
6
  interface Models {
7
7
  word_riddle_sessions: {
8
8
  id: string;
9
+ locale?: 'zh-CN' | 'en' | null;
9
10
  adapter: string;
10
11
  endpoint: string;
11
12
  channel_type: string;
@@ -32,10 +33,11 @@ export type RiddleSessionRow = Models['word_riddle_sessions'];
32
33
 
33
34
 
34
35
  export function defineHostTables(
35
- db: { define: (name: string, definition: Record<string, unknown>) => void },
36
+ db: { define: (name: string, definition: Record<string, unknown>, options?: { readonly addColumns?: readonly string[] }) => void },
36
37
  ): void {
37
38
  db.define('word_riddle_sessions', {
38
39
  id: { type: 'text', primary: true },
40
+ locale: { type: 'text', nullable: true },
39
41
  adapter: { type: 'text', nullable: false },
40
42
  endpoint: { type: 'text', nullable: false },
41
43
  channel_type: { type: 'text', nullable: false },
@@ -54,5 +56,5 @@ export function defineHostTables(
54
56
  status: { type: 'text', default: 'active' },
55
57
  updated_at: { type: 'bigint', default: 0 },
56
58
  created_at: { type: 'bigint', default: 0 },
57
- });
59
+ }, { addColumns: ['locale'] });
58
60
  }
@@ -1,8 +1,5 @@
1
- import {
2
- channelKey,
3
- type GameMessageLike,
4
- type GameReply,
5
- } from '@zhin.js/game-kit';
1
+ import { formatGameHelp, gameCommandFeedback, gameCommandHint, channelKey, type GameMessageLike, type GameReply } from '@zhin.js/game-kit';
2
+ import { createMessages } from 'zhin.js/i18n';
6
3
  import { continueGame, startGame } from './game-flow.js';
7
4
  import { riddleCount, type RiddleType } from './riddles-catalog.js';
8
5
 
@@ -11,18 +8,26 @@ import type { SessionService } from './session-service.js';
11
8
 
12
9
  const counts = riddleCount();
13
10
 
14
- export const RIDDLE_HELP = [
15
- '🧩 猜谜(字谜 + 猜成语)',
16
- `字谜 ${counts.char.toLocaleString('zh-CN')} 题 · 成语 ${counts.idiom.toLocaleString('zh-CN')} 题`,
17
- '猜谜 / riddle — 帮助',
18
- '猜谜 开始 — 字谜模式',
19
- '猜谜 字谜 — 字谜模式',
20
- '猜谜 成语 — 猜成语模式',
21
- '猜谜 继续 — 刷新界面',
22
- '猜谜 放弃 — 结束',
23
- '',
24
- '进行中直接回复答案;连击加分,提示/失误会清零连击。',
25
- ].join('\n');
11
+
12
+ const messages = createMessages({
13
+ counts: { 'zh-CN': '字谜 {chars} 题 · 成语 {idioms} 题', en: '{chars} character riddles · {idioms} idiom riddles' },
14
+ char: { 'zh-CN': '{command} — 字谜模式', en: '{command} — Chinese character riddles' },
15
+ idiom: { 'zh-CN': '{command} — 猜成语模式', en: '{command} — Chinese idiom riddles' },
16
+ instructions: { 'zh-CN': '进行中直接回复答案;连击加分,提示/失误会清零连击。', en: 'Reply with the answer during play. Streaks earn bonus points; hints and mistakes reset the streak.' },
17
+ active: { 'zh-CN': '进行中:{mode} · 得分 {score} · 连击 {streak}', en: 'Playing: {mode} · Score {score} · Streak {streak}' },
18
+ quit: { 'zh-CN': '已放弃猜谜。', en: 'You quit the riddle game.' },
19
+ });
20
+
21
+ export function getRiddleHelp(message: Pick<GameMessageLike, 'locale' | 'formatCommand'> = {}): string {
22
+ const locale = message.locale ?? 'zh-CN';
23
+ const command = message.formatCommand?.('riddle');
24
+ return [formatGameHelp(message, { 'zh-CN': '🧩 猜谜(字谜 + 猜成语)', en: '🧩 Chinese Character and Idiom Riddles' }, 'riddle', ['start', 'continue', 'quit']),
25
+ messages(locale, 'counts', { chars: counts.char.toLocaleString(locale), idioms: counts.idiom.toLocaleString(locale) }),
26
+ ...(command ? [messages(locale, 'char', { command: command + ' char' }), messages(locale, 'idiom', { command: command + ' idiom' })] : []),
27
+ messages(locale, 'instructions'),
28
+ ].join('\n');
29
+ }
30
+ export const RIDDLE_HELP = getRiddleHelp();
26
31
 
27
32
  function parseMode(action: string): RiddleType | null {
28
33
  if (action === 'char' || action === '字谜') return 'char';
@@ -41,11 +46,11 @@ export async function runRiddleCommand(
41
46
 
42
47
  if (!action || action === 'help') {
43
48
  const active = await services.getActiveByChannel(ch);
44
- const lines = [RIDDLE_HELP, ''];
49
+ const lines = [getRiddleHelp(message), ''];
45
50
  if (active) {
46
- lines.push(`进行中:${typeLabel(active.mode as RiddleType)} · 得分 ${active.score} · 连击 ${active.streak}`);
51
+ lines.push(messages(active.locale ?? undefined, 'active', { mode: typeLabel(active.mode as RiddleType, active.locale ?? undefined), score: active.score, streak: active.streak }));
47
52
  } else {
48
- lines.push('暂无对局,发送「猜谜 开始」。');
53
+ lines.push(gameCommandFeedback(message, 'noGame'), gameCommandHint(message, 'riddle'));
49
54
  }
50
55
  return lines.join('\n');
51
56
  }
@@ -59,10 +64,10 @@ export async function runRiddleCommand(
59
64
 
60
65
  if (action === 'quit' || action === '放弃') {
61
66
  const row = await services.getActiveForUser(ch, userId);
62
- if (!row) return '你没有进行中的猜谜。';
67
+ if (!row) return gameCommandFeedback(message, 'noGame');
63
68
  await services.updateSession(row.id, { status: 'aborted' });
64
- return '已放弃猜谜。';
69
+ return messages(row.locale ?? undefined, 'quit');
65
70
  }
66
71
 
67
- return `未知子命令:${action}\n\n${RIDDLE_HELP}`;
72
+ return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getRiddleHelp(message);
68
73
  }
@@ -36,6 +36,7 @@ export class SessionService extends BaseSessionService<RiddleSessionRow> {
36
36
  const queue = pickRoundQueue(mode).map((r) => r.id);
37
37
  const row: RiddleSessionRow = {
38
38
  id: generateSessionId(),
39
+ locale: message.locale ?? 'zh-CN',
39
40
  adapter: String(message.$adapter),
40
41
  endpoint: message.$endpoint,
41
42
  channel_type: message.$channel.type,
package/src/view.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { createMessages } from 'zhin.js/i18n';
1
2
  import { buildChoiceKeyboard } from '@zhin.js/game-kit';
2
3
  import type { SendContent } from '@zhin.js/core/runtime';
3
4
  import { getRiddleById, RIDDLE_PREFIX, typeLabel } from './engine.js';
@@ -17,34 +18,34 @@ export function buildRiddleView(
17
18
  const entry = riddleId ? getRiddleById(riddleId) : undefined;
18
19
 
19
20
  const lines = [
20
- `🧩 **${typeLabel(session.mode as 'char' | 'idiom')}**`,
21
+ `🧩 **${typeLabel(session.mode as 'char' | 'idiom', session.locale ?? undefined)}**`,
21
22
  '',
22
- `进度 ${Math.min(session.index + 1, queue.length)}/${queue.length} · 得分 **${session.score}** · 连击 **${session.streak}**(最佳 ${session.best_streak})`,
23
+ messages(session.locale ?? undefined, 'text1', { p0: Math.min(session.index + 1, queue.length), p1: queue.length, p2: session.score, p3: session.streak, p4: session.best_streak }),
23
24
  ];
24
25
 
25
26
  if (terminal) {
26
- lines.push('', '🎊 **本轮题目已全部完成!**', `最终得分:**${session.score}**`);
27
+ lines.push('', messages(session.locale ?? undefined, 'text2'), messages(session.locale ?? undefined, 'text3', { p0: session.score }));
27
28
  } else if (entry) {
28
29
  lines.push('', `❓ ${entry.question}`);
29
30
  if (session.wrong_count > 0) {
30
- lines.push(`⚠️ 本题失误 ${session.wrong_count}/${MAX_WRONG}`);
31
+ lines.push(messages(session.locale ?? undefined, 'text4', { p0: session.wrong_count, p1: MAX_WRONG }));
31
32
  }
32
- lines.push('', session.mode === 'char' ? '请回复一个汉字。' : '请回复四字成语。');
33
+ lines.push('', session.mode === 'char' ? messages(session.locale ?? undefined, 'text5') : messages(session.locale ?? undefined, 'text6'));
33
34
  }
34
35
 
35
36
  if (eventLines.length) lines.push('', ...eventLines);
36
37
 
37
- if (!entry && !terminal) return '题目加载失败,请重新开始。';
38
+ if (!entry && !terminal) return messages(session.locale ?? undefined, 'text7');
38
39
 
39
40
  const choices = terminal
40
41
  ? [
41
- { id: 'restart_char', label: '🔤 再来字谜', style: 'primary' as const, keepEnabledWhenTerminal: true },
42
- { id: 'restart_idiom', label: '📜 再来成语', style: 'primary' as const, keepEnabledWhenTerminal: true },
42
+ { id: 'restart_char', label: messages(session.locale ?? undefined, 'text8'), style: 'primary' as const, keepEnabledWhenTerminal: true },
43
+ { id: 'restart_idiom', label: messages(session.locale ?? undefined, 'text9'), style: 'primary' as const, keepEnabledWhenTerminal: true },
43
44
  ]
44
45
  : [
45
- { id: 'hint', label: '💡 提示', style: 'secondary' as const },
46
- { id: 'skip', label: '⏭️ 跳过', style: 'secondary' as const },
47
- { id: 'quit', label: '🏳️ 结束', style: 'danger' as const },
46
+ { id: 'hint', label: messages(session.locale ?? undefined, 'text10'), style: 'secondary' as const },
47
+ { id: 'skip', label: messages(session.locale ?? undefined, 'text11'), style: 'secondary' as const },
48
+ { id: 'quit', label: messages(session.locale ?? undefined, 'text12'), style: 'danger' as const },
48
49
  ];
49
50
 
50
51
  return buildChoiceKeyboard({
@@ -54,10 +55,26 @@ export function buildRiddleView(
54
55
  choices,
55
56
  terminal,
56
57
  buttonsPerRow: terminal ? 2 : 3,
57
- fallbackHint: '回复答案,或 1提示 2跳过 3结束',
58
+ fallbackHint: messages(session.locale ?? undefined, 'text13'),
58
59
  interactionProfile: terminal ? 'terminal' : 'gameplay',
59
60
  channelType,
60
61
  });
61
62
  }
62
63
 
63
64
  export { MAX_WRONG };
65
+
66
+ const messages = createMessages({
67
+ text1: { 'zh-CN': "进度 {p0}/{p1} · 得分 **{p2}** · 连击 **{p3}**(最佳 {p4})", en: "Progress {p0}/{p1} · Score **{p2}** · Streak **{p3}** (best {p4})" },
68
+ text2: { 'zh-CN': "🎊 **本轮题目已全部完成!**", en: "🎊 **All riddles completed!**" },
69
+ text3: { 'zh-CN': "最终得分:**{p0}**", en: "Final score: **{p0}**" },
70
+ text4: { 'zh-CN': "⚠️ 本题失误 {p0}/{p1}", en: "⚠️ Mistakes on this riddle: {p0}/{p1}" },
71
+ text5: { 'zh-CN': "请回复一个汉字。", en: "Reply with one Chinese character." },
72
+ text6: { 'zh-CN': "请回复四字成语。", en: "Reply with a four-character Chinese idiom." },
73
+ text7: { 'zh-CN': "题目加载失败,请重新开始。", en: "The riddle could not be loaded. Please start again." },
74
+ text8: { 'zh-CN': "🔤 再来字谜", en: "🔤 More character riddles" },
75
+ text9: { 'zh-CN': "📜 再来成语", en: "📜 More idiom riddles" },
76
+ text10: { 'zh-CN': "💡 提示", en: "💡 Hint" },
77
+ text11: { 'zh-CN': "⏭️ 跳过", en: "⏭️ Skip" },
78
+ text12: { 'zh-CN': "🏳️ 结束", en: "🏳️ End" },
79
+ text13: { 'zh-CN': "回复答案,或 1提示 2跳过 3结束", en: "Reply with your answer, or 1 Hint · 2 Skip · 3 End" },
80
+ });