Skip to content

Commit a89caf1

Browse files
committed
feat: context menu command names
1 parent c88bff4 commit a89caf1

File tree

7 files changed

+154
-4
lines changed

7 files changed

+154
-4
lines changed

apps/website/docs/guide/02-commands/03-context-menu-commands.mdx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,57 @@ very similar to message context menu commands.
144144

145145
</TabItem>
146146
</Tabs>
147+
148+
You may have noticed that the context menu command names are the same as the message command names.
149+
This is because the context menu command names are borrowed from the non-context menu command names.
150+
151+
In order to change the context menu command name, you can use the `nameAliases` option in the `CommandMetadata` object.
152+
153+
:::warning
154+
155+
If you are using the [i18n plugin](../05-official-plugins/05-commandkit-i18n.mdx), the plugin will add `name_localizations` to the `nameAliases` option if localization for the context menu command name is provided.
156+
157+
```json title="src/app/locales/en/command.json"
158+
{
159+
"$command": {
160+
"name": "Report", // this will add `name_localizations` to the regular command name
161+
"description": "Report a message or user to moderators." // this will add `description_localizations` to the regular command description
162+
},
163+
"$command:user-ctx": {
164+
"name": "Report User" // this will add `name_localizations` to the `nameAliases.user` option
165+
},
166+
"$command:message-ctx": {
167+
"name": "Report Message" // this will add `name_localizations` to the `nameAliases.message` option
168+
}
169+
}
170+
```
171+
172+
:::
173+
174+
<Tabs>
175+
<TabItem value="ts" label="TypeScript" default>
176+
```ts title="src/app/commands/report-user.ts"
177+
import type { CommandMetadata } from 'commandkit';
178+
import { MessageFlags } from 'discord.js';
179+
180+
export const metadata: CommandMetadata = {
181+
nameAliases: {
182+
user: 'Report User',
183+
message: 'Report Message',
184+
}
185+
};
186+
```
187+
188+
</TabItem>
189+
<TabItem value="js" label="JavaScript">
190+
```js title="src/app/commands/report-user.js"
191+
/** @type {CommandMetadata} */
192+
export const metadata = {
193+
nameAliases: {
194+
user: 'Report User',
195+
message: 'Report Message',
196+
}
197+
};
198+
```
199+
</TabItem>
200+
</Tabs>

