chore: more localisation
This commit is contained in:
parent
22e5396684
commit
a4d4d981e0
1
.vscode/i18n-ally-custom-framework.yml
vendored
1
.vscode/i18n-ally-custom-framework.yml
vendored
|
@ -10,6 +10,7 @@ usageMatchRegex:
|
||||||
|
|
||||||
refactorTemplates:
|
refactorTemplates:
|
||||||
- "$t(\"$1\")"
|
- "$t(\"$1\")"
|
||||||
|
- "{$t(\"$1\")}"
|
||||||
- "<Translate i18nKey=\"$1\" />"
|
- "<Translate i18nKey=\"$1\" />"
|
||||||
|
|
||||||
monopoly: true
|
monopoly: true
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { proxyLazy } from "@utils/lazy";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { classes, isObjectEmpty } from "@utils/misc";
|
import { classes, isObjectEmpty } from "@utils/misc";
|
||||||
import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize } from "@utils/modal";
|
import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize } from "@utils/modal";
|
||||||
|
import { $t } from "@utils/translation";
|
||||||
import { OptionType, Plugin } from "@utils/types";
|
import { OptionType, Plugin } from "@utils/types";
|
||||||
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
||||||
import { Button, Clickable, FluxDispatcher, Forms, React, Text, Tooltip, UserStore, UserUtils } from "@webpack/common";
|
import { Button, Clickable, FluxDispatcher, Forms, React, Text, Tooltip, UserStore, UserUtils } from "@webpack/common";
|
||||||
|
@ -129,7 +130,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
|
||||||
|
|
||||||
function renderSettings() {
|
function renderSettings() {
|
||||||
if (!hasSettings || !plugin.options) {
|
if (!hasSettings || !plugin.options) {
|
||||||
return <Forms.FormText>There are no settings for this plugin.</Forms.FormText>;
|
return <Forms.FormText>{$t("vencord.noSettings")}</Forms.FormText>;
|
||||||
} else {
|
} else {
|
||||||
const options = Object.entries(plugin.options).map(([key, setting]) => {
|
const options = Object.entries(plugin.options).map(([key, setting]) => {
|
||||||
if (setting.hidden) return null;
|
if (setting.hidden) return null;
|
||||||
|
@ -227,7 +228,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Forms.FormSection className={Margins.bottom16}>
|
<Forms.FormSection className={Margins.bottom16}>
|
||||||
<Forms.FormTitle tag="h3">Settings</Forms.FormTitle>
|
<Forms.FormTitle tag="h3">{$t("vencord.settings")}</Forms.FormTitle>
|
||||||
{renderSettings()}
|
{renderSettings()}
|
||||||
</Forms.FormSection>
|
</Forms.FormSection>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
@ -242,7 +243,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Tooltip text="You must fix all errors before saving" shouldShow={!canSubmit()}>
|
<Tooltip text={$t("vencord.settingsErrors")} shouldShow={!canSubmit()}>
|
||||||
{({ onMouseEnter, onMouseLeave }) => (
|
{({ onMouseEnter, onMouseLeave }) => (
|
||||||
<Button
|
<Button
|
||||||
size={Button.Sizes.SMALL}
|
size={Button.Sizes.SMALL}
|
||||||
|
@ -252,12 +253,12 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
disabled={!canSubmit()}
|
disabled={!canSubmit()}
|
||||||
>
|
>
|
||||||
Save & Close
|
{$t("vencord.saveAndClose")}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Flex>
|
</Flex>
|
||||||
{saveError && <Text variant="text-md/semibold" style={{ color: "var(--text-danger)" }}>Error while saving: {saveError}</Text>}
|
{saveError && <Text variant="text-md/semibold" style={{ color: "var(--text-danger)" }}>{$t("vencord.settingsSaveError", { saveError })}</Text>}
|
||||||
</Flex>
|
</Flex>
|
||||||
</ModalFooter>}
|
</ModalFooter>}
|
||||||
</ModalRoot>
|
</ModalRoot>
|
||||||
|
|
|
@ -33,6 +33,7 @@ import { Margins } from "@utils/margins";
|
||||||
import { classes, isObjectEmpty } from "@utils/misc";
|
import { classes, isObjectEmpty } from "@utils/misc";
|
||||||
import { openModalLazy } from "@utils/modal";
|
import { openModalLazy } from "@utils/modal";
|
||||||
import { useAwaiter } from "@utils/react";
|
import { useAwaiter } from "@utils/react";
|
||||||
|
import { lowercaseify } from "@utils/text";
|
||||||
import { $t } from "@utils/translation";
|
import { $t } from "@utils/translation";
|
||||||
import { Plugin } from "@utils/types";
|
import { Plugin } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByPropsLazy } from "@webpack";
|
||||||
|
@ -66,19 +67,19 @@ function ReloadRequiredCard({ required }: { required: boolean; }) {
|
||||||
<Card className={cl("info-card", { "restart-card": required })}>
|
<Card className={cl("info-card", { "restart-card": required })}>
|
||||||
{required ? (
|
{required ? (
|
||||||
<>
|
<>
|
||||||
<Forms.FormTitle tag="h5">Restart required!</Forms.FormTitle>
|
<Forms.FormTitle tag="h5">{$t("vencord.pluginHeader.reloadHeader")}</Forms.FormTitle>
|
||||||
<Forms.FormText className={cl("dep-text")}>
|
<Forms.FormText className={cl("dep-text")}>
|
||||||
Restart now to apply new plugins and their settings
|
{$t("vencord.pluginHeader.reloadDescription")}
|
||||||
</Forms.FormText>
|
</Forms.FormText>
|
||||||
<Button onClick={() => location.reload()}>
|
<Button onClick={() => location.reload()}>
|
||||||
Restart
|
{$t("vencord.pluginHeader.restart")}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Forms.FormTitle tag="h5">Plugin Management</Forms.FormTitle>
|
<Forms.FormTitle tag="h5">{$t("vencord.pluginHeader.managementHeader")}</Forms.FormTitle>
|
||||||
<Forms.FormText>Press the cog wheel or info icon to get more info on a plugin</Forms.FormText>
|
<Forms.FormText>{$t("vencord.pluginHeader.iconInformation")}</Forms.FormText>
|
||||||
<Forms.FormText>Plugins with a cog wheel have settings you can modify!</Forms.FormText>
|
<Forms.FormText>{$t("vencord.pluginHeader.cogWheel")}</Forms.FormText>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -153,7 +154,7 @@ export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, on
|
||||||
return (
|
return (
|
||||||
<AddonCard
|
<AddonCard
|
||||||
name={plugin.name}
|
name={plugin.name}
|
||||||
description={plugin.description}
|
description={$t(`${lowercaseify(plugin.name)}.description`)}
|
||||||
isNew={isNew}
|
isNew={isNew}
|
||||||
enabled={isEnabled()}
|
enabled={isEnabled()}
|
||||||
setEnabled={toggleEnabled}
|
setEnabled={toggleEnabled}
|
||||||
|
@ -184,10 +185,10 @@ export default function PluginSettings() {
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
return () => void (changes.hasChanges && Alerts.show({
|
return () => void (changes.hasChanges && Alerts.show({
|
||||||
title: "Restart required",
|
title: $t("vencord.restartRequired"),
|
||||||
body: (
|
body: (
|
||||||
<>
|
<>
|
||||||
<p>The following plugins require a restart:</p>
|
<p>$t("vencord.pluginsNeedRestart")</p>
|
||||||
<div>{changes.map((s, i) => (
|
<div>{changes.map((s, i) => (
|
||||||
<>
|
<>
|
||||||
{i > 0 && ", "}
|
{i > 0 && ", "}
|
||||||
|
@ -196,8 +197,8 @@ export default function PluginSettings() {
|
||||||
))}</div>
|
))}</div>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
confirmText: "Restart now",
|
confirmText: $t("vencord.restartNow"),
|
||||||
cancelText: "Later!",
|
cancelText: $t("vencord.restartLater"),
|
||||||
onConfirm: () => location.reload()
|
onConfirm: () => location.reload()
|
||||||
}));
|
}));
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -303,7 +304,7 @@ export default function PluginSettings() {
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
plugins = requiredPlugins = <Text variant="text-md/normal">No plugins meet search criteria.</Text>;
|
plugins = requiredPlugins = <Text variant="text-md/normal">{$t("vencord.noSearchResults")}</Text>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -311,18 +312,18 @@ export default function PluginSettings() {
|
||||||
<ReloadRequiredCard required={changes.hasChanges} />
|
<ReloadRequiredCard required={changes.hasChanges} />
|
||||||
|
|
||||||
<Forms.FormTitle tag="h5" className={classes(Margins.top20, Margins.bottom8)}>
|
<Forms.FormTitle tag="h5" className={classes(Margins.top20, Margins.bottom8)}>
|
||||||
Filters
|
{$t("vencord.pluginFilters")}
|
||||||
</Forms.FormTitle>
|
</Forms.FormTitle>
|
||||||
|
|
||||||
<div className={cl("filter-controls")}>
|
<div className={cl("filter-controls")}>
|
||||||
<TextInput autoFocus value={searchValue.value} placeholder="Search for a plugin..." onChange={onSearch} className={Margins.bottom20} />
|
<TextInput autoFocus value={searchValue.value} placeholder={$t("vencord.search.placeholder")} onChange={onSearch} className={Margins.bottom20} />
|
||||||
<div className={InputStyles.inputWrapper}>
|
<div className={InputStyles.inputWrapper}>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={[
|
||||||
{ label: "Show All", value: SearchStatus.ALL, default: true },
|
{ label: $t("vencord.search.all"), value: SearchStatus.ALL, default: true },
|
||||||
{ label: "Show Enabled", value: SearchStatus.ENABLED },
|
{ label: $t("vencord.search.enabled"), value: SearchStatus.ENABLED },
|
||||||
{ label: "Show Disabled", value: SearchStatus.DISABLED },
|
{ label: $t("vencord.search.disabled"), value: SearchStatus.DISABLED },
|
||||||
{ label: "Show New", value: SearchStatus.NEW }
|
{ label: $t("vencord.search.new"), value: SearchStatus.NEW }
|
||||||
]}
|
]}
|
||||||
serialize={String}
|
serialize={String}
|
||||||
select={onStatusChange}
|
select={onStatusChange}
|
||||||
|
@ -332,7 +333,7 @@ export default function PluginSettings() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Forms.FormTitle className={Margins.top20}>Plugins</Forms.FormTitle>
|
<Forms.FormTitle className={Margins.top20}>{$t("vencord.plugins")}</Forms.FormTitle>
|
||||||
|
|
||||||
<div className={cl("grid")}>
|
<div className={cl("grid")}>
|
||||||
{plugins}
|
{plugins}
|
||||||
|
@ -341,7 +342,7 @@ export default function PluginSettings() {
|
||||||
<Forms.FormDivider className={Margins.top20} />
|
<Forms.FormDivider className={Margins.top20} />
|
||||||
|
|
||||||
<Forms.FormTitle tag="h5" className={classes(Margins.top20, Margins.bottom8)}>
|
<Forms.FormTitle tag="h5" className={classes(Margins.top20, Margins.bottom8)}>
|
||||||
Required Plugins
|
{$t("vencord.requiredPlugins")}
|
||||||
</Forms.FormTitle>
|
</Forms.FormTitle>
|
||||||
<div className={cl("grid")}>
|
<div className={cl("grid")}>
|
||||||
{requiredPlugins}
|
{requiredPlugins}
|
||||||
|
@ -353,7 +354,7 @@ export default function PluginSettings() {
|
||||||
function makeDependencyList(deps: string[]) {
|
function makeDependencyList(deps: string[]) {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Forms.FormText>This plugin is required by:</Forms.FormText>
|
<Forms.FormText>{$t("vencord.pluginRequiredBy")}</Forms.FormText>
|
||||||
{deps.map((dep: string) => <Forms.FormText className={cl("dep-text")}>{dep}</Forms.FormText>)}
|
{deps.map((dep: string) => <Forms.FormText className={cl("dep-text")}>{dep}</Forms.FormText>)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { Flex } from "@components/Flex";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { downloadSettingsBackup, uploadSettingsBackup } from "@utils/settingsSync";
|
import { downloadSettingsBackup, uploadSettingsBackup } from "@utils/settingsSync";
|
||||||
|
import { $t } from "@utils/translation";
|
||||||
import { Button, Card, Text } from "@webpack/common";
|
import { Button, Card, Text } from "@webpack/common";
|
||||||
|
|
||||||
import { SettingsTab, wrapTab } from "./shared";
|
import { SettingsTab, wrapTab } from "./shared";
|
||||||
|
@ -29,21 +30,19 @@ function BackupRestoreTab() {
|
||||||
<SettingsTab title="Backup & Restore">
|
<SettingsTab title="Backup & Restore">
|
||||||
<Card className={classes("vc-settings-card", "vc-backup-restore-card")}>
|
<Card className={classes("vc-settings-card", "vc-backup-restore-card")}>
|
||||||
<Flex flexDirection="column">
|
<Flex flexDirection="column">
|
||||||
<strong>Warning</strong>
|
<strong>{$t("vencord.warning")}</strong>
|
||||||
<span>Importing a settings file will overwrite your current settings.</span>
|
<span>{$t("vencord.backupAndRestore.importWarning")}</span>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Card>
|
</Card>
|
||||||
<Text variant="text-md/normal" className={Margins.bottom8}>
|
<Text variant="text-md/normal" className={Margins.bottom8}>
|
||||||
You can import and export your Vencord settings as a JSON file.
|
{$t("vencord.backupAndRestore.description")}
|
||||||
This allows you to easily transfer your settings to another device,
|
|
||||||
or recover your settings after reinstalling Vencord or Discord.
|
|
||||||
</Text>
|
</Text>
|
||||||
<Text variant="text-md/normal" className={Margins.bottom8}>
|
<Text variant="text-md/normal" className={Margins.bottom8}>
|
||||||
Settings Export contains:
|
{$t("vencord.backupAndRestore.exportContains")}
|
||||||
<ul>
|
<ul>
|
||||||
<li>— Custom QuickCSS</li>
|
<li>— {$t("vencord.backupAndRestore.customQuickcss")}</li>
|
||||||
<li>— Theme Links</li>
|
<li>— {$t("vencord.backupAndRestore.themeLinks")}</li>
|
||||||
<li>— Plugin Settings</li>
|
<li>— {$t("vencord.backupAndRestore.pluginSettings")}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Text>
|
</Text>
|
||||||
<Flex>
|
<Flex>
|
||||||
|
@ -51,13 +50,13 @@ function BackupRestoreTab() {
|
||||||
onClick={() => uploadSettingsBackup()}
|
onClick={() => uploadSettingsBackup()}
|
||||||
size={Button.Sizes.SMALL}
|
size={Button.Sizes.SMALL}
|
||||||
>
|
>
|
||||||
Import Settings
|
{$t("vencord.backupAndRestore.importSettings")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={downloadSettingsBackup}
|
onClick={downloadSettingsBackup}
|
||||||
size={Button.Sizes.SMALL}
|
size={Button.Sizes.SMALL}
|
||||||
>
|
>
|
||||||
Export Settings
|
{$t("vencord.backupAndRestore.exportSettings")}
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
</SettingsTab>
|
</SettingsTab>
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { Link } from "@components/Link";
|
||||||
import { authorizeCloud, cloudLogger, deauthorizeCloud, getCloudAuth, getCloudUrl } from "@utils/cloud";
|
import { authorizeCloud, cloudLogger, deauthorizeCloud, getCloudAuth, getCloudUrl } from "@utils/cloud";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { deleteCloudSettings, getCloudSettings, putCloudSettings } from "@utils/settingsSync";
|
import { deleteCloudSettings, getCloudSettings, putCloudSettings } from "@utils/settingsSync";
|
||||||
|
import { $t, Translate } from "@utils/translation";
|
||||||
import { Alerts, Button, Forms, Switch, Tooltip } from "@webpack/common";
|
import { Alerts, Button, Forms, Switch, Tooltip } from "@webpack/common";
|
||||||
|
|
||||||
import { SettingsTab, wrapTab } from "./shared";
|
import { SettingsTab, wrapTab } from "./shared";
|
||||||
|
@ -45,8 +46,8 @@ async function eraseAllData() {
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
cloudLogger.error(`Failed to erase data, API returned ${res.status}`);
|
cloudLogger.error(`Failed to erase data, API returned ${res.status}`);
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Integrations",
|
title: $t("vencord.cloudIntegrations"),
|
||||||
body: `Could not erase all data (API returned ${res.status}), please contact support.`,
|
body: $t("vencord.cloud.integrations.eraseError", { status: res.status }),
|
||||||
color: "var(--red-360)"
|
color: "var(--red-360)"
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
@ -56,8 +57,8 @@ async function eraseAllData() {
|
||||||
await deauthorizeCloud();
|
await deauthorizeCloud();
|
||||||
|
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Integrations",
|
title: $t("vencord.cloudIntegrations"),
|
||||||
body: "Successfully erased all data.",
|
body: $t("vencord.cloud.integrations.eraseSuccess"),
|
||||||
color: "var(--green-360)"
|
color: "var(--green-360)"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -69,8 +70,7 @@ function SettingsSyncSection() {
|
||||||
return (
|
return (
|
||||||
<Forms.FormSection title="Settings Sync" className={Margins.top16}>
|
<Forms.FormSection title="Settings Sync" className={Margins.top16}>
|
||||||
<Forms.FormText variant="text-md/normal" className={Margins.bottom20}>
|
<Forms.FormText variant="text-md/normal" className={Margins.bottom20}>
|
||||||
Synchronize your settings to the cloud. This allows easy synchronization across multiple devices with
|
{$t("vencord.cloud.settings.description")}
|
||||||
minimal effort.
|
|
||||||
</Forms.FormText>
|
</Forms.FormText>
|
||||||
<Switch
|
<Switch
|
||||||
key="cloud-sync"
|
key="cloud-sync"
|
||||||
|
@ -78,15 +78,15 @@ function SettingsSyncSection() {
|
||||||
value={cloud.settingsSync}
|
value={cloud.settingsSync}
|
||||||
onChange={v => { cloud.settingsSync = v; }}
|
onChange={v => { cloud.settingsSync = v; }}
|
||||||
>
|
>
|
||||||
Settings Sync
|
{$t("vencord.settingsSync")}
|
||||||
</Switch>
|
</Switch>
|
||||||
<div className="vc-cloud-settings-sync-grid">
|
<div className="vc-cloud-settings-sync-grid">
|
||||||
<Button
|
<Button
|
||||||
size={Button.Sizes.SMALL}
|
size={Button.Sizes.SMALL}
|
||||||
disabled={!sectionEnabled}
|
disabled={!sectionEnabled}
|
||||||
onClick={() => putCloudSettings(true)}
|
onClick={() => putCloudSettings(true)}
|
||||||
>Sync to Cloud</Button>
|
>{$t("vencord.cloud.settings.syncToCloud")}</Button>
|
||||||
<Tooltip text="This will overwrite your local settings with the ones on the cloud. Use wisely!">
|
<Tooltip text={$t("vencord.cloud.settings.overwriteWarning")}>
|
||||||
{({ onMouseLeave, onMouseEnter }) => (
|
{({ onMouseLeave, onMouseEnter }) => (
|
||||||
<Button
|
<Button
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
|
@ -95,7 +95,7 @@ function SettingsSyncSection() {
|
||||||
color={Button.Colors.RED}
|
color={Button.Colors.RED}
|
||||||
disabled={!sectionEnabled}
|
disabled={!sectionEnabled}
|
||||||
onClick={() => getCloudSettings(true, true)}
|
onClick={() => getCloudSettings(true, true)}
|
||||||
>Sync from Cloud</Button>
|
>{$t("vencord.cloud.settings.syncFromCloud")}</Button>
|
||||||
)}
|
)}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Button
|
<Button
|
||||||
|
@ -103,7 +103,7 @@ function SettingsSyncSection() {
|
||||||
color={Button.Colors.RED}
|
color={Button.Colors.RED}
|
||||||
disabled={!sectionEnabled}
|
disabled={!sectionEnabled}
|
||||||
onClick={() => deleteCloudSettings()}
|
onClick={() => deleteCloudSettings()}
|
||||||
>Delete Cloud Settings</Button>
|
>{$t("vencord.cloud.settings.deleteCloudSettings")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</Forms.FormSection>
|
</Forms.FormSection>
|
||||||
);
|
);
|
||||||
|
@ -116,22 +116,22 @@ function CloudTab() {
|
||||||
<SettingsTab title="Vencord Cloud">
|
<SettingsTab title="Vencord Cloud">
|
||||||
<Forms.FormSection title="Cloud Settings" className={Margins.top16}>
|
<Forms.FormSection title="Cloud Settings" className={Margins.top16}>
|
||||||
<Forms.FormText variant="text-md/normal" className={Margins.bottom20}>
|
<Forms.FormText variant="text-md/normal" className={Margins.bottom20}>
|
||||||
Vencord comes with a cloud integration that adds goodies like settings sync across devices.
|
<Translate i18nKey="vencord.cloud.integrations.description">
|
||||||
It <Link href="https://vencord.dev/cloud/privacy">respects your privacy</Link>, and
|
<Link href="https://vencord.dev/cloud/privacy" />
|
||||||
the <Link href="https://github.com/Vencord/Backend">source code</Link> is AGPL 3.0 licensed so you
|
<Link href="https://github.com/Vencord/Backend" />
|
||||||
can host it yourself.
|
</Translate>
|
||||||
</Forms.FormText>
|
</Forms.FormText>
|
||||||
<Switch
|
<Switch
|
||||||
key="backend"
|
key="backend"
|
||||||
value={settings.cloud.authenticated}
|
value={settings.cloud.authenticated}
|
||||||
onChange={v => { v && authorizeCloud(); if (!v) settings.cloud.authenticated = v; }}
|
onChange={v => { v && authorizeCloud(); if (!v) settings.cloud.authenticated = v; }}
|
||||||
note="This will request authorization if you have not yet set up cloud integrations."
|
note={$t("vencord.cloud.integrations.authorizationNote")}
|
||||||
>
|
>
|
||||||
Enable Cloud Integrations
|
{$t("vencord.cloud.integrations.enable")}
|
||||||
</Switch>
|
</Switch>
|
||||||
<Forms.FormTitle tag="h5">Backend URL</Forms.FormTitle>
|
<Forms.FormTitle tag="h5">{$t("vencord.cloud.integrations.backendUrl")}</Forms.FormTitle>
|
||||||
<Forms.FormText className={Margins.bottom8}>
|
<Forms.FormText className={Margins.bottom8}>
|
||||||
Which backend to use when using cloud integrations.
|
{$t("vencord.cloud.integrations.backendNote")}
|
||||||
</Forms.FormText>
|
</Forms.FormText>
|
||||||
<CheckedTextInput
|
<CheckedTextInput
|
||||||
key="backendUrl"
|
key="backendUrl"
|
||||||
|
@ -145,14 +145,14 @@ function CloudTab() {
|
||||||
color={Button.Colors.RED}
|
color={Button.Colors.RED}
|
||||||
disabled={!settings.cloud.authenticated}
|
disabled={!settings.cloud.authenticated}
|
||||||
onClick={() => Alerts.show({
|
onClick={() => Alerts.show({
|
||||||
title: "Are you sure?",
|
title: $t("vencord.areYouSure"),
|
||||||
body: "Once your data is erased, we cannot recover it. There's no going back!",
|
body: $t("vencord.cloud.integrations.eraseWarning"),
|
||||||
onConfirm: eraseAllData,
|
onConfirm: eraseAllData,
|
||||||
confirmText: "Erase it!",
|
confirmText: $t("vencord.cloud.integrations.eraseIt"),
|
||||||
confirmColor: "vc-cloud-erase-data-danger-btn",
|
confirmColor: "vc-cloud-erase-data-danger-btn",
|
||||||
cancelText: "Nevermind"
|
cancelText: $t("vencord.nevermind")
|
||||||
})}
|
})}
|
||||||
>Erase All Data</Button>
|
>{$t("vencord.cloud.integrations.eraseAllData")}</Button>
|
||||||
<Forms.FormDivider className={Margins.top16} />
|
<Forms.FormDivider className={Margins.top16} />
|
||||||
</Forms.FormSection >
|
</Forms.FormSection >
|
||||||
<SettingsSyncSection />
|
<SettingsSyncSection />
|
||||||
|
|
|
@ -29,6 +29,7 @@ import { classes } from "@utils/misc";
|
||||||
import { openModal } from "@utils/modal";
|
import { openModal } from "@utils/modal";
|
||||||
import { showItemInFolder } from "@utils/native";
|
import { showItemInFolder } from "@utils/native";
|
||||||
import { useAwaiter } from "@utils/react";
|
import { useAwaiter } from "@utils/react";
|
||||||
|
import { $t } from "@utils/translation";
|
||||||
import { findByPropsLazy, findLazy } from "@webpack";
|
import { findByPropsLazy, findLazy } from "@webpack";
|
||||||
import { Button, Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common";
|
import { Button, Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common";
|
||||||
import type { ComponentType, Ref, SyntheticEvent } from "react";
|
import type { ComponentType, Ref, SyntheticEvent } from "react";
|
||||||
|
@ -202,17 +203,17 @@ function ThemesTab() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card className="vc-settings-card">
|
<Card className="vc-settings-card">
|
||||||
<Forms.FormTitle tag="h5">Find Themes:</Forms.FormTitle>
|
<Forms.FormTitle tag="h5">{$t("vencord.themes.findThemes")}</Forms.FormTitle>
|
||||||
<div style={{ marginBottom: ".5em", display: "flex", flexDirection: "column" }}>
|
<div style={{ marginBottom: ".5em", display: "flex", flexDirection: "column" }}>
|
||||||
<Link style={{ marginRight: ".5em" }} href="https://betterdiscord.app/themes">
|
<Link style={{ marginRight: ".5em" }} href="https://betterdiscord.app/themes">
|
||||||
BetterDiscord Themes
|
{$t("vencord.themes.betterDiscord")}
|
||||||
</Link>
|
</Link>
|
||||||
<Link href="https://github.com/search?q=discord+theme">GitHub</Link>
|
<Link href="https://github.com/search?q=discord+theme">GitHub</Link>
|
||||||
</div>
|
</div>
|
||||||
<Forms.FormText>If using the BD site, click on "Download" and place the downloaded .theme.css file into your themes folder.</Forms.FormText>
|
<Forms.FormText>{$t("vencord.themes.betterDiscordNote")}</Forms.FormText>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Forms.FormSection title="Local Themes">
|
<Forms.FormSection title={$t("vencord.themes.local")}>
|
||||||
<Card className="vc-settings-quick-actions-card">
|
<Card className="vc-settings-quick-actions-card">
|
||||||
<>
|
<>
|
||||||
{IS_WEB ?
|
{IS_WEB ?
|
||||||
|
@ -221,7 +222,7 @@ function ThemesTab() {
|
||||||
size={Button.Sizes.SMALL}
|
size={Button.Sizes.SMALL}
|
||||||
disabled={themeDirPending}
|
disabled={themeDirPending}
|
||||||
>
|
>
|
||||||
Upload Theme
|
{$t("vencord.themes.upload")}
|
||||||
<FileInput
|
<FileInput
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
onChange={onFileUpload}
|
onChange={onFileUpload}
|
||||||
|
@ -235,20 +236,20 @@ function ThemesTab() {
|
||||||
size={Button.Sizes.SMALL}
|
size={Button.Sizes.SMALL}
|
||||||
disabled={themeDirPending}
|
disabled={themeDirPending}
|
||||||
>
|
>
|
||||||
Open Themes Folder
|
{$t("vencord.themes.openFolder")}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
onClick={refreshLocalThemes}
|
onClick={refreshLocalThemes}
|
||||||
size={Button.Sizes.SMALL}
|
size={Button.Sizes.SMALL}
|
||||||
>
|
>
|
||||||
Load missing Themes
|
{$t("vencord.themes.loadMissing")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => VencordNative.quickCss.openEditor()}
|
onClick={() => VencordNative.quickCss.openEditor()}
|
||||||
size={Button.Sizes.SMALL}
|
size={Button.Sizes.SMALL}
|
||||||
>
|
>
|
||||||
Edit QuickCSS
|
{$t("vencord.themes.editQuickCss")}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{Vencord.Settings.plugins.ClientTheme.enabled && (
|
{Vencord.Settings.plugins.ClientTheme.enabled && (
|
||||||
|
@ -262,7 +263,7 @@ function ThemesTab() {
|
||||||
))}
|
))}
|
||||||
size={Button.Sizes.SMALL}
|
size={Button.Sizes.SMALL}
|
||||||
>
|
>
|
||||||
Edit ClientTheme
|
{$t("clientTheme.edit")}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -303,12 +304,12 @@ function ThemesTab() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card className="vc-settings-card vc-text-selectable">
|
<Card className="vc-settings-card vc-text-selectable">
|
||||||
<Forms.FormTitle tag="h5">Paste links to css files here</Forms.FormTitle>
|
<Forms.FormTitle tag="h5">{$t("vencord.themes.pasteLinks")}</Forms.FormTitle>
|
||||||
<Forms.FormText>One link per line</Forms.FormText>
|
<Forms.FormText>{$t("vencord.themes.oneLinkPerLine")}</Forms.FormText>
|
||||||
<Forms.FormText>Make sure to use direct links to files (raw or github.io)!</Forms.FormText>
|
<Forms.FormText>{$t("vencord.themes.useDirect")}</Forms.FormText>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Forms.FormSection title="Online Themes" tag="h5">
|
<Forms.FormSection title={$t("vencord.themes.online")} tag="h5">
|
||||||
<TextArea
|
<TextArea
|
||||||
value={themeText}
|
value={themeText}
|
||||||
onChange={setThemeText}
|
onChange={setThemeText}
|
||||||
|
@ -337,13 +338,13 @@ function ThemesTab() {
|
||||||
className="vc-settings-tab-bar-item"
|
className="vc-settings-tab-bar-item"
|
||||||
id={ThemeTab.LOCAL}
|
id={ThemeTab.LOCAL}
|
||||||
>
|
>
|
||||||
Local Themes
|
{$t("vencord.themes.local")}
|
||||||
</TabBar.Item>
|
</TabBar.Item>
|
||||||
<TabBar.Item
|
<TabBar.Item
|
||||||
className="vc-settings-tab-bar-item"
|
className="vc-settings-tab-bar-item"
|
||||||
id={ThemeTab.ONLINE}
|
id={ThemeTab.ONLINE}
|
||||||
>
|
>
|
||||||
Online Themes
|
{$t("vencord.themes.online")}
|
||||||
</TabBar.Item>
|
</TabBar.Item>
|
||||||
</TabBar>
|
</TabBar>
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ export const wordsToPascal = (words: string[]) =>
|
||||||
export const wordsToTitle = (words: string[]) =>
|
export const wordsToTitle = (words: string[]) =>
|
||||||
words.map(w => w[0].toUpperCase() + w.slice(1)).join(" ");
|
words.map(w => w[0].toUpperCase() + w.slice(1)).join(" ");
|
||||||
|
|
||||||
|
export const lowercaseify = (text: string) => text[0].toLowerCase() + text.slice(1);
|
||||||
|
|
||||||
const units = ["years", "months", "weeks", "days", "hours", "minutes", "seconds"] as const;
|
const units = ["years", "months", "weeks", "days", "hours", "minutes", "seconds"] as const;
|
||||||
type Units = typeof units[number];
|
type Units = typeof units[number];
|
||||||
|
|
||||||
|
|
4
translations/en/clientTheme.json
Normal file
4
translations/en/clientTheme.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"description": "Recreation of the old client theme experiment. Add a color to your Discord client theme",
|
||||||
|
"edit": "Edit ClientTheme"
|
||||||
|
}
|
3
translations/en/translation.json
Normal file
3
translations/en/translation.json
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"description": "Assists with translating Vencord"
|
||||||
|
}
|
|
@ -1,58 +1,130 @@
|
||||||
{
|
{
|
||||||
"ohNo": "Oh no!",
|
"areYouSure": "Are you sure?",
|
||||||
"errorBoundaryDescription": "An error occurred while rendering this Component. More info can be found below and in your console.",
|
"backupAndRestore": {
|
||||||
"failureUpdate": "Uh Oh! Failed to render this Page. However, there is an update available that might fix it. Would you like to update and restart now?",
|
"customQuickcss": "Custom QuickCSS",
|
||||||
"pluginRestart": "Restart to apply changes!",
|
"description": "You can import and export your Vencord settings as a JSON file. This allows you to easily transfer your settings to another device, or recover your settings after reinstalling Vencord or Discord.",
|
||||||
"requiredPlugin": "This plugin is required for Vencord to function.",
|
"exportContains": "Settings Export contains:",
|
||||||
"new": "NEW",
|
"exportSettings": "Export Settings",
|
||||||
"pluginContributed": {
|
"importSettings": "Import Settings",
|
||||||
"one": "This person has <0>contributed</0> to one plugin!",
|
"importWarning": "Importing a settings file will overwrite your current settings.",
|
||||||
"other": "This person has <0>contributed</0> to {count} plugins!",
|
"pluginSettings": "Plugin Settings",
|
||||||
"zero": "This person has not made any plugins. They likely <0>contributed</0> to Vencord in other ways!"
|
"themeLinks": "Theme Links"
|
||||||
|
},
|
||||||
|
"clipboardNotSupported": "Your browser does not support copying to clipboard",
|
||||||
|
"cloud": {
|
||||||
|
"integrations": {
|
||||||
|
"authorizationNote": "This will request authorization if you have not yet set up cloud integrations.",
|
||||||
|
"backendNote": "Which backend to use when using cloud integrations.",
|
||||||
|
"backendUrl": "Backend URL",
|
||||||
|
"description": "Vencord comes with a cloud integration that adds goodies like settings sync across devices. It <0>respects your privacy</0>, and the <1>source code</1> is AGPL 3.0 licensed so you can host it yourself.",
|
||||||
|
"enable": "Enable Cloud Integrations",
|
||||||
|
"enabled": "Cloud integrations enabled!",
|
||||||
|
"eraseAllData": "Erase All Data",
|
||||||
|
"eraseError": "Could not erase all data (API returned {status}), please contact support.",
|
||||||
|
"eraseIt": "Erase it!",
|
||||||
|
"eraseSuccess": "Successfully erased all data.",
|
||||||
|
"eraseWarning": "Once your data is erased, we cannot recover it. There's no going back!",
|
||||||
|
"reauthenticate": "We've noticed you have cloud integrations enabled in another client! Due to limitations, you will need to re-authenticate to continue using them. Click here to go to the settings page to do so!",
|
||||||
|
"setupFailure": {
|
||||||
|
"generic": "Setup failed ({error}).",
|
||||||
|
"missingSecret": "Setup failed (no secret returned?).",
|
||||||
|
"oauth": "Setup failed (couldn't retrieve OAuth configuration)."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"update": {
|
"settings": {
|
||||||
"available": "A Vencord update is available!",
|
"deleteCloudSettings": "Delete Cloud Settings",
|
||||||
"clickToRestart": "Click here to restart",
|
"deleteError": {
|
||||||
"clickToView": "Click here to view the update",
|
"api": "Could not delete settings (API returned {status}).",
|
||||||
"updated": "Vencord has been updated!"
|
"generic": "Could not delete settings ({error})."
|
||||||
},
|
},
|
||||||
"cloudIntegrations": "Cloud Integrations",
|
"deleted": "Settings deleted from cloud!",
|
||||||
"cloudSettings": "Cloud Settings",
|
"description": "Synchronize your settings to the cloud. This allows easy synchronization across multiple devices with minimal effort.",
|
||||||
"cloud": {
|
"localNewer": "Your local settings are newer than the cloud ones.",
|
||||||
"integrations": {
|
"nothingOnline": "There are no settings in the cloud.",
|
||||||
"enabled": "Cloud integrations enabled!",
|
"overwriteWarning": "This will overwrite your local settings with the ones on the cloud. Use wisely!",
|
||||||
"reauthenticate": "We've noticed you have cloud integrations enabled in another client! Due to limitations, you will need to re-authenticate to continue using them. Click here to go to the settings page to do so!",
|
"syncErrorDown": {
|
||||||
"setupFailure": {
|
"api": "Could not synchronize settings from the cloud (API returned {status}).",
|
||||||
"generic": "Setup failed ({error}).",
|
"generic": "Could not synchronize settings from the cloud ({error})."
|
||||||
"missingSecret": "Setup failed (no secret returned?).",
|
},
|
||||||
"oauth": "Setup failed (couldn't retrieve OAuth configuration)."
|
"syncErrorUp": {
|
||||||
}
|
"api": "Could not synchronize settings to the cloud (API returned {status}).",
|
||||||
},
|
"generic": "Could not synchronize settings to the cloud ({error})."
|
||||||
"settings": {
|
},
|
||||||
"deleteError": {
|
"syncFromCloud": "Sync from Cloud",
|
||||||
"api": "Could not delete settings (API returned {status}).",
|
"syncSuccess": "Synchronized settings to the cloud!",
|
||||||
"generic": "Could not delete settings ({error})."
|
"syncToCloud": "Sync to Cloud",
|
||||||
},
|
"upToDate": "Your settings are up to date.",
|
||||||
"deleted": "Settings deleted from cloud!",
|
"updated": "Your settings have been updated! Click here to restart to fully apply changes!"
|
||||||
"localNewer": "Your local settings are newer than the cloud ones.",
|
}
|
||||||
"nothingOnline": "There are no settings in the cloud.",
|
},
|
||||||
"syncErrorDown": {
|
"cloudIntegrations": "Cloud Integrations",
|
||||||
"api": "Could not synchronize settings from the cloud (API returned {status}).",
|
"cloudSettings": "Cloud Settings",
|
||||||
"generic": "Could not synchronize settings from the cloud ({error})."
|
"copiedToClipboard": "Copied to clipboard!",
|
||||||
},
|
"errorBoundaryDescription": "An error occurred while rendering this Component. More info can be found below and in your console.",
|
||||||
"syncErrorUp": {
|
"failedToImport": "Failed to import settings: {error}",
|
||||||
"api": "Could not synchronize settings to the cloud (API returned {status}).",
|
"failureUpdate": "Uh Oh! Failed to render this Page. However, there is an update available that might fix it. Would you like to update and restart now?",
|
||||||
"generic": "Could not synchronize settings to the cloud ({error})."
|
"gitCopyNewer": "Your local copy has more recent commits. Please stash or reset them.",
|
||||||
},
|
"importedSettings": "Settings successfully imported. Restart to apply changes!",
|
||||||
"syncSuccess": "Synchronized settings to the cloud!",
|
"nevermind": "Nevermind",
|
||||||
"upToDate": "Your settings are up to date.",
|
"new": "NEW",
|
||||||
"updated": "Your settings have been updated! Click here to restart to fully apply changes!"
|
"noSearchResults": "No plugins meet search criteria.",
|
||||||
}
|
"noSettings": "There are no settings for this plugin.",
|
||||||
},
|
"ohNo": "Oh no!",
|
||||||
"copiedToClipboard": "Copied to clipboard!",
|
"pluginContributed": {
|
||||||
"clipboardNotSupported": "Your browser does not support copying to clipboard",
|
"one": "This person has <0>contributed</0> to one plugin!",
|
||||||
"failedToImport": "Failed to import settings: {error}",
|
"other": "This person has <0>contributed</0> to {count} plugins!",
|
||||||
"importedSettings": "Settings successfully imported. Restart to apply changes!",
|
"zero": "This person has not made any plugins. They likely <0>contributed</0> to Vencord in other ways!"
|
||||||
"updaterRepeatFailed": "That also failed :( Try updating or re-installing with the installer!",
|
},
|
||||||
"gitCopyNewer": "Your local copy has more recent commits. Please stash or reset them."
|
"pluginFilters": "Filters",
|
||||||
|
"pluginHeader": {
|
||||||
|
"cogWheel": "Plugins with a cog wheel have settings you can modify!",
|
||||||
|
"iconInformation": "Press the cog wheel or info icon to get more info on a plugin.",
|
||||||
|
"managementHeader": "Plugin Management",
|
||||||
|
"reloadDescription": "Restart now to apply new plugins and their settings",
|
||||||
|
"reloadHeader": "Restart required!",
|
||||||
|
"restart": "Restart"
|
||||||
|
},
|
||||||
|
"pluginRequiredBy": "This plugin is required by:",
|
||||||
|
"pluginRestart": "Restart to apply changes!",
|
||||||
|
"plugins": "Plugins",
|
||||||
|
"pluginsNeedRestart": "The following plugins require a restart:",
|
||||||
|
"requiredPlugin": "This plugin is required for Vencord to function.",
|
||||||
|
"requiredPlugins": "Required Plugins",
|
||||||
|
"restartLater": "Later!",
|
||||||
|
"restartNow": "Restart now",
|
||||||
|
"restartRequired": "Restart required",
|
||||||
|
"saveAndClose": "Save & Close",
|
||||||
|
"search": {
|
||||||
|
"all": "Show All",
|
||||||
|
"disabled": "Show Disabled",
|
||||||
|
"enabled": "Show Enabled",
|
||||||
|
"new": "Show New",
|
||||||
|
"placeholder": "Search for a plugin..."
|
||||||
|
},
|
||||||
|
"settings": "Settings",
|
||||||
|
"settingsErrors": "You must fix all errors before saving",
|
||||||
|
"settingsSaveError": "Error while saving: {saveError}",
|
||||||
|
"settingsSync": "Settings Sync",
|
||||||
|
"themes": {
|
||||||
|
"betterDiscord": "BetterDiscord Themes",
|
||||||
|
"betterDiscordNote": "If using the BD site, click on \"Download\" and place the downloaded .theme.css file into your themes folder.",
|
||||||
|
"editQuickCss": "Edit QuickCSS",
|
||||||
|
"findThemes": "Find Themes:",
|
||||||
|
"loadMissing": "Load missing Themes",
|
||||||
|
"local": "Local Themes",
|
||||||
|
"oneLinkPerLine": "One link per line.",
|
||||||
|
"online": "Online Themes",
|
||||||
|
"openFolder": "Open Themes Folder",
|
||||||
|
"pasteLinks": "Paste links to css files here",
|
||||||
|
"upload": "Upload Theme",
|
||||||
|
"useDirect": "Make sure to use direct links to files (raw or github.io)!"
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"available": "A Vencord update is available!",
|
||||||
|
"clickToRestart": "Click here to restart",
|
||||||
|
"clickToView": "Click here to view the update",
|
||||||
|
"updated": "Vencord has been updated!"
|
||||||
|
},
|
||||||
|
"updaterRepeatFailed": "That also failed :( Try updating or re-installing with the installer!",
|
||||||
|
"warning": "Warning"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue