Skip to content

Commit

Permalink
i18n: Create simple component to provide translations with placeholder
Browse files Browse the repository at this point in the history
  • Loading branch information
danielhjacobs committed Nov 15, 2024
1 parent be03ce3 commit a6c5493
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 32 deletions.
24 changes: 14 additions & 10 deletions src/app/downloads/nightlies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
githubReleasesUrl,
webLinks,
} from "@/app/downloads/config";
import { useTranslation } from "@/app/translate";
import { useTranslation, Trans } from "@/app/translate";

function DownloadLink({
link,
Expand Down Expand Up @@ -130,15 +130,19 @@ export function NightlyList({
<Stack>
<Title id="nightly-releases">{t("downloads.nightly-releases")}</Title>
<Text>
{t("downloads.nightly-releases-description")}{" "}
<Link
href={githubReleasesUrl}
className={classes.moreNightlies}
target="_blank"
>
{t("footer.github")}
</Link>
{t("common.line-ender")}
<Trans
i18nKey="downloads.nightly-releases-description"
components={[
<Link
key="link"
href={githubReleasesUrl}
className={classes.moreNightlies}
target="_blank"
>
{t("footer.github")}
</Link>,
]}
/>
</Text>
<Table
horizontalSpacing="md"
Expand Down
38 changes: 24 additions & 14 deletions src/app/downloads/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
maxNightlies,
} from "@/app/downloads/config";
import { getLatestReleases } from "@/app/downloads/github";
import { useTranslation } from "@/app/translate";
import { useTranslation, Trans } from "@/app/translate";

function WebDownload({ latest }: { latest: GithubRelease | null }) {
const { t } = useTranslation();
Expand All @@ -33,24 +33,34 @@ function WebDownload({ latest }: { latest: GithubRelease | null }) {
{'<script src="https://unpkg.com/@ruffle-rs/ruffle"></script>'}
</Code>
<Text>
{t("downloads.self-host-description-start")}{" "}
<Link
href={latest?.downloads?.web || githubReleasesUrl}
target="_blank"
>
{t("downloads.self-host-description-link")}
</Link>{" "}
{t("downloads.self-host-description-end")}
<Trans
i18nKey="downloads.self-host-description"
components={[
<Link
key="link"
href={latest?.downloads?.web || githubReleasesUrl}
target="_blank"
>
{t("downloads.self-host-description-link")}
</Link>,
]}
/>
</Text>
<Code block className={classes.cdn}>
{'<script src="path/to/ruffle.js"></script>'}
</Code>
<Text>
{t("downloads.advanced-usage-description-start")}{" "}
<Link href="https://github.com/ruffle-rs/ruffle/wiki/Using-Ruffle#javascript-api">
{t("downloads.advanced-usage-description-link")}
</Link>{" "}
{t("downloads.advanced-usage-description-end")}
<Trans
i18nKey="downloads.advanced-usage-description"
components={[
<Link
key="link"
href="https://github.com/ruffle-rs/ruffle/wiki/Using-Ruffle#javascript-api"
>
{t("downloads.advanced-usage-description-link")}
</Link>,
]}
/>
</Text>
</Stack>
);
Expand Down
29 changes: 29 additions & 0 deletions src/app/translate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,35 @@ export function useTranslation() {
return { t };
}

interface TransProps {
i18nKey: string; // Translation key
components?: React.ReactNode[]; // Components to inject into placeholders
}

export const Trans: React.FC<TransProps> = ({ i18nKey, components = [] }) => {
const { t } = useTranslation();
const translation = t(i18nKey);

const renderWithPlaceholders = (template: string) => {
const parts = template.split(/({{.*?}})/g); // Split on placeholders like {{key}}
return parts.map((part) => {
const match = part.match(/{{(.*?)}}/); // Match placeholders
if (match) {
const placeholderKey = match[1];
const component = components.find(
(comp) => React.isValidElement(comp) && comp.key === placeholderKey,
);
if (component) {
return component;
}
}
return part; // Return plain text if no placeholder
});
};

return <>{renderWithPlaceholders(translation)}</>;
};

export const LanguageSelector: React.FC<LanguageSelectorProps> = ({
className,
}) => {
Expand Down
11 changes: 3 additions & 8 deletions src/i18n/translations.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,15 @@
"browser-extension": "Browser Extension",
"browser-extension-description": "If you visit websites that have Flash content but aren't using Ruffle, or you want to ensure you're using the latest and greatest version of Ruffle on every website, then our browser extension is the perfect thing for you!",
"nightly-releases": "Nightly Releases",
"nightly-releases-description": "If none of the above are suitable for you, you can manually download the latest Nightly release. These are automatically built every day (approximately midnight UTC), unless there are no changes on that day. Older nightly releases are available on",
"nightly-releases-description": "If none of the above are suitable for you, you can manually download the latest Nightly release. These are automatically built every day (approximately midnight UTC), unless there are no changes on that day. Older nightly releases are available on {{link}}.",
"web-package": "Web Package",
"web-package-description": "You can install Ruffle onto a website using one single line of code by using a CDN, no extra work required! It'll always stay up to date with the latest available version of Ruffle.",
"self-host-description-start": "If you'd like to host it yourself, you can grab",
"self-host-description": "If you'd like to host it yourself, you can grab {{link}} and upload it to your server. Then, include it on your page like so:",
"self-host-description-link": "the latest self-hosted package",
"self-host-description-end": "and upload it to your server. Then, include it on your page like so:",
"advanced-usage-description-start": "For advanced usage, consult",
"advanced-usage-description": "For advanced usage, consult {{link}} for our JavaScript API and installation options.",
"advanced-usage-description-link": "our documentation",
"advanced-usage-description-end": "for our JavaScript API and installation options.",
"chrome-extension-alt": "Available in the Chrome Web Store",
"firefox-extension-alt": "Get the Add-On for Firefox",
"edge-extension-alt": "Get it from Microsoft for Edge"
},
"common": {
"line-ender": "."
}
}

0 comments on commit a6c5493

Please sign in to comment.