packages/commandkit/src/app/register/CommandRegistrar.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export class CommandRegistrar {
6464
) {
6565
collections.push({
6666
...json,
67+
name: __metadata?.nameAliases?.user ?? json.name,
6768
type: ApplicationCommandType.User,
6869
options: undefined,
6970
description_localizations: undefined,
@@ -80,6 +81,7 @@ export class CommandRegistrar {
8081
) {
8182
collections.push({
8283
...json,
84+
name: __metadata?.nameAliases?.message ?? json.name,
8385
type: ApplicationCommandType.Message,
8486
description_localizations: undefined,
8587
// @ts-ignore

packages/commandkit/src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ export interface CommandMetadata {
6464
* The bot permissions required to execute the command.
6565
*/
6666
botPermissions?: PermissionsString | PermissionsString[];
67+
/**
68+
* The name aliases for the `user` and `message` context menu commands. When i18n plugin is in use, this option will be ignored if the translation for the context menu command name is provided.
69+
*/
70+
nameAliases?: Record<'user' | 'message', string>;
6771
}
6872

6973
/**

packages/i18n/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,20 @@ If your translation file contains `$command` key with localization object, it wi
6666
}
6767
]
6868
},
69+
"$command:user-ctx": {
70+
"name": "Ping"
71+
},
72+
"$command:message-ctx": {
73+
"name": "Ping"
74+
},
6975
"response": "Pong! The latency is {{latency}}ms"
7076
}
7177
```
7278

7379
The `$command` key defines localization for the command name and description (or options). These properties are later merged with the actual command to build the final command object with localizations that Discord understands. Anything else in the translation file is used to localize the command response.
7480

81+
The `$command:user-ctx` and `$command:message-ctx` keys define localization for the user context menu and message context menu command names.
82+
7583
This plugin adds `locale()` function to your command context. You can use it to localize your command responses.
7684

7785
```ts

packages/i18n/src/constants.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,15 @@ export const DISCORD_LOCALES = new Set(
1212
* This key is used to store metadata about commands in the i18n system.
1313
*/
1414
export const COMMAND_METADATA_KEY = '$command';
15+
16+
/**
17+
* Metadata key for user context menu command localization.
18+
* This key is used to store metadata about user context menu commands in the i18n system.
19+
*/
20+
export const USER_CTX_COMMAND_METADATA_KEY = '$command:user-ctx';
21+
22+
/**
23+
* Metadata key for message context menu command localization.
24+
* This key is used to store metadata about message context menu commands in the i18n system.
25+
*/
26+
export const MESSAGE_CTX_COMMAND_METADATA_KEY = '$command:message-ctx';

packages/i18n/src/i18n.ts

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,24 @@ import CommandKit, {
2020
CommandKitHMREvent,
2121
getCommandKit,
2222
COMMANDKIT_CWD,
23+
PreRegisterCommandsEvent,
2324
} from 'commandkit';
2425
import FsBackend from 'i18next-fs-backend';
2526
import { basename, extname, join } from 'path';
2627
import { FsBackendOptions } from 'i18next-fs-backend';
27-
import { Locale } from 'discord.js';
28+
import { ApplicationCommandType, Locale } from 'discord.js';
2829
import { existsSync } from 'fs';
29-
import { CommandTranslation, CommandTranslationMetadata } from './types';
30-
import { COMMAND_METADATA_KEY, DISCORD_LOCALES } from './constants';
30+
import {
31+
BasicCommandTranslationMetadata,
32+
CommandTranslation,
33+
CommandTranslationMetadata,
34+
} from './types';
35+
import {
36+
COMMAND_METADATA_KEY,
37+
DISCORD_LOCALES,
38+
MESSAGE_CTX_COMMAND_METADATA_KEY,
39+
USER_CTX_COMMAND_METADATA_KEY,
40+
} from './constants';
3141
import { applyTranslations } from './utils';
3242
import { readdir, readFile } from 'fs/promises';
3343

@@ -330,10 +340,20 @@ export class I18nPlugin extends RuntimePlugin<LocalizationPluginOptions> {
330340
if (!translation) return;
331341

332342
const metadata = translation[COMMAND_METADATA_KEY];
343+
const userCtxMetadata = translation[USER_CTX_COMMAND_METADATA_KEY];
344+
const messageCtxMetadata = translation[MESSAGE_CTX_COMMAND_METADATA_KEY];
333345

334346
if (metadata) {
335347
this.metadata.set(`${locale}:${name}`, metadata);
336348
}
349+
350+
if (userCtxMetadata) {
351+
this.metadata.set(`${locale}:${name}:user-ctx`, userCtxMetadata);
352+
}
353+
354+
if (messageCtxMetadata) {
355+
this.metadata.set(`${locale}:${name}:message-ctx`, messageCtxMetadata);
356+
}
337357
} catch {}
338358
}
339359

@@ -383,4 +403,32 @@ export class I18nPlugin extends RuntimePlugin<LocalizationPluginOptions> {
383403

384404
return data;
385405
}
406+
407+
public async onBeforeRegisterCommands(
408+
ctx: CommandKitPluginRuntime,
409+
event: PreRegisterCommandsEvent,
410+
): Promise<void> {
411+
const { commands } = event;
412+
const validTypes = [
413+
ApplicationCommandType.User,
414+
ApplicationCommandType.Message,
415+
];
416+
417+
for (const command of commands) {
418+
if (!validTypes.includes(command.type!)) continue;
419+
420+
for (const locale of DISCORD_LOCALES) {
421+
const translationBasic = (
422+
command.type === ApplicationCommandType.User
423+
? this.metadata.get(`${locale}:${command.name}:user-ctx`)
424+
: this.metadata.get(`${locale}:${command.name}:message-ctx`)
425+
) as BasicCommandTranslationMetadata;
426+
427+
if (translationBasic?.name) {
428+
command.name_localizations ??= {};
429+
command.name_localizations[locale] = translationBasic.name;
430+
}
431+
}
432+
}
433+
}
386434
}

packages/i18n/src/types.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { COMMAND_METADATA_KEY } from './constants';
1+
import {
2+
COMMAND_METADATA_KEY,
3+
MESSAGE_CTX_COMMAND_METADATA_KEY,
4+
USER_CTX_COMMAND_METADATA_KEY,
5+
} from './constants';
26

37
/**
48
* Represents the metadata for command translations.
@@ -21,6 +25,16 @@ export interface CommandTranslationMetadata {
2125
)[];
2226
}
2327

28+
/**
29+
* Represents the metadata for basic command translations.
30+
*/
31+
export interface BasicCommandTranslationMetadata {
32+
/**
33+
* The name of the command.
34+
*/
35+
name?: string;
36+
}
37+
2438
/**
2539
* Represents a command translation, including its metadata and translations.
2640
*/
@@ -29,6 +43,14 @@ export interface CommandTranslation {
2943
* The metadata for the command translation.
3044
*/
3145
[COMMAND_METADATA_KEY]: CommandTranslationMetadata;
46+
/**
47+
* The metadata for the user context menu command translation.
48+
*/
49+
[USER_CTX_COMMAND_METADATA_KEY]: BasicCommandTranslationMetadata;
50+
/**
51+
* The metadata for the message context menu command translation.
52+
*/
53+
[MESSAGE_CTX_COMMAND_METADATA_KEY]: BasicCommandTranslationMetadata;
3254
/**
3355
* The translations for the command, keyed by locale.
3456
*/

0 commit comments

Comments
 (0)