解决多语言切换的bug

This commit is contained in:
ymk
2025-08-02 12:06:41 +08:00
parent f54550631c
commit aa1e2b105d
11 changed files with 100 additions and 74 deletions

View File

@@ -1,6 +1,9 @@
{
"Index": {
"Header": {
"appName": "Fast3DText",
"editorName": "Editor"
},
"HomePage": {
"heroTitle": "Create Stunning 3D Text Designs",
"heroSubtitle": "Generate and customize beautiful 3D text effects for your projects",
"toolTitle": "3D Text Generator Tool",

View File

@@ -1,6 +1,9 @@
{
"Index": {
"Header": {
"appName": "Fast3DText",
"editorName": "编辑器"
},
"HomePage": {
"heroTitle": "创建惊艳的3D文字设计",
"heroSubtitle": "为您的项目生成并定制精美的3D文字效果",
"toolTitle": "3D文字生成工具",

View File

@@ -7,17 +7,10 @@ import { Metadata } from "next";
import Editor from "@/components/SimpleEditor";
import { FontNames, FontWeights, TextProp } from "@/components/common/TextSetting";
export default function Page({
params,
}: {
params: Promise<{ locale: string }>;
}) {
const { locale } = use(params);
// Enable static rendering
setRequestLocale(locale);
export default function Page() {
const t = useTranslations("DoNotWriteOnThisPage");
const indexT = useTranslations("Index");
const indexT = useTranslations("HomePage");
const text = TextProp.default("Do Not Write On This Page");

View File

@@ -3,9 +3,10 @@ import Footer from "@/components/Footer";
import FullEditor from "@/components/FullEditor";
import Header from "@/components/Header";
import { Locales } from "@/i18n/config";
import { Box, Flex } from "@radix-ui/themes";
import { Flex } from "@radix-ui/themes";
import { Metadata } from "next";
import { getTranslations } from "next-intl/server";
import { getTranslations, setRequestLocale } from "next-intl/server";
import { use } from "react";
const host = process.env.NEXT_PUBLIC_HOST;
export default function Page() {

View File

@@ -8,16 +8,9 @@ import { Locales } from "@/i18n/config";
import { Metadata } from "next";
import { Box, Flex, Heading, Section, Text } from "@radix-ui/themes";
const host = process.env.NEXT_PUBLIC_HOST;
export default function HomePage({
params,
}: {
params: Promise<{ locale: string }>;
}) {
const { locale } = use(params);
// Enable static rendering
setRequestLocale(locale);
export default function HomePage() {
const t = useTranslations("Index");
const t = useTranslations("HomePage");
return (
<div className="flex flex-col min-h-screen overflow-hidden">

View File

@@ -1,10 +1,16 @@
'use client'
import { useTranslations } from "next-intl";
import LanguageSwitcher from "./LanguageSwitcher";
import { ModeToggle } from "./ModeToggle";
import { Box, Flex, Link, Strong, Text } from "@radix-ui/themes";
import { useRouter } from "@/i18n/navigation";
export default function Header() {
const t = useTranslations("Index");
const t = useTranslations("Header");
const router = useRouter();
return (
<header className="w-full py-2 border-b-1 ">
<Flex justify="center" gap="9" align="center">
@@ -16,9 +22,9 @@ export default function Header() {
<Flex gap={"4"} justify={"center"} align={"center"} className="w-1/2">
<Link
href="/editor"
onClick={() => { router.push("/editor") }}
>
Editor
{t("editorName")}
</Link>
</Flex>

View File

@@ -1,44 +1,12 @@
"use client";
import { useEffect, useState } from "react";
'use client';
import { usePathname, useRouter } from "@/i18n/navigation";
import { Locales } from "@/i18n/config";
import { Button, DropdownMenu } from "@radix-ui/themes";
import { useLocale } from "next-intl";
const LanguageSwitcher = () => {
const router = useRouter();
const pathname = usePathname();
const [currentLanguage, setCurrentLanguage] = useState("en");
const locale = useLocale();
useEffect(() => {
const savedLanguage =
document.cookie
.split("; ")
.find((row) => row.startsWith("NEXT_LOCALE="))
?.split("=")[1] || "en";
setCurrentLanguage(savedLanguage);
const urlLanguage = pathname.split("/")[1];
if (Locales.includes(urlLanguage)) {
setCurrentLanguage(urlLanguage);
}
}, [pathname]);
const changeLanguage = (newLanguage: string) => {
setCurrentLanguage(newLanguage);
document.cookie = `NEXT_LOCALE=${newLanguage}; path=/;`;
const segments = pathname.split("/");
if (Locales.includes(segments[1])) {
segments[1] = newLanguage;
} else {
segments.splice(1, 0, newLanguage);
}
router.push(segments.join("/"));
router.refresh();
};
const languageLabels = {
en: "English",
@@ -48,21 +16,26 @@ const LanguageSwitcher = () => {
// jp: "日本語",
};
const router = useRouter();
const labels = [];
for (let l in languageLabels) {
const key = l as keyof typeof languageLabels;
labels.push(
<DropdownMenu.Item key={l} onClick={() => changeLanguage(l)}>
<DropdownMenu.Item key={l} onClick={() => {
if (l !== locale) {
router.push(pathname, { locale: l });
}
}}>
{languageLabels[key]}
</DropdownMenu.Item>
);
}
return (
<DropdownMenu.Root dir={currentLanguage === "ar" ? "rtl" : "ltr"}>
<DropdownMenu.Root dir={locale === "ar" ? "rtl" : "ltr"}>
<DropdownMenu.Trigger >
<Button variant="outline" size={"2"}>
{languageLabels[currentLanguage as keyof typeof languageLabels]}
{languageLabels[locale as keyof typeof languageLabels]}
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content align="end">

View File

@@ -5,9 +5,10 @@ import BackgroundSelector, {
} from "./common/BackgroundSelector";
import PreviewToolbar from "./common/PreviewToolbar";
import SimpleTextSetting from "./common/SimpleTextSetting";
import { useState } from "react";
import { useEffect, useState } from "react";
import { useTranslations } from "next-intl";
import { TextProp } from "./common/TextSetting";
import { useRouter } from "@/i18n/navigation";
/**
* 简易工具
@@ -16,7 +17,9 @@ import { TextProp } from "./common/TextSetting";
export default function Page({ textProp, backgroundProp }: { textProp: TextProp | undefined, backgroundProp: BackgroundProp | undefined }) {
const t = useTranslations("TextEditor");
const tIndex = useTranslations("Index");
const tIndex = useTranslations("HomePage");
const router = useRouter();
const [background, setBackground] = useState<BackgroundProp>(backgroundProp || {
type: "color",
@@ -26,6 +29,34 @@ export default function Page({ textProp, backgroundProp }: { textProp: TextProp
const [text, setText] = useState<TextProp>(textProp || TextProp.default(t("defaultText")));
useEffect(() => {
let bg = sessionStorage.getItem("background");
if (bg) {
console.log("初始化设置 bg", bg);
setBackground(JSON.parse(bg));
}
let txt = sessionStorage.getItem("text");
if (txt) {
console.log("初始化设置 txt", txt);
setText(JSON.parse(txt));
}
}, []);
useEffect(() => {
sessionStorage.setItem("background", JSON.stringify(background));
}, [background]);
useEffect(() => {
sessionStorage.setItem("text", JSON.stringify(text));
}, [text]);
return (
<Flex gap={"2"}>
<Flex gap={"2"} direction={"column"} className="w-1/3">
@@ -39,7 +70,7 @@ export default function Page({ textProp, backgroundProp }: { textProp: TextProp
<Flex className="w-2/3" direction={"column"} justify={"between"}>
<PreviewToolbar background={background} text={text} />
<Box className="text-center"> <Link href="./editor">{tIndex("toolMore")}?</Link> </Box>
<Box className="text-center"> <Link onClick={() => { router.push("/editor") }}>{tIndex("toolMore")}?</Link> </Box>
</Flex>
</Flex>
);

View File

@@ -47,8 +47,8 @@ export default function PreviewToolbar({
} else {
const box = container.current;
const split = Sizes[aspectRadio].split("x").map(Number);
threeInit(box, split[0], split[1]);
console.log("three init");
const initSuccess = threeInit(box, split[0], split[1]);
console.log("three init ", initSuccess);
}
}
@@ -59,13 +59,26 @@ export default function PreviewToolbar({
useEffect(updateSize, [aspectRadio]);
useEffect(() => {
updateBackground(background);
console.log("background init");
const timeoutId = setTimeout(() => {
updateBackground(background);
console.log("background change", background);
}, 200);
return () => clearTimeout(timeoutId);
}, [background]);
useEffect(() => {
updateTextProps(text);
console.log("text init");
const timeoutId = setTimeout(() => {
updateTextProps(text);
console.log("text change", text);
}, 1000);
return () => clearTimeout(timeoutId);
}, [text]);
const handleDownload = () => {

View File

@@ -13,11 +13,20 @@ let camera: THREE.PerspectiveCamera,
controls: OrbitControls,
container: HTMLCanvasElement;
console.log("three tool loaded");
let inited = false;
export function init(
_container: HTMLCanvasElement,
width: number,
height: number
) {
// if (inited) {
// renderer.dispose();
// }
inited = true;
container = _container;
scene = new THREE.Scene();
@@ -156,6 +165,7 @@ export async function updateTextProps(textProps: TextProp) {
(textMesh.material as THREE.MeshLambertMaterial).color.set(textProps.color);
}
scene.add(textMesh);
lastTextProps = textProps;
}

View File

@@ -7,7 +7,7 @@ export const routing = defineRouting({
// Used when no locale matches
defaultLocale: "en",
localeDetection: true,
localeDetection: false,
//to remove the locale prefix from the url
localePrefix: "never",
localePrefix: "as-needed",
});