Skip to content

Commit 253b15c

Browse files
committed
i18n: Translate first blog post but keep RSS feed working
1 parent 7e0a012 commit 253b15c

File tree

7 files changed

+131
-57
lines changed

7 files changed

+131
-57
lines changed

blog_posts/2023-03-12-progress-report.markdown

+20-20
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ date: 2023-03-12 01:23:00 +0100
44
author: nosamu
55
icon: /undraw/undraw_welcoming_re_x0qo.svg
66
---
7-
Get ready for the biggest Ruffle announcement yet! And the first one on the blog!
7+
{{blog.20230312.headline}}
88

99
---
1010

11-
## Huge improvements to Ruffle's AVM1 engine accuracy!
12-
Thanks to a massive code refactor by [@CUB3D](https://github.com/CUB3D/), dozens upon dozens of ActionScript 2 games have been fixed! Here are just a few of them:
11+
## {{blog.20230312.avm1-improvements}}
12+
{{blog.20230312.avm1-fixes-start}} [@CUB3D](https://github.com/CUB3D/){{blog.20230312.avm1-fixes-end}}
1313
- [Chibi Knight](https://www.newgrounds.com/portal/view/526470)
1414
- [Xeno Tactic 2](https://www.newgrounds.com/portal/view/438241/format/flash?emulate=flash)
1515
- [Trojan War](https://www.newgrounds.com/portal/view/604949/format/flash?emulate=flash)
@@ -20,44 +20,44 @@ Thanks to a massive code refactor by [@CUB3D](https://github.com/CUB3D/), dozens
2020
- [The Powerpuff Girls: Attack of the Puppybots](https://flasharch.com/en/archive/play/b93354279e9788b849f83ef78f52cbbb)
2121
- [Extreme Pamplona](https://flasharch.com/en/archive/play/e36aac73914ec8672218317e000615d7)
2222

23-
## Incredible progress in AVM2 (ActionScript 3) support!
24-
- Our website now has [a page listing exactly what ActionScript 3 APIs we have implemented](https://ruffle.rs/compatibility/avm2), making it easy to follow our progress. It will be frequently updated!
25-
- XML support is rapidly improving! ActionScript 3 games tend to use a wide variety of XML methods. As Ruffle gains support for these methods, games are springing to life!
26-
- Several problems that caused unresponsive buttons and menus have been fixed. Unclickable buttons in ActionScript 3 games are (mostly) a thing of the past!
27-
- Other major refactors are in progress to improve Ruffle's compatibility with ActionScript 3 frameworks like Haxe.
28-
- [@Aaron1011](https://github.com/Aaron1011/) is working on **Stage3D support**! Thanks to his work, the gorgeous interstellar strategy game Solarmax 2 is now fully playable in Ruffle on the desktop player! Check out the video below.
23+
## {{blog.20230312.avm2-improvements}}
24+
- {{blog.20230312.avm2-progress-start}} [{{blog.20230312.avm2-progress-link}}](https://ruffle.rs/compatibility/avm2){{blog.20230312.avm2-progress-end}}
25+
- {{blog.20230312.xml-support}}
26+
- {{blog.20230312.unresponsive-buttons}}
27+
- {{blog.20230312.framework-compatibility}}
28+
- [@Aaron1011](https://github.com/Aaron1011/) {{blog.20230312.stage3d-support-start}} **{{blog.20230312.stage3d-support}}**{{blog.20230312.stage3d-support-end}}
2929

3030
<video muted autoplay controls>
3131
<source src="/2023-03-12-progress-report/ruffle_solarmax2.mp4" type="video/mp4">
3232
</video>
3333

34-
Many of the fan-favorite **Flipline games are now playable**! Check them out:
34+
{{blog.20230312.flipline-start}} **{{blog.20230312.flipline}}**{{blog.20230312.flipline-end}}
3535
- [Papa's Burgeria](https://www.kongregate.com/games/FliplineStudios/papas-burgeria)
3636
- [Jacksmith](https://www.kongregate.com/games/FliplineStudios/jacksmith)
37-
- [Papa's Cheeseria](https://www.flipline.com/games/papascheeseria/index.html) (requires the Ruffle Chrome extension)
38-
- [Papa's Bakeria](https://www.flipline.com/games/papasbakeria/index.html) (requires the Ruffle Chrome extension)
37+
- [Papa's Cheeseria](https://www.flipline.com/games/papascheeseria/index.html) {{blog.20230312.extension-required}}
38+
- [Papa's Bakeria](https://www.flipline.com/games/papasbakeria/index.html) {{blog.20230312.extension-required}}
3939

4040
<video muted autoplay controls>
4141
<source src="/2023-03-12-progress-report/ruffle_burgeria.mp4" type="video/mp4">
4242
</video>
4343

44-
Here are just a few more of the many ActionScript 3 games that are playable today in Ruffle!
44+
{{blog.20230312.more-as3-games}}
4545
- [Canabalt](https://www.newgrounds.com/portal/view/510303)
4646
- [Bloons Tower Defense 3](https://www.newgrounds.com/portal/view/463445/format/flash?emulate=flash)
4747
- [Diggy](https://www.kongregate.com/games/Vogd/diggy)
4848
- [Wooden Path 2](https://www.kongregate.com/games/Remivision/wooden-path-2)
4949
- [Fracuum](https://www.newgrounds.com/portal/view/594354)
5050
- [Dino Run: Marathon of Doom](https://www.newgrounds.com/portal/view/566176)
5151

52-
## Last but not least, support for **mobile devices** is improving in a big way!
53-
- **Text input boxes** are finally supported on mobile devices! Tapping on a text box within Flash content now brings up the soft keyboard, so you can type into it without using a bluetooth keyboard or other workarounds.
54-
- The **context menu** finally works on iOS! It is activated by a long-press on the screen. To stop this behavior if needed, simply tap the "Hide this menu" option.
52+
## {{blog.20230312.mobile-start}} **{{blog.20230312.mobile}}** {{blog.20230312.mobile-end}}
53+
- **{{blog.20230312.text-input}}** {{blog.20230312.text-input-support}}
54+
- {{blog.20230312.context-menu-start}} **{{blog.20230312.context-menu}}** {{blog.20230312.context-menu-end}}
5555

5656
<video muted autoplay controls>
5757
<source src="/2023-03-12-progress-report/Ruffle_Kongregate_Pizzeria_iPhone.mov" type="video/mp4">
5858
</video>
5959

60-
**We have even more improvements coming very soon!**
61-
- The latest releases now have **dynamic audio buffering**, making audio playback in the most demanding content much smoother! (Thanks to [@szőlő](https://github.com/torokati44/))
62-
- A bug that causes some AVM2 games' intro sounds to repeat over and over will soon be fixed. (Thanks to [@Aaron1011](https://github.com/Aaron1011/))
63-
- [@Dinnerbone](https://github.com/Dinnerbone/) is working on improving drawing accuracy for thin/hairline strokes and scaled objects. [You can follow his progress here](https://github.com/ruffle-rs/ruffle/pull/9981).
60+
**{{blog.20230312.more-soon}}**
61+
- {{blog.20230312.audio-buffering-start}} **{{blog.20230312.audio-buffering}}**{{blog.20230312.audio-buffering-description}}[@szőlő](https://github.com/torokati44/){{blog.20230312.parentheses-end}}
62+
- {{blog.20230312.looping}}[@Aaron1011](https://github.com/Aaron1011/){{blog.20230312.parentheses-end}}
63+
- [@Dinnerbone](https://github.com/Dinnerbone/) {{blog.20230312.hairline-description}} [{{blog.20230312.hairline-link}}](https://github.com/ruffle-rs/ruffle/pull/9981){{blog.20230312.line-end}}

src/app/blog/[year]/[month]/[day]/[slug]/page.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { getPostData, getSortedPostsData, PostPath } from "@/app/blog/utils";
22
import { Container } from "@mantine/core";
33
import { BlogPost } from "@/app/blog/post";
44
import { Metadata } from "next";
5+
import { getBaseTranslation } from "@/app/utils";
56

67
export async function generateMetadata(props: {
78
params: Promise<PostPath>;
@@ -12,12 +13,12 @@ export async function generateMetadata(props: {
1213
);
1314
const baseUrl = process.env.BASE_URL || "";
1415
return {
15-
title: `${post.title} - Ruffle`,
16+
title: `${getBaseTranslation(post.title)} - Ruffle`,
1617
description: post.excerpt.split("\n")[0].trim(),
1718
metadataBase: baseUrl ? new URL(baseUrl) : null,
1819
openGraph: {
1920
type: "article",
20-
title: post.title,
21+
title: getBaseTranslation(post.title),
2122
siteName: "Ruffle",
2223
publishedTime: post.date.toISOString(),
2324
authors: [post.author],

src/app/blog/post.tsx

+35-10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Image from "next/image";
99
import rehypeRaw from "rehype-raw";
1010
import rehypeSlug from "rehype-slug";
1111
import { useTranslation } from "@/app/translate";
12+
import React from "react";
1213

1314
export interface BlogPostProps {
1415
metadata: PostMetadata;
@@ -30,6 +31,17 @@ export function BlogPostAndIcon({ metadata, type }: BlogPostProps) {
3031
);
3132
}
3233

34+
function processChild(
35+
child: React.ReactNode,
36+
t: (key: string) => string,
37+
): React.ReactNode {
38+
if (typeof child === "string") {
39+
// Replace all {{key}} occurrences with t("key")
40+
return child.replace(/{{(.*?)}}/g, (_, key) => t(key.trim()));
41+
}
42+
return child; // Return as is if not a string
43+
}
44+
3345
export function BlogPost({ metadata, type }: BlogPostProps) {
3446
const { t } = useTranslation();
3547
const url = `/blog/${metadata.year}/${metadata.month}/${metadata.day}/${metadata.slug}`;
@@ -55,17 +67,30 @@ export function BlogPost({ metadata, type }: BlogPostProps) {
5567
</Group>
5668
<div>
5769
<Markdown
58-
className={type == "excerpt" ? classes.excerpt : classes.contents}
70+
className={type === "excerpt" ? classes.excerpt : classes.contents}
5971
rehypePlugins={[rehypeRaw, rehypeSlug]}
60-
components={{
61-
a(props) {
62-
return (
63-
<Link href={props.href || "#"} target="_blank">
64-
{props.children}
65-
</Link>
66-
);
67-
},
68-
}}
72+
components={["a", "p", "h2", "li", "strong", "code", "em"].reduce(
73+
(acc, tag) => ({
74+
...acc,
75+
[tag]: (props: { children?: React.ReactNode; href?: string }) =>
76+
tag === "a" ? (
77+
<Link href={props.href || "#"} target="_blank">
78+
{React.Children.map(props.children, (child) =>
79+
processChild(child, t),
80+
)}
81+
</Link>
82+
) : (
83+
React.createElement(
84+
tag,
85+
null,
86+
React.Children.map(props.children, (child) =>
87+
processChild(child, t),
88+
),
89+
)
90+
),
91+
}),
92+
{},
93+
)}
6994
>
7095
{type == "excerpt" ? metadata.excerpt : metadata.content}
7196
</Markdown>

src/app/feed.xml/route.tsx

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Feed } from "feed";
22
import { getSortedPostsData } from "@/app/blog/utils";
3+
import { getBaseTranslation } from "@/app/utils";
34

45
export async function GET() {
56
const posts = getSortedPostsData();
@@ -22,8 +23,10 @@ export async function GET() {
2223
feed.addItem({
2324
date: post.date,
2425
link: `https://ruffle.rs/blog/${post.year}/${post.month}/${post.day}/${post.slug}`,
25-
title: post.title,
26-
description: post.excerpt,
26+
title: getBaseTranslation(post.title),
27+
description: post.excerpt.replace(/{{(.*?)}}/g, (_, key) =>
28+
getBaseTranslation(key.trim()),
29+
),
2730
author: [{ name: post.author }],
2831
});
2932
}
@@ -35,4 +38,5 @@ export async function GET() {
3538
});
3639
}
3740

38-
export const dynamic = "force-static";
41+
//export const dynamic = "force-static";
42+
export const revalidate = 1;

src/app/translate.tsx

+1-21
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,14 @@
22

33
import React, { useEffect, useState, useCallback } from "react";
44
import defaultTranslations from "@/i18n/translations.en.json";
5+
import { getNestedTranslation, TranslationObject } from "@/app/utils";
56

67
const languages = {
78
en: "English",
89
es: "Español",
910
// ...
1011
};
1112

12-
type TranslationObject = {
13-
[key: string]: string | TranslationObject;
14-
};
15-
1613
interface LanguageSelectorProps {
1714
className?: string;
1815
}
@@ -44,23 +41,6 @@ async function getAvailableLanguage() {
4441
return lang;
4542
}
4643

47-
const getNestedTranslation = (
48-
obj: TranslationObject,
49-
key: string,
50-
): string | undefined => {
51-
let acc: TranslationObject | string | undefined = obj;
52-
for (let i = 0; i < key.split(".").length; i++) {
53-
const part = key.split(".")[i];
54-
if (acc && typeof acc !== "string" && acc[part] !== undefined) {
55-
acc = acc[part];
56-
} else {
57-
acc = undefined; // If a part is not found, stop and return undefined
58-
break;
59-
}
60-
}
61-
return typeof acc === "string" ? acc : undefined;
62-
};
63-
6444
async function fetchTranslations(lang: string) {
6545
try {
6646
const translations = await import(`@/i18n/translations.${lang}.json`);

src/app/utils.tsx

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import defaultTranslations from "@/i18n/translations.en.json";
2+
3+
export type TranslationObject = {
4+
[key: string]: string | TranslationObject;
5+
};
6+
7+
export const getNestedTranslation = (
8+
obj: TranslationObject,
9+
key: string,
10+
): string | undefined => {
11+
let acc: TranslationObject | string | undefined = obj;
12+
for (let i = 0; i < key.split(".").length; i++) {
13+
const part = key.split(".")[i];
14+
if (acc && typeof acc !== "string" && acc[part] !== undefined) {
15+
acc = acc[part];
16+
} else {
17+
acc = undefined; // If a part is not found, stop and return undefined
18+
break;
19+
}
20+
}
21+
return typeof acc === "string" ? acc : undefined;
22+
};
23+
24+
export function getBaseTranslation(translationKey: string): string {
25+
return (
26+
getNestedTranslation(defaultTranslations, translationKey) || translationKey
27+
);
28+
}

src/i18n/translations.en.json

+37-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,43 @@
146146
"blog": {
147147
"read-more": "Read more...",
148148
"20230312": {
149-
"title": "First post, progress report!"
149+
"title": "First post, progress report!",
150+
"headline": "Get ready for the biggest Ruffle announcement yet! And the first one on the blog!",
151+
"avm1-improvements": "Huge improvements to Ruffle's AVM1 engine accuracy!",
152+
"avm1-fixes-start": "Thanks to a massive code refactor by",
153+
"avm1-fixes-end": ", dozens upon dozens of ActionScript 2 games have been fixed! Here are just a few of them:",
154+
"avm2-improvements": "Incredible progress in AVM2 (ActionScript 3) support!",
155+
"avm2-progress-start": "Our website now has",
156+
"avm2-progress-link": "a page listing exactly what ActionScript 3 APIs we have implemented",
157+
"avm2-progress-end": ", making it easy to follow our progress. It will be frequently updated!",
158+
"xml-support": "XML support is rapidly improving! ActionScript 3 games tend to use a wide variety of XML methods. As Ruffle gains support for these methods, games are springing to life!",
159+
"unresponsive-buttons": "Several problems that caused unresponsive buttons and menus have been fixed. Unclickable buttons in ActionScript 3 games are (mostly) a thing of the past!",
160+
"framework-compatibility": "Other major refactors are in progress to improve Ruffle's compatibility with ActionScript 3 frameworks like Haxe.",
161+
"stage3d-support-start": "is working on",
162+
"stage3d-support": "Stage3D support",
163+
"stage3d-support-end": "! Thanks to his work, the gorgeous interstellar strategy game Solarmax 2 is now fully playable in Ruffle on the desktop player! Check out the video below.",
164+
"flipline-start": "Many of the fan-favorite",
165+
"flipline": "Flipline games are now playable",
166+
"flipline-end": "! Check them out:",
167+
"extension-required": "(requires the Ruffle Chrome extension)",
168+
"more-as3-games": "Here are just a few more of the many ActionScript 3 games that are playable today in Ruffle!",
169+
"mobile-start": "Last but not least, support for",
170+
"mobile": "mobile devices",
171+
"mobile-end": "is improving in a big way!",
172+
"text-input": "Text input boxes",
173+
"text-input-support": "are finally supported on mobile devices! Tapping on a text box within Flash content now brings up the soft keyboard, so you can type into it without using a bluetooth keyboard or other workarounds.",
174+
"context-menu-start": "The",
175+
"context-menu": "context menu",
176+
"context-menu-end": "finally works on iOS! It is activated by a long-press on the screen. To stop this behavior if needed, simply tap the \"Hide this menu\" option.",
177+
"more-soon": "We have even more improvements coming very soon!",
178+
"audio-buffering-start": "The latest releases now have",
179+
"audio-buffering": "dynamic audio buffering",
180+
"audio-buffering-description": ", making audio playback in the most demanding content much smoother! (Thanks to ",
181+
"parentheses-end": ")",
182+
"looping": "A bug that causes some AVM2 games' intro sounds to repeat over and over will soon be fixed. (Thanks to ",
183+
"hairline-description": "is working on improving drawing accuracy for thin/hairline strokes and scaled objects.",
184+
"hairline-link": "You can follow his progress here",
185+
"line-end": "."
150186
},
151187
"20230423": {
152188
"title": "A post-mortem of Ruffle's removal from addons.mozilla.org"

0 commit comments

Comments
 (0)