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