Skip to content

i18n: Translate the website (excluding blogs) #358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
23 changes: 16 additions & 7 deletions src/app/compatibility/avm.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import classes from "./avm.module.css";
import {
Button,
Expand All @@ -9,6 +11,7 @@ import {
Title,
} from "@mantine/core";
import Link from "next/link";
import { useTranslation } from "@/app/translate";

interface AvmProgressProps {
done: number;
Expand All @@ -21,25 +24,26 @@ interface AvmProgressPropsFull extends AvmProgressProps {
}

function AvmProgress(props: AvmProgressPropsFull) {
const { t } = useTranslation();
return (
<Group align="center" justify="spread-between" mt={props.mt}>
<Text size="sm" className={classes.progressName}>
{props.name}: {props.done}%
{t(props.name)}: {props.done}%
</Text>
<ProgressRoot size="xl" radius={10} className={classes.progress}>
<ProgressSection
striped
value={props.done}
color="var(--mantine-color-green-9)"
title={`${props.done}% done`}
title={`${props.done}% ${t("compatibility.done")}`}
></ProgressSection>
{props.stubbed && (
<ProgressSection
striped
value={props.stubbed}
color="ruffle-orange"
className={classes.stub}
title={`${props.stubbed}% partially done`}
title={`${props.stubbed}% ${t("compatibility.partial")}`}
></ProgressSection>
)}
</ProgressRoot>
Expand All @@ -57,25 +61,30 @@ interface AvmBlockProps {
}

export function AvmBlock(props: AvmBlockProps) {
const { t } = useTranslation();
return (
<Stack className={classes.avm}>
<Group justify="space-between">
<Title order={2}>{props.name}</Title>
<Title order={2}>{t(props.name)}</Title>
<Button
component={Link}
href={props.info_link}
target={props.info_link_target}
size="compact-md"
color="var(--ruffle-blue-7)"
>
More Info
{t("compatibility.more")}
</Button>
</Group>

{props.children}

<AvmProgress name="Language" mt="auto" {...props.language} />
<AvmProgress name="API" {...props.api} />
<AvmProgress
name="compatibility.language"
mt="auto"
{...props.language}
/>
<AvmProgress name="compatibility.api" {...props.api} />
</Stack>
);
}
17 changes: 12 additions & 5 deletions src/app/compatibility/avm2/class_box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import classes from "./avm2.module.css";
import React from "react";
import {
ClassStatus,
ProgressIcon,
displayedPercentage,
} from "@/app/compatibility/avm2/report_utils";
import { ProgressIcon } from "@/app/compatibility/avm2/icons";
import { useTranslation } from "@/app/translate";

export function ClassBox(props: ClassStatus) {
const { t } = useTranslation();
const [opened, { toggle }] = useDisclosure(false);
const pctDone = displayedPercentage(
props.summary.impl_points - props.summary.stub_penalty,
Expand All @@ -33,21 +35,23 @@ export function ClassBox(props: ClassStatus) {
);
return (
<Card bg="var(--ruffle-blue-9)" className={classes.class}>
<Title order={4}>{props.name || "(Package level)"}</Title>
<Title order={4}>
{props.name || t("compatibility.avm2.package-level")}
</Title>
<ProgressRoot size="xl" radius={10} className={classes.progress}>
<ProgressSection
striped
value={pctDone}
color="var(--mantine-color-green-9)"
title={`${pctDone}% done`}
title={`${pctDone}% ${t("compatibility.done")}`}
></ProgressSection>
{pctStub > 0 && (
<ProgressSection
striped
value={pctStub}
color="ruffle-orange"
className={classes.progressStub}
title={`${pctStub}% partially done`}
title={`${pctStub}% ${t("compatibility.partial")}`}
></ProgressSection>
)}
</ProgressRoot>
Expand All @@ -58,7 +62,10 @@ export function ClassBox(props: ClassStatus) {
className={classes.showMemberButton}
onClick={toggle}
>
{opened ? "Hide" : "Show"} Missing Members
{opened
? t("compatibility.avm2.hide")
: t("compatibility.avm2.show")}{" "}
{t("compatibility.avm2.missing-members")}
</Button>
<List hidden={!opened}>
{props.items.map((item, i) => (
Expand Down
65 changes: 65 additions & 0 deletions src/app/compatibility/avm2/icons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"use client";

import { rem, ThemeIcon } from "@mantine/core";
import { IconCheck, IconProgress, IconX } from "@tabler/icons-react";
import { useTranslation } from "@/app/translate";

export function IconDone() {
const { t } = useTranslation();
return (
<ThemeIcon
size={20}
radius="xl"
color="var(--mantine-color-green-9)"
title={t("compatibility.avm2.done")}
>
<IconCheck
color="white"
style={{ width: rem(12), height: rem(12) }}
stroke={4}
/>
</ThemeIcon>
);
}

export function IconStub() {
const { t } = useTranslation();
return (
<ThemeIcon size={20} radius="xl" title={t("compatibility.avm2.partial")}>
<IconProgress
color="#3c1518"
style={{ width: rem(12), height: rem(12) }}
stroke={4}
/>
</ThemeIcon>
);
}

export function IconMissing() {
const { t } = useTranslation();
return (
<ThemeIcon
size={20}
radius="xl"
color="#3c1518"
title={t("compatibility.avm2.missing")}
>
<IconX
color="white"
style={{ width: rem(12), height: rem(12) }}
stroke={4}
/>
</ThemeIcon>
);
}

export function ProgressIcon(type: "stub" | "missing" | "done") {
switch (type) {
case "stub":
return <IconStub />;
case "missing":
return <IconMissing />;
case "done":
return <IconDone />;
}
}
97 changes: 63 additions & 34 deletions src/app/compatibility/avm2/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import {
Container,
Group,
Expand All @@ -8,22 +10,26 @@ import {
Title,
} from "@mantine/core";
import Image from "next/image";
import React from "react";
import React, { useEffect, useState } from "react";
import classes from "./avm2.module.css";
import { ClassBox } from "@/app/compatibility/avm2/class_box";
import {
getReportByNamespace,
NamespaceStatus,
} from "@/app/compatibility/avm2/report_utils";
import {
IconDone,
IconMissing,
IconStub,
NamespaceStatus,
} from "@/app/compatibility/avm2/report_utils";
} from "@/app/compatibility/avm2/icons";
import Link from "next/link";
import { useTranslation, Trans } from "@/app/translate";

function NamespaceBox(props: NamespaceStatus) {
const { t } = useTranslation();
return (
<Stack className={classes.namespace}>
<Title order={2}>{props.name || "(Top Level)"}</Title>
<Title order={2}>{props.name || t("compatibility.avm2.top-level")}</Title>
<Group align="baseline">
{Object.entries(props.classes).map(([classname, classinfo]) => (
<ClassBox key={classname} {...classinfo} />
Expand All @@ -33,8 +39,22 @@ function NamespaceBox(props: NamespaceStatus) {
);
}

export default async function Page() {
const byNamespace = await getReportByNamespace();
export default function Page() {
const { t } = useTranslation();
const [byNamespace, setByNamespace] = useState<
{ [name: string]: NamespaceStatus } | undefined
>(undefined);
useEffect(() => {
const fetchData = async () => {
try {
const byNamespace = await getReportByNamespace();
setByNamespace(byNamespace);
} catch (error) {
console.error("Error fetching data", error);
}
};
fetchData();
}, []);
return (
<Container size="xl">
<Stack gap="xl">
Expand All @@ -48,43 +68,52 @@ export default async function Page() {
className={classes.progressImage}
/>
<Stack className={classes.actionscriptInfo}>
<Title className={classes.title}>ActionScript 3 API Progress</Title>
<Text>
ActionScript 3 contains many different methods and classes - not
all of which is ultimately <i>useful</i> to every application. The
majority of content only uses a small portion of the available
API, so even if we aren&apos;t 100% &quot;complete&quot; across
the entirely of AVM 2, we may have enough for that content to run
completely fine.
</Text>
<Text>
On this page, we list every single ActionScript 3 API that exists
but Ruffle does not yet 100% implement. We classify items into
three different stages:
</Text>
<Title className={classes.title}>
{t("compatibility.avm2.title")}
</Title>
<Text>{t("compatibility.avm2.description")}</Text>
<Text>{t("compatibility.avm2.classification")}</Text>
<List spacing="sm">
<ListItem icon={<IconDone />}>
<b>Implemented</b> items are marked as &quot;Done&quot;, and we
believe they are fully functional. For brevity, we do not list
completed items on this page.
<Trans
i18nKey="compatibility.avm2.implemented-description"
components={[
<b key="implemented">
{t("compatibility.avm2.implemented")}
</b>,
]}
/>
</ListItem>
<ListItem icon={<IconStub />}>
<b>Partial</b> items exist and are enough for most content to
work, but are incomplete. A partial class may be missing items,
or a method may just simply return a value without performing
its intended function.
<Trans
i18nKey="compatibility.avm2.partial-description"
components={[
<b key="partial">{t("compatibility.avm2.partial")}</b>,
]}
/>
</ListItem>
<ListItem icon={<IconMissing />}>
<b>Missing</b> items do not exist at all in Ruffle yet, and
trying to use them will give an error.
<Trans
i18nKey="compatibility.avm2.missing-description"
components={[
<b key="missing">{t("compatibility.avm2.missing")}</b>,
]}
/>
</ListItem>
</List>
<Text>
You can also visualize the progress{" "}
<Link href="/compatibility/avm2/tree.svg" target="_blank">
as a tree graph
</Link>
.
<Trans
i18nKey="compatibility.avm2.tree"
components={[
<Link
key="link"
href="/compatibility/avm2/tree.svg"
target="_blank"
>
{t("compatibility.avm2.tree-link")}
</Link>,
]}
/>
</Text>
</Stack>
</Group>
Expand Down
Loading