diff --git a/.vscode/i18n-ally-custom-framework.yml b/.vscode/i18n-ally-custom-framework.yml index 5c68edc42..4cdc6aae0 100644 --- a/.vscode/i18n-ally-custom-framework.yml +++ b/.vscode/i18n-ally-custom-framework.yml @@ -6,5 +6,10 @@ languageIds: usageMatchRegex: - "[^\\w\\d]\\$t\\(['\"`]({key})['\"`]" + - "" monopoly: true diff --git a/src/components/PluginSettings/ContributorModal.tsx b/src/components/PluginSettings/ContributorModal.tsx index 99a8da168..022160c2e 100644 --- a/src/components/PluginSettings/ContributorModal.tsx +++ b/src/components/PluginSettings/ContributorModal.tsx @@ -12,8 +12,8 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Link } from "@components/Link"; import { DevsById } from "@utils/constants"; import { fetchUserProfile, getTheme, Theme } from "@utils/discord"; -import { pluralise } from "@utils/misc"; import { ModalContent, ModalRoot, openModal } from "@utils/modal"; +import { Translate } from "@utils/translation"; import { Forms, MaskedLink, showToast, Tooltip, useEffect, useMemo, UserProfileStore, useStateFromStores } from "@webpack/common"; import { User } from "discord-types/general"; @@ -108,15 +108,9 @@ function ContributorModal({ user }: { user: User; }) { - {plugins.length ? ( - - This person has {ContributedHyperLink} to {pluralise(plugins.length, "plugin")}! - - ) : ( - - This person has not made any plugins. They likely {ContributedHyperLink} to Vencord in other ways! - - )} + + + {!!plugins.length && (
diff --git a/src/utils/translation.ts b/src/utils/translation.tsx similarity index 74% rename from src/utils/translation.ts rename to src/utils/translation.tsx index 807ac1d8d..a1cba453d 100644 --- a/src/utils/translation.ts +++ b/src/utils/translation.tsx @@ -5,7 +5,7 @@ */ import { negotiateLanguages } from "@fluent/langneg"; -import { FluxDispatcher, i18n } from "@webpack/common"; +import { FluxDispatcher, i18n, React } from "@webpack/common"; import translations from "~translations"; @@ -124,3 +124,37 @@ export function $t(key: string, variables?: Record): string { return format(translation as string, variables); } + +interface TranslateProps { + /** The key to translate. */ + i18nKey: string; + /** The variables to interpolate into the resultant string. If dealing with plurals, `count` must be set. */ + variables?: Record; + /** The component(s) to interpolate into the resultant string. */ + children: JSX.Element | JSX.Element[]; +} + +/** + * A translation component. Follows the same rules as {@link $t}, but lets you add components to strings. + * @param param0 Component props. + */ +export function Translate({ i18nKey, variables, children: trueChildren }: TranslateProps): JSX.Element { + const children = [trueChildren].flat(); + + const translation = $t(i18nKey, variables); + + const parts = translation.split(/(<\d+>.*?<\/\d+>)/g); + + const finalChildren = parts.map((part, index) => { + const match = part.match(/<(\d+)>(.*?)<\/\d+>/); + + if (match) { + const childIndex = parseInt(match[1], 10); + return React.cloneElement(children[childIndex], { key: index }, match[2]); + } + + return part; + }); + + return <>{finalChildren}; +} diff --git a/translations/en/vencord.json b/translations/en/vencord.json index 3c24ed09b..ca08ff5ed 100644 --- a/translations/en/vencord.json +++ b/translations/en/vencord.json @@ -5,6 +5,15 @@ "error": "An error occurred while rendering this Component. More info can be found below and in your console.", "ohNo": "Oh no!" }, + "pluginSettings": { + "contributorModal": { + "contributed": { + "zero": "This person has not made any plugins. They likely <0>contributed to Vencord in other ways!", + "one": "This person has <0>contributed to one plugin!", + "other": "This person has <0>contributed to {count} plugins!" + } + } + }, "vencordSettings": { "addonCard": { "new": "NEW"