Plugin
Translate
Translate messages with Google Translate, DeepL or Kagi.
1
/*2
* FiveCord — a Discord client mod3
* Copyright (c) 2025 FiveCord4
* SPDX-License-Identifier: GPL-3.0-or-later5
*/6
7
import "./styles.css";8
9
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";10
import { Devs } from "@utils/constants";11
import definePlugin from "@utils/types";12
import { Message } from "@vencord/discord-types";13
import { ChannelStore, Menu } from "@webpack/common";14
15
import { settings } from "./settings";16
import { setShouldShowTranslateEnabledTooltip, TranslateChatBarIcon, TranslateIcon } from "./TranslateIcon";17
import { handleTranslate, TranslationAccessory } from "./TranslationAccessory";18
import { translate } from "./utils";19
20
const messageCtxPatch: NavContextMenuPatchCallback = (children, { message }: { message: Message; }) => {21
const content = getMessageContent(message);22
if (!content) return;23
24
const group = findGroupChildrenByChildId("copy-text", children);25
if (!group) return;26
27
group.splice(group.findIndex(c => c?.props?.id === "copy-text") + 1, 0, (28
<Menu.MenuItem29
id="vc-trans"30
label="Translate"31
icon={TranslateIcon}32
action={async () => {33
const trans = await translate("received", content);34
handleTranslate(message.id, trans);35
}}36
/>37
));38
};39
40
41
function getMessageContent(message: Message) {42
// Message snapshots is an array, which allows for nested snapshots, which Discord does not do yet.43
// no point collecting content or rewriting this to render in a certain way that makes sense44
// for something currently impossible.45
return message.content46
|| message.messageSnapshots?.[0]?.message.content47
|| message.embeds?.find(embed => embed.type === "auto_moderation_message")?.rawDescription || "";48
}49
50
let tooltipTimeout: any;51
52
export default definePlugin({53
name: "Translate",54
description: "Translate messages with Google Translate, DeepL or Kagi.",55
tags: ["Chat", "Utility"],56
authors: [Devs.Ven, Devs.AshtonMemer, Devs.koish1],57
settings,58
contextMenus: {59
"message": messageCtxPatch60
},61
// not used, just here in case some other plugin wants it or w/e62
translate,63
64
renderMessageAccessory: props => <TranslationAccessory message={props.message} />,65
66
chatBarButton: {67
icon: TranslateIcon,68
render: TranslateChatBarIcon69
},70
71
messagePopoverButton: {72
icon: TranslateIcon,73
render(message: Message) {74
const content = getMessageContent(message);75
if (!content) return null;76
77
return {78
label: "Translate",79
icon: TranslateIcon,80
message,81
channel: ChannelStore.getChannel(message.channel_id),82
onClick: async () => {83
const trans = await translate("received", content);84
handleTranslate(message.id, trans);85
}86
};87
}88
},89
90
async onBeforeMessageSend(_, message) {91
if (!settings.store.autoTranslate) return;92
if (!message.content) return;93
94
setShouldShowTranslateEnabledTooltip?.(true);95
clearTimeout(tooltipTimeout);96
tooltipTimeout = setTimeout(() => setShouldShowTranslateEnabledTooltip?.(false), 2000);97
98
const trans = await translate("sent", message.content);99
message.content = trans.text;100
}101
});102