Skip to content

Commit

Permalink
feat: Додано підтримку локалізації
Browse files Browse the repository at this point in the history
Додано папку `locales` яка містить рядки локалізації, проведено локалізацію подій, команд, компонентів відповідно до рядків локалізації..
  • Loading branch information
GamesTwoLife committed Mar 12, 2024
1 parent d5b4b38 commit 75beba0
Show file tree
Hide file tree
Showing 33 changed files with 826 additions and 330 deletions.
16 changes: 13 additions & 3 deletions commands/info/ping.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
const { SlashCommandBuilder } = require("discord.js");
const { t } = require("i18next");

/**
* @type {import('../../typings').Command}
*/
module.exports = {
data: new SlashCommandBuilder()
.setName("ping")
.setDescription("Ping Pong.")
.setDescription(t('commands:info.ping.description', { lng: "en-US" }))
.setDescriptionLocalizations({
'en-GB': t('commands:info.ping.description', { lng: "en-GB" }),
uk: t('commands:info.ping.description', { lng: "uk" }),
ru: t('commands:info.ping.description', { lng: "ru" })
})
.setDMPermission(false),
options: {
cooldown: 30,
ownerOnly: false,
devGuildOnly: true,
cooldown: 0,
bot_permissions: ["ViewChannel", "SendMessages"],
},

async execute(interaction) {
const { client } = interaction;

await interaction.reply({ content: `Pong!\nWebsocket ping: **${client.ws.ping}**ms`, ephemeral: true });
await interaction.deferReply()

const reply = await interaction.fetchReply()

await interaction.editReply({ content: t('commands:info.ping.content', { lng: interaction.locale, ping: Math.round(client.ws.ping), latency: Math.round(reply.createdTimestamp - interaction.createdTimestamp) }) });
},
};
13 changes: 9 additions & 4 deletions commands/sample/message sample.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
const { ContextMenuCommandBuilder, ApplicationCommandType } = require("discord.js");
const { t } = require("i18next");

/**
* @type {import("../../typings").Command}
*/
module.exports = {
data: new ContextMenuCommandBuilder()
.setName("message sample")
.setName(t('commands:sample.message_sample.description', { lng: "en" }).slice(0, 32))
.setNameLocalizations({
uk: t('commands:sample.message_sample.description', { lng: "uk" }).slice(0, 32),
ru: t('commands:sample.message_sample.description', { lng: "ru" }).slice(0, 32)
})
.setType(ApplicationCommandType.Message)
.setDMPermission(false),
options: {
cooldown: 0,
cooldown: 10,
ownerOnly: false,
devGuildOnly: true,
bot_permissions: ["ViewChannel", "SendMessages"],
Expand All @@ -19,9 +24,9 @@ module.exports = {
if (!interaction.isMessageContextMenuCommand()) return;

const { targetId, targetMessage } = interaction;

await interaction.reply({
content: `Це відповідь на команду контекстного меню повідомлення\nID повідомлення: ${targetId}\nКонтент повідомлення: ${targetMessage}`,
content: t('commands:sample.message_sample.content', { lng: interaction.locale, id: targetId, message: targetMessage.content }),
ephemeral: true
});
},
Expand Down
99 changes: 72 additions & 27 deletions commands/sample/sample.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, StringSelectMenuBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, EmbedBuilder } = require("discord.js");
const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, StringSelectMenuBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, EmbedBuilder, UserSelectMenuBuilder, ChannelSelectMenuBuilder, MentionableSelectMenuBuilder, RoleSelectMenuBuilder } = require("discord.js");
const { t } = require("i18next");
const buttonPagination = require("../../utils/buttonPagination");
const buttonWrapper = require("../../utils/buttonWrapper");

