Skip to main content
Version: Next

Events Localization

Event handlers in CommandKit can also benefit from localization, allowing you to create multilingual responses and messages for various Discord events like message creation, member joins, and more.

Using Translations in Event Handlers​

Since event handlers don't have the same context as commands, you need to import the locale function directly from the i18n plugin:

src/app/events/messageCreate/handler.ts
import { locale } from '@commandkit/i18n';
import type { Message } from 'discord.js';

export default async function onMessageCreate(message: Message) {
// Skip bot messages
if (message.author.bot) return;

// Get translations for the guild's preferred locale
const { t } = locale(message.guild?.preferredLocale);

if (message.content.toLowerCase() === 'hello') {
await message.reply(t('greeting', { user: message.author.displayName }));
}

if (message.content.toLowerCase() === 'help') {
await message.reply(t('help_message'));
}
}

Event Translation Files​

Create translation files for your events using descriptive names:

src/app/locales/en-US/messageCreate.event.json
{
"greeting": "πŸ‘‹ Hello {{user}}! Welcome to our server!",
"help_message": "πŸ“– Use `/help` to see all available commands",
"auto_mod": {
"warning": "⚠️ {{user}}, please watch your language!",
"timeout": "πŸ”‡ {{user}} has been timed out for inappropriate language"
}
}
src/app/locales/fr/messageCreate.event.json
{
"greeting": "πŸ‘‹ Salut {{user}} ! Bienvenue sur notre serveur !",
"help_message": "πŸ“– Utilisez `/help` pour voir toutes les commandes disponibles",
"auto_mod": {
"warning": "⚠️ {{user}}, attention à votre langage !",
"timeout": "πŸ”‡ {{user}} a Γ©tΓ© mis en sourdine pour langage inappropriΓ©"
}
}

Advanced Event Localization​

Guild Welcome Messages​

src/app/events/guildMemberAdd/handler.ts
import { locale } from '@commandkit/i18n';
import type { GuildMember } from 'discord.js';

export default async function onGuildMemberAdd(member: GuildMember) {
const { t } = locale(member.guild.preferredLocale);

// Find welcome channel
const welcomeChannel = member.guild.channels.cache.find(
(channel) => channel.name === 'welcome',
);

if (welcomeChannel?.isTextBased()) {
const memberCount = member.guild.memberCount;

await welcomeChannel.send({
content: t('welcome.message', {
user: member.displayName,
guild: member.guild.name,
count: memberCount,
}),
// You can also send embeds with localized content
embeds: [
{
title: t('welcome.embed.title'),
description: t('welcome.embed.description', {
user: member.displayName,
}),
color: 0x00ff00,
fields: [
{
name: t('welcome.embed.fields.rules'),
value: t('welcome.embed.fields.rules_description'),
},
{
name: t('welcome.embed.fields.channels'),
value: t('welcome.embed.fields.channels_description'),
},
],
},
],
});
}
}
src/app/locales/en-US/guildMemberAdd.event.json
{
"welcome": {
"message": "πŸŽ‰ Welcome {{user}} to **{{guild}}**! You're our **{{count}}** member!",
"embed": {
"title": "Welcome to the Server!",
"description": "Hi {{user}}, we're glad to have you here!",
"fields": {
"rules": "πŸ“‹ Rules",
"rules_description": "Please read our rules in #rules channel",
"channels": "πŸ’¬ Important Channels",
"channels_description": "Check out #announcements and #general"
}
}
}
}

Locale Detection Strategies​

When working with events, you have several options for determining the appropriate locale:

// Use the guild's preferred locale set by server admins
const { t } = locale(message.guild?.preferredLocale);

2. User Locale​

// Use the individual user's Discord locale
const { t } = locale(message.author.locale);

3. Fallback Chain​

// Try multiple locale sources with fallback
const detectedLocale =
message.guild?.preferredLocale || message.author.locale || 'en-US';

const { t } = locale(detectedLocale);

4. Custom Locale Detection​

async function detectLocale(message: Message): Promise<string> {
// Custom logic: check database for user preferences
const userSettings = await getUserSettings(message.author.id);
if (userSettings?.language) {
return userSettings.language;
}

// Fall back to guild locale
return message.guild?.preferredLocale || 'en-US';
}

export default async function onMessageCreate(message: Message) {
const userLocale = await detectLocale(message);
const { t } = locale(userLocale);

// Use translations...
}

Error Handling with Localization​

Handle translation errors gracefully in event handlers:

src/app/events/messageCreate/autoMod.ts
import { locale } from '@commandkit/i18n';
import type { Message } from 'discord.js';

const FORBIDDEN_WORDS = ['spam', 'scam', 'hack'];

export default async function autoModerator(message: Message) {
if (message.author.bot) return;

try {
const { t } = locale(message.guild?.preferredLocale);

const hasViolation = FORBIDDEN_WORDS.some((word) =>
message.content.toLowerCase().includes(word),
);

if (hasViolation) {
// Delete the message
await message.delete();

// Send warning
await message.channel.send({
content: t('moderation.auto_warning', {
user: message.author.displayName,
}),
});

// Log the action
console.log(
t('moderation.log_message', {
user: message.author.tag,
guild: message.guild?.name,
channel: message.channel.name,
}),
);
}
} catch (error) {
// Fallback to English if translation fails
console.error('Translation error:', error);
await message.channel.send(
`⚠️ ${message.author.displayName}, please follow our community guidelines.`,
);
}
}

Best Practices for Event Localization​

  1. Always provide fallbacks: Event handlers should gracefully handle missing translations
  2. Use appropriate locale sources: Choose between guild, user, or custom locale detection based on context
  3. Keep translations consistent: Use the same tone and style across events and commands
  4. Test with different locales: Ensure your events work correctly with various language settings
  5. Cache translations when possible: For high-frequency events, consider caching translation functions