Skip to content

Commit

Permalink
translatecomponent
Browse files Browse the repository at this point in the history
  • Loading branch information
ttizze committed Jul 15, 2024
1 parent 368055e commit 8f50021
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 39 deletions.
9 changes: 7 additions & 2 deletions web/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import {
Scripts,
ScrollRestoration,
} from "@remix-run/react";
import "./tailwind.css";
import tailwind from "~/tailwind.css?url";
import type { User } from "@prisma/client";
import { json } from "@remix-run/node";
import type { LoaderFunctionArgs } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { Header } from "./components/Header";
import { authenticator } from "./utils/auth.server";
import type { LinksFunction } from "@remix-run/node";

type UserWithoutPassword = Omit<User, "password">;

export const links: LinksFunction = () => [
{ rel: "stylesheet", href: tailwind },
];
export interface RootLoaderData {
user: UserWithoutPassword | null;
}
Expand All @@ -25,7 +29,8 @@ export async function loader({ request }: LoaderFunctionArgs) {
return json<RootLoaderData>({ user: safeUser });
}
export function Layout({ children }: { children: React.ReactNode }) {
const { user } = useLoaderData<RootLoaderData>();
const data = useLoaderData<typeof loader>();
const user = data?.user as UserWithoutPassword | null;

return (
<html lang="en">
Expand Down
2 changes: 1 addition & 1 deletion web/app/routes/_index/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { extractNumberedElements } from "../../utils/extractNumberedElements";
import {
URLTranslationForm,
urlTranslationSchema,
} from "../components/URLTranslationForm";
} from "./components/URLTranslationForm";
import { addNumbersToContent } from "./utils/addNumbersToContent";
import { extractArticle } from "./utils/articleUtils";
import { fetchWithRetry } from "./utils/fetchWithRetry";
Expand Down
51 changes: 51 additions & 0 deletions web/app/routes/reader.$encodedUrl/components/TranslatedContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import parse from "html-react-parser";

interface TranslatedContentProps {
content: string;
translations: Array<{ number: number; text: string }>;
targetLanguage: string;
}

function Translation({ text, targetLanguage }: { text: string; targetLanguage: string }) {
return (
<div
lang={targetLanguage}
className="notranslate block mt-2 p-2 bg-gray-100 rounded-md"
>
{text}
</div>
);
};

export function TranslatedContent({ content, translations, targetLanguage }: TranslatedContentProps) {
if (typeof window === 'undefined') {
return <div>Loading...</div>;
}
const doc = new DOMParser().parseFromString(content, 'text/html');

for (const { number, text } of translations) {
const element = doc.querySelector(`[data-number="${number}"]`);
if (element) {
const translationElement = doc.createElement('div');
translationElement.setAttribute('data-translation', number.toString());
element.appendChild(translationElement);
}
}

return (
<>
{parse(doc.body.innerHTML, {
replace: (domNode) => {
if (domNode.type === 'tag' && domNode.attribs['data-translation']) {
const number = Number.parseInt(domNode.attribs['data-translation'], 10);
const translation = translations.find(t => t.number === number);
if (translation) {
return <Translation key="translation" text={translation.text} targetLanguage={targetLanguage} />;
}
}
return domNode;
}
})}
</>
);
}
55 changes: 19 additions & 36 deletions web/app/routes/reader.$encodedUrl/route.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { type LoaderFunctionArgs, json } from "@remix-run/node";
import { useLoaderData, useParams } from "@remix-run/react";
import parse from "html-react-parser";
import { extractNumberedElements } from "../../utils/extractNumberedElements";
import { prisma } from "../../utils/prisma";
import { displayContent } from "./utils/create";
import { TranslatedContent } from "./components/TranslatedContent";

export const loader = async ({ params }: LoaderFunctionArgs) => {
const { encodedUrl } = params;
Expand All @@ -18,7 +16,10 @@ export const loader = async ({ params }: LoaderFunctionArgs) => {
include: {
translateTexts: {
where: { language: "ja" },
orderBy: { createdAt: "desc" },
orderBy: [
{ point: "desc" },
{ createdAt: "desc" }
],
take: 1,
},
},
Expand All @@ -29,42 +30,24 @@ export const loader = async ({ params }: LoaderFunctionArgs) => {
throw new Response("Failed to fetch article", { status: 500 });
}

// コンテンツから番号付き要素を抽出
const numberedElements = extractNumberedElements(latestPageVersion.content);
const translations = latestPageVersion.sourceTexts.map((sourceText) => ({
number: sourceText.number,
text: sourceText.translateTexts[0]?.text,
}));

// 翻訳テキストを適用
console.log("latestPageVersion.sourceTexts", latestPageVersion.sourceTexts);
const translatedElements = numberedElements.map((element) => {
const sourceText = latestPageVersion.sourceTexts.find(
(st) => st.text === element.text,
);
if (sourceText && sourceText.translateTexts.length > 0) {
return {
...element,
text: sourceText.translateTexts[0].text,
};
}
return element;
});

// 翻訳されたコンテンツを生成
const translatedContent = await displayContent(
latestPageVersion.content,
translatedElements,
);

return json({
title: latestPageVersion.title,
url: latestPageVersion.url,
content: translatedContent,
});
return json({
title: latestPageVersion.title,
url: latestPageVersion.url,
content: latestPageVersion.content,
translations,
});
};

export default function ReaderView() {
const { encodedUrl } = useParams();
const article = useLoaderData<typeof loader>();
const { title, url, content, translations } = useLoaderData<typeof loader>();

if (!article) {
if (!title || !url || !content || !translations) {
return <div>Loading...</div>;
}

Expand All @@ -73,7 +56,7 @@ export default function ReaderView() {
return (
<div className="container mx-auto px-4 py-8">
<article className="prose lg:prose-xl">
<h1>{article.title}</h1>
<h1>{title}</h1>
<p>
<a
href={originalUrl}
Expand All @@ -84,7 +67,7 @@ export default function ReaderView() {
Original Article
</a>
</p>
<div>{parse(article.content)}</div>
<TranslatedContent content={content} translations={translations} targetLanguage="ja" />
</article>
</div>
);
Expand Down

0 comments on commit 8f50021

Please sign in to comment.