Expand All @@ -8,49 +9,82 @@ const buttonWrapper = require("../../utils/buttonWrapper");
module.exports = {
data: new SlashCommandBuilder()
.setName("sample")
.setDescription("Sample Autocomplete/Button/Menu/Modal.")
.setDescription(t('commands:sample.sample.description', { lng: "en" }))
.setDescriptionLocalizations({
uk: t('commands:sample.sample.description', { lng: "uk" }),
ru: t('commands:sample.sample.description', { lng: "ru" })
})
.addSubcommand(subcommand =>
subcommand
.setName("autocomplete")
.setDescription("Sample Autocomplete")
.setDescription(t('commands:sample.sample.autocomplete.description', { lng: "en" }))
.setDescriptionLocalizations({
uk: t('commands:sample.sample.autocomplete.description', { lng: "uk" }),
ru: t('commands:sample.sample.autocomplete.description', { lng: "ru" })
})
.addStringOption(option =>
option
.setName("input")
.setDescription("Input")
.setDescription(t('commands:sample.sample.autocomplete.options.input', { lng: "en" }))
.setDescriptionLocalizations({
uk: t('commands:sample.sample.autocomplete.options.input', { lng: "uk" }),
ru: t('commands:sample.sample.autocomplete.options.input', { lng: "ru" })
})
.setAutocomplete(true)
.setRequired(true)
)
)
.addSubcommand(subcommand =>
subcommand
.setName("button")
.setDescription("Sample Button")
.setDescription(t('commands:sample.sample.button.description', { lng: "en" }))
.setDescriptionLocalizations({
uk: t('commands:sample.sample.button.description', { lng: "uk" }),
ru: t('commands:sample.sample.button.description', { lng: "ru" })
})
)
.addSubcommand(subcommand =>
subcommand
.setName("menu")
.setDescription("Sample Menu")
.setDescription(t('commands:sample.sample.menu.description', { lng: "en" }))
.setDescriptionLocalizations({
uk: t('commands:sample.sample.menu.description', { lng: "uk" }),
ru: t('commands:sample.sample.menu.description', { lng: "ru" })
})
)
.addSubcommand(subcommand =>
subcommand
.setName("modal")
.setDescription("Sample Modal")
.setDescription(t('commands:sample.sample.modal.description', { lng: "en" }))
.setDescriptionLocalizations({
uk: t('commands:sample.sample.modal.description', { lng: "uk" }),
ru: t('commands:sample.sample.modal.description', { lng: "ru" })
})
)
.addSubcommand(subcommand =>
subcommand
.setName("pagination")
.setDescription("Sample Pagination")
.setDescription(t('commands:sample.sample.pagination.description', { lng: "en" }))
.setDescriptionLocalizations({
uk: t('commands:sample.sample.pagination.description', { lng: "uk" }),
ru: t('commands:sample.sample.pagination.description', { lng: "ru" })
})
)
.addSubcommand(subcommand =>
subcommand
.setName("buttonwrapper")
.setDescription("Sample Button Wrapper")
.setDescription(t('commands:sample.sample.buttonwrapper.description', { lng: "en" }))
.setDescriptionLocalizations({
uk: t('commands:sample.sample.buttonwrapper.description', { lng: "uk" }),
ru: t('commands:sample.sample.buttonwrapper.description', { lng: "ru" })
})
)
.setDMPermission(false),
options: {
cooldown: 10,
ownerOnly: false,
devGuildOnly: true,
cooldown: 0,
bot_permissions: ["ViewChannel", "SendMessages"],
},

Expand All @@ -74,27 +108,45 @@ module.exports = {
.setLabel("sample button")
);

await interaction.reply({
content: "Кнопка",
await interaction.reply({
components: [row]
});
} break;

case "menu": {
const row = new ActionRowBuilder().addComponents(
new StringSelectMenuBuilder()
.setCustomId("sample")
.setCustomId("string_sample")
.setOptions(
{
label: "sample option",
value: "sample_option"
},
{
label: "sample option_two",
value: "sample_option_two"
}
)
);

await interaction.reply({
content: "Меню",
components: [row]
const row2 = new ActionRowBuilder().addComponents(
new UserSelectMenuBuilder().setCustomId("user_sample")
);

const row3 = new ActionRowBuilder().addComponents(
new MentionableSelectMenuBuilder().setCustomId("mentionable_sample")
);

const row4 = new ActionRowBuilder().addComponents(
new ChannelSelectMenuBuilder().setCustomId("channel_sample")
);

const row5 = new ActionRowBuilder().addComponents(
new RoleSelectMenuBuilder().setCustomId("role_sample")
);

await interaction.reply({
components: [row, row2, row3, row4, row5]
});
} break;

Expand All @@ -117,17 +169,10 @@ module.exports = {
} break;

case "pagination": {
let pageStrings = [
"Котики найкращі :)",
"Песики найкращі :)",
"Україна понад усе!",
"Слава Україні! Героям Слава!",
"Крутий шаблон бота"
];
let embeds = [];

for (let i = 0; i < 4; i++) {
embeds.push(new EmbedBuilder().setColor(0x2b2d31).setDescription(`${pageStrings[i]}`));
for (let i = 0; i < 5; i++) {
embeds.push(new EmbedBuilder().setColor(0x2b2d31).setDescription(`${t(`commands:sample.sample.pagination.pageStrings.${[i]}`, { lng: interaction.locale })}`));
}

await buttonPagination(interaction, embeds);
Expand All @@ -138,15 +183,15 @@ module.exports = {
new ButtonBuilder()
.setCustomId("say_hello")
.setStyle(ButtonStyle.Secondary)
.setLabel("Натисни на мене"),
.setLabel(t('commands:sample.sample.buttonwrapper.say_hello', { lng: interaction.locale })),
new ButtonBuilder()
.setLabel("Найкращий шаблон Discord бота")
.setLabel(t('commands:sample.sample.buttonwrapper.cool_template', { lng: interaction.locale }))
.setStyle(ButtonStyle.Link)
.setURL("https://github.com/GamesTwoLife/DiscordBot-Template"),
];

await interaction.reply({
content: "Натискайте на кнопки знизу:",
content: t('commands:sample.sample.buttonwrapper.content', { lng: interaction.locale }),
components: buttonWrapper(buttons)
});
} break;
Expand Down
13 changes: 9 additions & 4 deletions commands/sample/user sample.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
const { ContextMenuCommandBuilder, ApplicationCommandType } = require("discord.js");
const { t } = require("i18next");

/**
* @type {import("../../typings").Command}
*/
module.exports = {
data: new ContextMenuCommandBuilder()
.setName("user sample")
.setName(t('commands:sample.user_sample.description', { lng: "en" }).slice(0, 32))
.setNameLocalizations({
uk: t('commands:sample.user_sample.description', { lng: "uk" }).slice(0, 32),
ru: t('commands:sample.user_sample.description', { lng: "ru" }).slice(0, 32)
})
.setType(ApplicationCommandType.User)
.setDMPermission(false),
options: {
cooldown: 0,
cooldown: 10,
ownerOnly: false,
devGuildOnly: true,
bot_permissions: ["ViewChannel", "SendMessages"],
Expand All @@ -19,9 +24,9 @@ module.exports = {
if (!interaction.isUserContextMenuCommand()) return;

const { targetId, targetMember, targetUser} = interaction;

await interaction.reply({
content: `Це відповідь на команду контекстного меню користувача\nID користувача: ${targetId}\nУчасник/Користувач: ${targetMember} / ${targetUser}`,
content: t('commands:sample.user_sample.content', { lng: interaction.locale, id: targetId, member: targetMember.toString(), user: targetUser.toString() }),
ephemeral: true
});
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
/**
* @type {import("../../../typings").AutocompleteInteraction}
* @type {import("../../../typings").Autocomplete}
*/
module.exports = {
name: "sample",
type: "autocomplete",

async execute(interaction) {
if (!interaction.isAutocomplete()) return;

const { options } = interaction;

const choices = ['Популярні теми: Потоки', 'Шардинг: Початок роботи', 'Бібліотека: Голосові з’єднання', 'Взаємодії: Відповідь на (/) команди', 'Популярні теми: Попередній перегляд для вставлення'];
const choices = ['Popular Topics: Threads', 'Sharding: Getting started', 'Library: Voice Connections', 'Interactions: Replying to slash commands', 'Popular Topics: Embed preview'];

const focusedValue = options.getFocused();
if (focusedValue.length === 0) {
Expand All @@ -18,7 +21,7 @@ module.exports = {

const filtered = choices.filter(choice => choice.startsWith(focusedValue));

await interaction.respond(
return interaction.respond(
filtered.map(choice => ({ name: choice, value: choice })),
);
},
Expand Down
12 changes: 0 additions & 12 deletions components/buttons/category/sample.js

This file was deleted.

12 changes: 0 additions & 12 deletions components/buttons/category/say_hello.js

This file was deleted.

13 changes: 13 additions & 0 deletions components/buttons/sample/sample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* @type {import("../../../typings").Button}
*/
module.exports = {
name: "sample",
type: "button",

async execute(interaction) {
if (!interaction.isButton()) return;

return interaction.reply({ content: `${interaction.customId}`, ephemeral: true });
},
};
13 changes: 13 additions & 0 deletions components/buttons/sample/say_hello.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* @type {import("../../../typings").Button}
*/
module.exports = {
name: "say_hello",
type: "button",

async execute(interaction) {
if (!interaction.isButton()) return;

return interaction.reply({ content: `Hello, ${interaction.user}!`, ephemeral: true });
},
};
16 changes: 0 additions & 16 deletions components/modals/category/sample.js

This file was deleted.

Loading

0 comments on commit 75beba0

Please sign in to comment.