@@ -17,13 +19,13 @@ export default function Home() {
- Start Sharing
+ {t("start-title")}
- Create a room and share your screen with others
+ {t("start-desc")}
-
+
@@ -32,14 +34,14 @@ export default function Home() {
- Join a Room
+ {t("join-title")}
- Enter a room code to view someone's screen
+ {t("join-desc")}
diff --git a/i18n/messages/en.json b/i18n/messages/en.json
new file mode 100644
index 0000000..7ffa347
--- /dev/null
+++ b/i18n/messages/en.json
@@ -0,0 +1,59 @@
+{
+ "Common": {
+ "title": "Screen Share - Share Your Screen Instantly",
+ "description": "Share your screen instantly with anyone using a simple room code. No downloads or sign-ups required.",
+ "keywords": "screen sharing, webrtc, online screen share, browser screen sharing, free screen sharing",
+ "footer": "Built by
Hin. The source code is available on
Github.",
+ "back-to-home": "Back to Home"
+ },
+ "Home": {
+ "header": "Share Your Screen Instantly",
+ "description": "Create a room, share the code, and start presenting to your audience in seconds.",
+ "start-title": "Start Sharing",
+ "start-desc": "Create a room and share your screen with others",
+ "create-room-btn": "Create Room",
+ "join-title": "Join a Room",
+ "join-desc": "Enter a room code to view someone's screen",
+ "join-room-btn": "Join Room"
+ },
+ "ShareOptions": {
+ "code-copied": "Room code copied!",
+ "code-copied-desc": "Share this code with others to let them join your room.",
+ "link-copied": "Shareable link copied!",
+ "link-copied-desc": "Share this link with others to let them join your room directly.",
+ "room-code": "Room Code",
+ "copy-code-btn": "Copy Code",
+ "generating-code": "Generating room code...",
+ "shareable-link": "Shareable Link",
+ "copy-link-btn": "Copy Link",
+ "generating-link": "Generating link..."
+ },
+ "HostPage": {
+ "title": "Your Screen Sharing Room",
+ "description": "Share your room code or link with others to let them view your screen. To share audio as well, ensure you're using Chrome or Edge, and select the option to share a tab.",
+ "current-viewers": "Current Viewers",
+ "stop-sharing": "Stop sharing",
+ "new-viewer": "New viewer connected",
+ "new-viewer-desc": "Click to start sharing your screen.",
+ "share-error": "Screen sharing error",
+ "share-error-desc": "Failed to start screen sharing. Please try again.",
+ "start-sharing": "Start Sharing",
+ "session-ended": "Session ended",
+ "session-ended-desc": "Your screen sharing session has been terminated."
+ },
+ "JoinPage": {
+ "title": "Join a Room",
+ "description": "Enter the room code to join and view the shared screen",
+ "enter-code": "Enter room code",
+ "join-room": "Join Room",
+ "connecting": "Connecting...",
+ "code-required": "Room code required",
+ "code-required-desc": "Please enter a valid room code.",
+ "connected": "Connected!",
+ "connected-desc": "Waiting for host to share their screen...",
+ "disconnected": "Disconnected",
+ "disconnected-desc": "The session has been ended.",
+ "connection-failed": "Connection failed",
+ "connection-failed-desc": "Could not connect to the room. Please check the room code and try again."
+ }
+}
diff --git a/i18n/messages/zh.json b/i18n/messages/zh.json
new file mode 100644
index 0000000..e797e9d
--- /dev/null
+++ b/i18n/messages/zh.json
@@ -0,0 +1,59 @@
+{
+ "Common": {
+ "title": "屏幕共享 - 立即共享您的屏幕",
+ "description": "使用简单的房间代码立即与任何人共享您的屏幕。无需下载或注册。",
+ "keywords": "屏幕共享, webrtc, 在线屏幕共享, 浏览器屏幕共享, 免费屏幕共享",
+ "footer": "由
Hin构建。源代码可在
Github上获得。",
+ "back-to-home": "返回首页"
+ },
+ "Home": {
+ "header": "立即共享您的屏幕",
+ "description": "创建一个房间,分享代码,几秒钟内开始向您的观众展示。",
+ "start-title": "开始共享",
+ "start-desc": "创建一个房间并与其他人共享您的屏幕",
+ "create-room-btn": "创建房间",
+ "join-title": "加入房间",
+ "join-desc": "输入房间代码以查看某人的屏幕",
+ "join-room-btn": "加入房间"
+ },
+ "ShareOptions": {
+ "code-copied": "房间代码已复制!",
+ "code-copied-desc": "与他人分享此代码,让他们加入您的房间。",
+ "link-copied": "可分享链接已复制!",
+ "link-copied-desc": "与他人分享此链接,让他们直接加入您的房间。",
+ "room-code": "房间代码",
+ "copy-code-btn": "复制代码",
+ "generating-code": "正在生成房间代码...",
+ "shareable-link": "可分享链接",
+ "copy-link-btn": "复制链接",
+ "generating-link": "正在生成链接..."
+ },
+ "HostPage": {
+ "title": "您的屏幕共享房间",
+ "description": "与他人分享您的房间代码或链接,让他们查看您的屏幕。要共享音频,请确保您使用的是Chrome或Edge,并选择共享标签页的选项。",
+ "current-viewers": "当前观众",
+ "stop-sharing": "停止共享",
+ "new-viewer": "新观众已连接",
+ "new-viewer-desc": "点击开始共享您的屏幕。",
+ "share-error": "屏幕共享错误",
+ "share-error-desc": "无法启动屏幕共享。请再试一次。",
+ "start-sharing": "开始共享",
+ "session-ended": "会话已结束",
+ "session-ended-desc": "您的屏幕共享会话已终止。"
+ },
+ "JoinPage": {
+ "title": "加入房间",
+ "description": "输入房间代码以加入并查看共享屏幕",
+ "enter-code": "输入房间代码",
+ "join-room": "加入房间",
+ "connecting": "连接中...",
+ "code-required": "需要房间代码",
+ "code-required-desc": "请输入有效的房间代码。",
+ "connected": "已连接!",
+ "connected-desc": "等待主持人共享他们的屏幕...",
+ "disconnected": "已断开连接",
+ "disconnected-desc": "会议已结束。",
+ "connection-failed": "连接失败",
+ "connection-failed-desc": "无法连接到房间。请检查房间代码并重试。"
+ }
+}
diff --git a/i18n/request.ts b/i18n/request.ts
new file mode 100644
index 0000000..f58043d
--- /dev/null
+++ b/i18n/request.ts
@@ -0,0 +1,22 @@
+import { getRequestConfig } from "next-intl/server";
+import { headers } from "next/headers";
+
+const LOCALES = ["en", "zh"];
+
+export default getRequestConfig(async () => {
+ // Provide a static locale, fetch a user setting,
+ // read locale from `cookies()`, `headers()`, etc.
+ // const locale = LOCALES.includes(navigator.language) ? navigator.language : "en";
+ // const locale = (await cookies()).get('locale')?.value || "en";
+ const locale =
+ (await headers())
+ .get("accept-language")
+ ?.split(",")
+ .map((l) => l.replace(/;q=[\.\d]+/, ""))
+ .find((lang) => LOCALES.includes(lang)) || "en";
+
+ return {
+ locale,
+ messages: (await import(`./messages/${locale}.json`)).default
+ };
+});
diff --git a/next.config.ts b/next.config.ts
index 518254b..1b806ca 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -1,11 +1,13 @@
import type { NextConfig } from "next";
+import createNextIntlPlugin from "next-intl/plugin";
+
+const withNextIntl = createNextIntlPlugin();
const nextConfig: NextConfig = {
- output: "export",
eslint: {
ignoreDuringBuilds: true
},
images: { unoptimized: true }
};
-export default nextConfig;
+export default withNextIntl(nextConfig);
diff --git a/package-lock.json b/package-lock.json
index 8e5cd46..788b0b6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
"clsx": "^2.1.1",
"lucide-react": "^0.462.0",
"next": "15.0.3",
+ "next-intl": "^3.26.0",
"peerjs": "^1.5.2",
"react": "19.0.0-rc-66855b96-20241106",
"react-dom": "19.0.0-rc-66855b96-20241106",
@@ -184,6 +185,56 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@formatjs/ecma402-abstract": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.2.4.tgz",
+ "integrity": "sha512-lFyiQDVvSbQOpU+WFd//ILolGj4UgA/qXrKeZxdV14uKiAUiPAtX6XAn7WBCRi7Mx6I7EybM9E5yYn4BIpZWYg==",
+ "license": "MIT",
+ "dependencies": {
+ "@formatjs/fast-memoize": "2.2.3",
+ "@formatjs/intl-localematcher": "0.5.8",
+ "tslib": "2"
+ }
+ },
+ "node_modules/@formatjs/fast-memoize": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.3.tgz",
+ "integrity": "sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "2"
+ }
+ },
+ "node_modules/@formatjs/icu-messageformat-parser": {
+ "version": "2.9.4",
+ "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.9.4.tgz",
+ "integrity": "sha512-Tbvp5a9IWuxUcpWNIW6GlMQYEc4rwNHR259uUFoKWNN1jM9obf9Ul0e+7r7MvFOBNcN+13K7NuKCKqQiAn1QEg==",
+ "license": "MIT",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.2.4",
+ "@formatjs/icu-skeleton-parser": "1.8.8",
+ "tslib": "2"
+ }
+ },
+ "node_modules/@formatjs/icu-skeleton-parser": {
+ "version": "1.8.8",
+ "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.8.tgz",
+ "integrity": "sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==",
+ "license": "MIT",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.2.4",
+ "tslib": "2"
+ }
+ },
+ "node_modules/@formatjs/intl-localematcher": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.8.tgz",
+ "integrity": "sha512-I+WDNWWJFZie+jkfkiK5Mp4hEDyRSEvmyfYadflOno/mmKJKcB17fEpEH0oJu/OWhhCJ8kJBDz2YMd/6cDl7Mg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "2"
+ }
+ },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -3789,6 +3840,18 @@
"node": ">= 0.4"
}
},
+ "node_modules/intl-messageformat": {
+ "version": "10.7.7",
+ "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.7.tgz",
+ "integrity": "sha512-F134jIoeYMro/3I0h08D0Yt4N9o9pjddU/4IIxMMURqbAtI2wu70X8hvG1V48W49zXHXv3RKSF/po+0fDfsGjA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.2.4",
+ "@formatjs/fast-memoize": "2.2.3",
+ "@formatjs/icu-messageformat-parser": "2.9.4",
+ "tslib": "2"
+ }
+ },
"node_modules/is-array-buffer": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
@@ -4835,6 +4898,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/negotiator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/next": {
"version": "15.0.3",
"resolved": "https://registry.npmjs.org/next/-/next-15.0.3.tgz",
@@ -4889,6 +4961,27 @@
}
}
},
+ "node_modules/next-intl": {
+ "version": "3.26.0",
+ "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-3.26.0.tgz",
+ "integrity": "sha512-gkamnHIANQzeW8xpTGRxd0xiOCztQhY8GDp79fgdlw0GioqrjTEfSWLhHkgaAtvHRbuh/ByJdwiEY5eNK9bUSQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/amannn"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@formatjs/intl-localematcher": "^0.5.4",
+ "negotiator": "^1.0.0",
+ "use-intl": "^3.26.0"
+ },
+ "peerDependencies": {
+ "next": "^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0"
+ }
+ },
"node_modules/next/node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
@@ -6699,6 +6792,19 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/use-intl": {
+ "version": "3.26.0",
+ "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-3.26.0.tgz",
+ "integrity": "sha512-HGXmpjGlbEv1uFZPfm557LK8p/hv0pKF9UwnrJeHUTxQx6bUGzMgpmPRLCVY3zkr7hfjy4LPwQJfk4Fhnn+dIg==",
+ "license": "MIT",
+ "dependencies": {
+ "@formatjs/fast-memoize": "^2.2.0",
+ "intl-messageformat": "^10.5.14"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
diff --git a/package.json b/package.json
index f4aec4e..c644ae4 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
"clsx": "^2.1.1",
"lucide-react": "^0.462.0",
"next": "15.0.3",
+ "next-intl": "^3.26.0",
"peerjs": "^1.5.2",
"react": "19.0.0-rc-66855b96-20241106",
"react-dom": "19.0.0-rc-66855b96-20241106",