diff --git a/next-i18next.config.js b/next-i18next.config.js deleted file mode 100644 index 0332432..0000000 --- a/next-i18next.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - i18n: { - defaultLocale: 'en', - locales: ['en', 'zh-CN'], - }, -} \ No newline at end of file diff --git a/next.config.mjs b/next.config.mjs index b89fb19..c3bec89 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,9 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - i18n: { - defaultLocale: 'en', - locales: ['en', 'zh-CN'], - } + }; export default nextConfig; diff --git a/package.json b/package.json index 5e37f9f..7dfd98c 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,10 @@ "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", "@mui/material": "^6.1.3", - "i18next": "^23.15.2", "next": "14.2.15", - "next-i18next": "^15.3.1", + "next-intl": "^3.21.1", "react": "^18", - "react-dom": "^18", - "react-i18next": "^15.0.3" + "react-dom": "^18" }, "devDependencies": { "@types/node": "^20", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b5321bd..ff6f1ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: next: specifier: 14.2.15 version: 14.2.15(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-intl: + specifier: ^3.21.1 + version: 3.21.1(next@14.2.15(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) react: specifier: ^18 version: 18.3.1 @@ -175,6 +178,21 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@formatjs/ecma402-abstract@2.2.0': + resolution: {integrity: sha512-IpM+ev1E4QLtstniOE29W1rqH9eTdx5hQdNL8pzrflMj/gogfaoONZqL83LUeQScHAvyMbpqP5C9MzNf+fFwhQ==} + + '@formatjs/fast-memoize@2.2.1': + resolution: {integrity: sha512-XS2RcOSyWxmUB7BUjj3mlPH0exsUzlf6QfhhijgI941WaJhVxXQ6mEWkdUFIdnKi3TuTYxRdelsgv3mjieIGIA==} + + '@formatjs/icu-messageformat-parser@2.7.10': + resolution: {integrity: sha512-wlQfqCZ7PURkUNL2+8VTEFavPovtADU/isSKLFvDbdFmV7QPZIYqFMkhklaDYgMyLSBJa/h2MVQ2aFvoEJhxgg==} + + '@formatjs/icu-skeleton-parser@1.8.4': + resolution: {integrity: sha512-LMQ1+Wk1QSzU4zpd5aSu7+w5oeYhupRwZnMQckLPRYhSjf2/8JWQ882BauY9NyHxs5igpuQIXZDgfkaH3PoATg==} + + '@formatjs/intl-localematcher@0.5.5': + resolution: {integrity: sha512-t5tOGMgZ/i5+ALl2/offNqAQq/lfUnKLEw0mXQI4N4bqpedhrSE+fyKLpwnd22sK0dif6AV+ufQcTsKShB9J1g==} + '@humanwhocodes/config-array@0.13.0': resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} @@ -1066,6 +1084,9 @@ packages: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} + intl-messageformat@10.7.0: + resolution: {integrity: sha512-2P06M9jFTqJnEQzE072VGPjbAx6ZG1YysgopAwc8ui0ajSjtwX1MeQ6bXFXIzKcNENJTizKkcJIcZ0zlpl1zSg==} + is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -1313,6 +1334,16 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + next-intl@3.21.1: + resolution: {integrity: sha512-hQm4Wgq5i1lfOHAWmXBVl5d2/XAeddcjsrUmjotXEESzPSvW5j2t0Pr8AV8WorTILgqU748aXuenBhz5P78tdw==} + peerDependencies: + next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + next@14.2.15: resolution: {integrity: sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==} engines: {node: '>=18.17.0'} @@ -1786,6 +1817,11 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + use-intl@3.21.1: + resolution: {integrity: sha512-52kYgcydYkG9SX0ZZGt7W6WD2Va01hwe15bDgkXuaTdSxrF9fDu6hHTV5DxIuSmSSf/FEcBo/nodpw3ZhY31Lw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -2009,6 +2045,31 @@ snapshots: '@eslint/js@8.57.1': {} + '@formatjs/ecma402-abstract@2.2.0': + dependencies: + '@formatjs/fast-memoize': 2.2.1 + '@formatjs/intl-localematcher': 0.5.5 + tslib: 2.7.0 + + '@formatjs/fast-memoize@2.2.1': + dependencies: + tslib: 2.7.0 + + '@formatjs/icu-messageformat-parser@2.7.10': + dependencies: + '@formatjs/ecma402-abstract': 2.2.0 + '@formatjs/icu-skeleton-parser': 1.8.4 + tslib: 2.7.0 + + '@formatjs/icu-skeleton-parser@1.8.4': + dependencies: + '@formatjs/ecma402-abstract': 2.2.0 + tslib: 2.7.0 + + '@formatjs/intl-localematcher@0.5.5': + dependencies: + tslib: 2.7.0 + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -3103,6 +3164,13 @@ snapshots: hasown: 2.0.2 side-channel: 1.0.6 + intl-messageformat@10.7.0: + dependencies: + '@formatjs/ecma402-abstract': 2.2.0 + '@formatjs/fast-memoize': 2.2.1 + '@formatjs/icu-messageformat-parser': 2.7.10 + tslib: 2.7.0 + is-arguments@1.1.1: dependencies: call-bind: 1.0.7 @@ -3329,6 +3397,16 @@ snapshots: natural-compare@1.4.0: {} + negotiator@0.6.3: {} + + next-intl@3.21.1(next@14.2.15(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + dependencies: + '@formatjs/intl-localematcher': 0.5.5 + negotiator: 0.6.3 + next: 14.2.15(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + use-intl: 3.21.1(react@18.3.1) + next@14.2.15(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@next/env': 14.2.15 @@ -3861,6 +3939,12 @@ snapshots: dependencies: punycode: 2.3.1 + use-intl@3.21.1(react@18.3.1): + dependencies: + '@formatjs/fast-memoize': 2.2.1 + intl-messageformat: 10.7.0 + react: 18.3.1 + util-deprecate@1.0.2: {} which-boxed-primitive@1.0.2: diff --git a/public/home/qrcode.png b/public/home/qrcode.png new file mode 100644 index 0000000..193d73e Binary files /dev/null and b/public/home/qrcode.png differ diff --git a/public/home/submit_icon.png b/public/home/submit_icon.png new file mode 100644 index 0000000..e458770 Binary files /dev/null and b/public/home/submit_icon.png differ diff --git a/public/locales/en-US.json b/public/locales/en-US.json deleted file mode 100644 index 3c29ecf..0000000 --- a/public/locales/en-US.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "lan": "Chinese" -} \ No newline at end of file diff --git a/public/locales/en/common.json b/public/locales/en/common.json deleted file mode 100644 index e69de29..0000000 diff --git a/public/locales/zh-CN.json b/public/locales/zh-CN.json deleted file mode 100644 index 92a0d3a..0000000 --- a/public/locales/zh-CN.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "lan": "简体中文" -} \ No newline at end of file diff --git a/public/locales/zh-CN/common.json b/public/locales/zh-CN/common.json deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/[lang]/home/components/form.tsx b/src/app/[lang]/home/components/form.tsx new file mode 100644 index 0000000..3fb7eab --- /dev/null +++ b/src/app/[lang]/home/components/form.tsx @@ -0,0 +1,40 @@ +import Image from "next/image"; + + +export default function Form() { + return ( +
+ + +
+
提交
+ + +
+
+ ) +} \ No newline at end of file diff --git a/src/app/[lang]/home/page.tsx b/src/app/[lang]/home/page.tsx new file mode 100644 index 0000000..519154b --- /dev/null +++ b/src/app/[lang]/home/page.tsx @@ -0,0 +1,199 @@ +import Image from "next/image"; +import { getDictionary } from '@/dictionaries'; +import Form from "./components/form"; +import Header from "@/app/components/header"; +import Footer from "@/app/components/footer"; + +type CaseType = { + img: string +} +export type PropsType = { + params: { + lang: string; + }; +} +export default async function Home (props: PropsType) { + const lang = props.params.lang; + const dict = await getDictionary(lang); + const caseList: CaseType[] = [ + { img: '/home/case_1.png' }, + { img: '/home/case_2.png' }, + { img: '/home/case_3.png' }, + { img: '/home/case_3.png' }, + { img: '/home/case_1.png' }, + { img: '/home/case_2.png' }, + { img: '/home/case_3.png' }, + { img: '/home/case_3.png' }, + { img: '/home/case_1.png' }, + { img: '/home/case_2.png' }, + { img: '/home/case_3.png' }, + { img: '/home/case_3.png' }, + { img: '/home/case_1.png' }, + { img: '/home/case_2.png' }, + { img: '/home/case_3.png' }, + ] + return <> +
+
+
+
+
+
+ {dict.FocusingOnPlayableAds} +
+
+ {dict.goOverseas} +
+
+
+
+
+ +
+ { dict.customized } +
+
+
+ +
+ { dict.ABTesting} +
+
+ { dict.iterateGameplay } +
+
+
+ +
+ { dict.multiLanguage } +
+
+ { dict.breakingGeographical } +
+
+
+ +
+ { dict.allChannel } +
+
+ { dict.expandInfluence } +
+
+
+ +
+ { dict.lightweightDeployment } +
+
+ { dict.simplifyProcess } +
+
+ +
+
+
{ dict.caseGallery }
+
{ dict.clickNow }
+
+
+
+
+ { + caseList.map((item: CaseType, index: number) => { + return
+ +
+ }) + } +
+
{ dict.seeMore }
+
{ dict.contactUs! }
+
+
+
+
+
+
{ dict.contactUs }
+
+
+
+
+
+ 商务合作/求职:info@soyootech.com +
+
+
+
+
+ +} \ No newline at end of file diff --git a/src/app/components/footer.tsx b/src/app/components/footer.tsx new file mode 100644 index 0000000..f1fdf2b --- /dev/null +++ b/src/app/components/footer.tsx @@ -0,0 +1,39 @@ +import Image from "next/image" +export default function Footer() { + return ( + + ) +} \ No newline at end of file diff --git a/src/app/components/header.tsx b/src/app/components/header.tsx index 5ec6d86..ef7c5a2 100644 --- a/src/app/components/header.tsx +++ b/src/app/components/header.tsx @@ -1,24 +1,28 @@ +'use client' import Image from "next/image"; -import { useTranslation } from 'next-i18next'; +import Link from "next/link"; +import { useState } from "react"; type NavType = { name: string; href: string; } -function SplitButton() { - // const { t } = useTranslation(); - const lagn = '简体中文' +function SplitButton(props: {dict: Record, lang: string}) { + const { dict, lang } = props + const [show, setShow] = useState(false) return <> +
+ border-[1px] border-[#eeeeee] rounded-[3px] px-[10px] mt-[18px] cursor-pointer" + onClick={() => setShow(!show)}> logo -
{ lagn }
+
{ dict?.lang }
logo
+ { + show && ( + +
+
{dict?.lang1}
+
+ + ) + } +
} -export default function Header() { +export default function Header(props: {dict: Record, lang: string}) { + const { dict, lang } = props + const [activeTab, setActiveTab] = useState(dict.home) const navList: NavType[] = [ { - name: "首页", - href: "/" + name: dict.home, + href: "#home" }, { - name: "服务内容", - href: "/service" + name: dict.services, + href: "#service" }, { - name: "案例中心", - href: "/case" + name: dict.caseGallery, + href: "#case" }, { - name: "联系我们", - href: "/contact " + name: dict.contactUs, + href: "#contact " }, ] - const pathname = '首页' return (<>
{ navList.map((item: NavType) => ( -
-
{ item.name }
- { - pathname === item.name ? - : -
- } -
+ +
setActiveTab(item.name)}> +
{ item.name }
+ { + activeTab === item.name ? + : +
+ } +
+ )) }
- +
diff --git a/src/app/home/page.tsx b/src/app/home/page.tsx deleted file mode 100644 index 83481df..0000000 --- a/src/app/home/page.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import Image from "next/image"; - -type CaseType = { - img: string -} -export default function Home () { - const caseList: CaseType[] = [ - { img: '/home/case_1.png' }, - { img: '/home/case_2.png' }, - { img: '/home/case_3.png' }, - { img: '/home/case_3.png' }, - { img: '/home/case_1.png' }, - { img: '/home/case_2.png' }, - { img: '/home/case_3.png' }, - { img: '/home/case_3.png' }, - { img: '/home/case_1.png' }, - { img: '/home/case_2.png' }, - { img: '/home/case_3.png' }, - { img: '/home/case_3.png' }, - { img: '/home/case_1.png' }, - { img: '/home/case_2.png' }, - { img: '/home/case_3.png' }, - ] - return <> -
-
-
-
- 聚焦试玩广告 -
-
- 全面助力游戏出海 -
-
-
-
- -
- 100%内容定制,根据项目需求量身打造试玩广告方案 - 确保完全符合产品形象与市场定位 -
-
-
- -
- 支持 A/B 测试,通过优化素材内容 -
-
- 迭代游戏玩法,全面提升提升转化率与用户体验 -
-
-
- -
- 多语言支持,覆盖全球多种语言版本 -
-
- 打破地域限制,实现国际化布局 -
-
-
- -
- 全渠道适配,接入各大主流分发渠道 -
-
- 让您的产品触达更多潜在用户,扩大品牌影响力 -
-
-
- -
- 轻量化部署,提供便捷的产品效果预览方案 -
-
- 简化用户决策流程,方便追踪各阶段进度 -
-
-
-
案例中心
-
点击图标 立即体验
-
-
- { - caseList.map((item: CaseType) => { - return
- -
- }) - } -
-
想看更多?
-
联系我们!
-
- - -
-
-
联系我们
-
-
-
- -
-
-
- -} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 4db939b..976ebd8 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,10 +1,7 @@ import type { Metadata } from "next"; import localFont from "next/font/local"; import "./globals.css"; -import { appWithTranslation } from 'next-i18next' -import Header from "./components/header"; import { ReactElement, ReactNode } from "react"; -import { AppProps } from "next/app"; const geistSans = localFont({ src: "./fonts/GeistVF.woff", @@ -22,20 +19,15 @@ export const metadata: Metadata = { description: "Generated by create next app", }; -interface LayoutProps extends AppProps { - children: ReactNode; -} -function RootLayout({ children, ...appProps }: LayoutProps): ReactElement { +function RootLayout({ children }:{ children: ReactNode } ): ReactElement { return ( -
{children} ); } export default RootLayout -// export default appWithTranslation(RootLayout) diff --git a/src/dictionaries/en.json b/src/dictionaries/en.json new file mode 100644 index 0000000..2f3a22c --- /dev/null +++ b/src/dictionaries/en.json @@ -0,0 +1,23 @@ +{ + "lang": "English", + "lang1": "简体中文", + "home": "Home", + "services": "Services", + "caseGallery": "Case gallery", + "contactUs": "Contact Us", + "FocusingOnPlayableAds": "Focusing on playable ads", + "goOverseas": "comprehensively assisting the game to go overseas", + "customized": "100% customized , tailored to the needs of the project to create a playable ad Ensure full compliance with product image and market positioning", + "ABTesting": "Support A/B testing, by optimizing the material content", + "iterateGameplay": "Iterate gameplay to improve conversion rate and user experience", + "multiLanguage": "Multi-language support, covering the global multi-language version", + "breakingGeographical": "Breaking geographical restrictions and realizing internationalized layout", + "allChannel": "All-channel adaptation, access to major mainstream distribution channels", + "expandInfluence": "Let your products reach more potential users and expand your brand influence", + "lightweightDeployment": "Lightweight deployment, providing convenient product effect preview solutions", + "simplifyProcess": "Simplify the user decision-making process, easy to track the progress of each stage", + "clickNow": "Click on the icon to experience it now", + "seeMore": "Want to see more?", + "contactUs!": "Contact us!" + +} \ No newline at end of file diff --git a/src/dictionaries/index.ts b/src/dictionaries/index.ts new file mode 100644 index 0000000..5036757 --- /dev/null +++ b/src/dictionaries/index.ts @@ -0,0 +1,6 @@ +const dictionaries = { + en: () => import('./en.json').then((module) => module.default), + zh: () => import('./zh.json').then((module) => module.default), + } as Record Promise>>; + + export const getDictionary = async (locale: string) => dictionaries[locale](); \ No newline at end of file diff --git a/src/dictionaries/zh.json b/src/dictionaries/zh.json new file mode 100644 index 0000000..8741dfe --- /dev/null +++ b/src/dictionaries/zh.json @@ -0,0 +1,22 @@ +{ + "lang": "简体中文", + "lang1": "English", + "home": "首页", + "services": "服务内容", + "caseGallery": "案例中心", + "contactUs": "联系我们", + "FocusingOnPlayableAds": "聚焦试玩广告", + "goOverseas": "全面助力游戏出海", + "customized": "100%内容定制,根据项目需求量身打造试玩广告方案 确保完全符合产品形象与市场定位", + "ABTesting": "支持 A/B 测试,通过优化素材内容", + "iterateGameplay": "迭代游戏玩法,全面提升提升转化率与用户体验", + "multiLanguage": "多语言支持,覆盖全球多种语言版本", + "breakingGeographical": "打破地域限制,实现国际化布局", + "allChannel": "全渠道适配,接入各大主流分发渠道", + "expandInfluence": "让您的产品触达更多潜在用户,扩大品牌影响力", + "lightweightDeployment": "轻量化部署,提供便捷的产品效果预览方案", + "simplifyProcess": "简化用户决策流程,方便追踪各阶段进度", + "clickNow": "点击图标 立即体验", + "seeMore": "想看更多?", + "contactUs!": "联系我们!" +} \ No newline at end of file