From f78d9655d815456f92ad5fef17fefeaa82aade56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=8C=E3=81=BF?= Date: Sun, 29 Sep 2024 16:31:02 +0800 Subject: [PATCH] feat: add i18n --- .github/workflows/ninja_i18n.yml | 23 ++++ .vscode/extensions.json | 5 + messages/en.json | 49 ++++++++ messages/fr.json | 48 ++++++++ messages/ja.json | 51 +++++++++ messages/ko.json | 50 +++++++++ messages/zh-hans.json | 51 +++++++++ messages/zh-hant.json | 51 +++++++++ next.config.js | 9 +- package.json | 4 +- pnpm-lock.yaml | 184 +++++++++++++++++++++++++++++++ project.inlang/.gitignore | 1 + project.inlang/project_id | 1 + project.inlang/settings.json | 22 ++++ src/app/layout.tsx | 38 ++++--- src/components/theme-chooser.tsx | 9 +- src/lib/i18n.ts | 11 ++ src/middleware.ts | 24 ++++ 18 files changed, 610 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/ninja_i18n.yml create mode 100644 .vscode/extensions.json create mode 100644 messages/en.json create mode 100644 messages/fr.json create mode 100644 messages/ja.json create mode 100644 messages/ko.json create mode 100644 messages/zh-hans.json create mode 100644 messages/zh-hant.json create mode 100644 project.inlang/.gitignore create mode 100644 project.inlang/project_id create mode 100644 project.inlang/settings.json create mode 100644 src/lib/i18n.ts create mode 100644 src/middleware.ts diff --git a/.github/workflows/ninja_i18n.yml b/.github/workflows/ninja_i18n.yml new file mode 100644 index 0000000..c0ed059 --- /dev/null +++ b/.github/workflows/ninja_i18n.yml @@ -0,0 +1,23 @@ + +name: Ninja i18n action + +on: pull_request_target + +# explicitly configure permissions, in case your GITHUB_TOKEN workflow permissions are set to read-only in repository settings +permissions: + pull-requests: write # Necessary to comment on PRs + issues: read # Necessary to read issue comments + contents: read # Necessary to access the repo content + +jobs: + ninja-i18n: + name: Ninja i18n - GitHub Lint Action + runs-on: ubuntu-latest + + steps: + - name: Run Ninja i18n + # @main ensures that the latest version of the action is used + uses: opral/ninja-i18n-action@main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..116d685 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "inlang.vs-code-extension" + ] +} \ No newline at end of file diff --git a/messages/en.json b/messages/en.json new file mode 100644 index 0000000..51c2e7a --- /dev/null +++ b/messages/en.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format", + "language": "English", + "name": "poi", + "description": "Scalable KanColle browser and tool.", + "github": "GitHub", + "telegram": "Telegram", + "opencollective": "OpenCollective", + "weibo": "Weibo", + "download": "Download {{version}}", + "linuxX64": "Linux (x64)", + "linuxArm": "Linux (ARM)", + "linuxDebX64": "Debian / Ubuntu (x64)", + "linuxDebArm": "Debian / Ubuntu (ARM)", + "linuxRpmX64": "Fedora / CentOS (x64)", + "macosX64": "macOS (x64)", + "macosArm": "macOS (ARM)", + "winIa32": "Windows (x86) Portable", + "winIa32Setup": "Windows (x86)", + "winX64": "Windows (x64) Portable", + "winX64Setup": "Windows (x64)", + "winArm": "Windows (ARM)", + "stableHint": "Stable, for most users", + "betaHint": "Beta, for new features", + "otherVersions": "Check the complete list", + "telegramGroupLink": "https://t.me/joinchat/ENYTx0Cr6B9OxSCRKUzYUw", + "discordChannelLink": "https://discordapp.com/channels/118339803660943369/367575898313981952", + "discordSubChannel": "Discord", + "chooseAnotherPlatform": "Choose another platform", + "lsc": "Large Scale Constructing...", + "currentTheme": "Theme ", + "chibaheit": "Chibaheit", + "lilywhite": "Lilywhite", + "nowLoading": "Now Loading", + "stable": "Stable", + "beta": "Beta", + "others": "Others", + "hostedAt": "Hosted at {{site}}", + "oldVersions": "Old versions", + "windowsNightlies": "Windows nightlies", + "linuxAndMacOsNightlies": "Linux and macOS nightlies", + "sourceCode": "Source code", + "closeDialog": "Close dialog", + "errorMessage": "Ah, the webpage has become 🐢. We will fix it.", + "reload": "Reload", + "downloads": "Downloads", + "noContent": "We're working on it, please check later.", + "returnToHome": "Return to home" +} diff --git a/messages/fr.json b/messages/fr.json new file mode 100644 index 0000000..831b298 --- /dev/null +++ b/messages/fr.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format", + "language": "français", + "name": "poi", + "description": "Navigateur et outil évolutif pour KanColle", + "github": "GitHub", + "telegram": "Telegram", + "opencollective": "OpenCollective", + "weibo": "Weibo", + "download": "Téléchargez {{version}}", + "linuxX64": "Linux (x64)", + "linuxArm": "Linux (ARM)", + "linuxDebX64": "Debian / Ubuntu (x64)", + "linuxDebArm": "Debian / Ubuntu (ARM)", + "linuxRpmX64": "Fedora / CentOS (x64)", + "macosX64": "macOS (x64)", + "macosArm": "macOS (ARM)", + "winIa32": "Windows (x86) Portable", + "winIa32Setup": "Windows (x86)", + "winX64": "Windows (x64) Portable", + "winX64Setup": "Windows (x64)", + "winArm": "Windows (ARM)", + "stableHint": "Stable, pour la plupart des utilisateurs", + "betaHint": "Beta, pour les nouvelles fonctionalités", + "telegramGroupLink": "https://t.me/joinchat/ENYTx0Cr6B9OxSCRKUzYUw", + "discordChannelLink": "https://discordapp.com/channels/118339803660943369/367575898313981952", + "discordSubChannel": "Discord", + "chooseAnotherPlatform": "Choisissez une autre plateforme", + "lsc": "Construction à grande échelle...", + "currentTheme": "Thème ", + "chibaheit": "Chibaheit", + "lilywhite": "Lilywhite", + "nowLoading": "En cours de chargement", + "stable": "Stable", + "beta": "Beta", + "others": "Autres", + "hostedAt": "Hébergé sur {{site}}", + "oldVersions": "Anciennes versions", + "windowsNightlies": "Nightlies Windows", + "linuxAndMacOsNightlies": "Nightlies Linux et macOS", + "sourceCode": "Code source", + "closeDialog": "Fermer le dialogue", + "errorMessage": "Ah, la page Web est devenue 🐢. Nous allons le réparer.", + "reload": "Rechargez", + "downloads": "Téléchargements", + "noContent": "Nous y travaillons, veuillez vérifier plus tard.", + "returnToHome": "Retourner à l'accueil" +} diff --git a/messages/ja.json b/messages/ja.json new file mode 100644 index 0000000..7457263 --- /dev/null +++ b/messages/ja.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format", + "language": "日本語", + "name": "poi", + "description": "拡張可能な「艦隊これくしょん」ブラウザ", + "github": "GitHub", + "telegram": "Telegram", + "opencollective": "OpenCollective", + "weibo": "Weibo", + "download": "{{version}} をダウンロードする", + "linuxX64": "64 ビット Linux バージョン", + "linuxArm": "ARM Linux バージョン", + "linuxDebX64": "64 ビット Debian / Ubuntu バージョン", + "linuxDebArm": "ARM Debian / Ubuntu バージョン", + "linuxRpmX64": "64 ビット Fedora / CentOS バージョン", + "macosX64": "64 ビット macOS バージョン", + "macosArm": "ARM macOS バージョン", + "winIa32": "32 ビット Windows バージョン", + "winIa32Setup": "32 ビット Windows インストーラ", + "winX64": "64 ビット Windows バージョン", + "winX64Setup": "64 ビット Windows インストーラ", + "winArm": "ARM Windows バージョン", + "stableHint": "安定版・一般利用の方におすすめ", + "betaHint": "開発版・新機能が欲しい方におすすめ", + "otherVersions": "完全なリストを見る", + "telegramGroupLink": "https://t.me/joinchat/ENYTx0Cr6B9OxSCRKUzYUw", + "discordChannelLink": "https://discordapp.com/channels/118339803660943369/367575898313981952", + "discordSubChannel": "Discord チャンネル", + "chooseAnotherPlatform": "他のプラットフォームを選択", + "explore": "機能紹介", + "plugins": "プラグイン一覧", + "lsc": "大型建造中", + "currentTheme": "テーマ:", + "chibaheit": "チバハイト", + "lilywhite": "リリーホワイト", + "nowLoading": "少女祈祷中", + "stable": "安定版", + "beta": "開発版", + "others": "他", + "hostedAt": "{{site}} でホストされています", + "oldVersions": "古いバージョン", + "windowsNightlies": "Windows デイリービルド", + "linuxAndMacOsNightlies": "Linux と macOS デイリービルド", + "sourceCode": "ソースコード", + "closeDialog": "ダイアログを閉じる", + "errorMessage": "ああ、ウェブページは 🐢 になっています。 修正します。", + "reload": "再起動", + "downloads": "ダウンロード", + "noContent": "作業中です。後で確認してください。", + "returnToHome": "ホームに戻る" +} diff --git a/messages/ko.json b/messages/ko.json new file mode 100644 index 0000000..23b5cbb --- /dev/null +++ b/messages/ko.json @@ -0,0 +1,50 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format", + "language": "한국어", + "name": "poi", + "description": "확장 가능한 「함대 컬렉션」 브라우저", + "github": "GitHub", + "telegram": "Telegram", + "opencollective": "OpenCollective", + "weibo": "Weibo", + "download": "{{version}} 다운로드하기", + "linuxX64": "64비트 리눅스용", + "linuxArm": "ARM 리눅스용", + "linuxDebX64": "64비트 데비안/우분투용", + "linuxDebArm": "ARM 데비안/우분투용", + "linuxRpmX64": "64비트 페도라/CentOS용", + "macosX64": "64비트 macOS용", + "macosArm": "ARM macOS용", + "winIa32": "32비트 윈도우용 포터블 버전", + "winIa32Setup": "32비트 윈도우용", + "winX64": "64비트 윈도우용 포터블 버전", + "winX64Setup": "64비트 윈도우용", + "winArm": "ARM 윈도우용 포터블 버전", + "stableHint": "일반 사용자용 안정 버전", + "betaHint": "새로운 기능 맛보기용 베타 버전", + "otherVersions": "모든 버전 목록 보기", + "telegramGroupLink": "https://t.me/joinchat/ENYTx0Cr6B9OxSCRKUzYUw", + "discordChannelLink": "https://discordapp.com/channels/118339803660943369/367575898313981952", + "discordSubChannel": "디스코드 채널", + "chooseAnotherPlatform": "다른 플랫폼 고르기", + "explore": "소개", + "lsc": "대형함 건조 중...", + "currentTheme": "테마: ", + "chibaheit": "치바하이트", + "lilywhite": "릴리화이트", + "nowLoading": "로딩중", + "stable": "안정 버전", + "beta": "베타 버전", + "others": "기타", + "hostedAt": "{{site}}에서 호스팅 중", + "oldVersions": "오래된 버전", + "windowsNightlies": "윈도우 나이틀리 빌드", + "linuxAndMacOsNightlies": "리눅스와 맥OS 나이틀리 빌드", + "sourceCode": "소스코드", + "closeDialog": "창 닫기", + "errorMessage": "앗, 웹페이지가 🐢가 돼 버렸네요. 수복하겠습니다!", + "reload": "새로고침", + "downloads": "다운로드", + "noContent": "현재 공사 중입니다. 다음에 다시 방문해 주세요!", + "returnToHome": "홈으로 돌아가기" +} diff --git a/messages/zh-hans.json b/messages/zh-hans.json new file mode 100644 index 0000000..45e636b --- /dev/null +++ b/messages/zh-hans.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format", + "language": "简体中文", + "name": "poi", + "description": "可扩展的「舰队 Collection」浏览器", + "github": "GitHub", + "telegram": "Telegram", + "opencollective": "OpenCollective ", + "weibo": "新浪微博", + "download": "下载 {{version}}", + "linuxX64": "64 位 Linux 版", + "linuxArm": "ARM Linux 版", + "linuxDebX64": "64 位 Debian / Ubuntu 版", + "linuxDebArm": "ARM Debian / Ubuntu 版", + "linuxRpmX64": "64 位 Fedora / CentOS 版", + "macosX64": "64 位 macOS 版", + "macosArm": "ARM macOS 版", + "winIa32": "32 位 Windows 版", + "winIa32Setup": "32 位 Windows 安装包", + "winX64": "64 位 Windows 版", + "winX64Setup": "64 位 Windows 安装包", + "winArm": "ARM Windows 版", + "stableHint": "正式版,适合大部分人使用", + "betaHint": "测试版,包含最新的功能", + "otherVersions": "浏览完整列表", + "telegramGroupLink": "https://t.me/joinchat/ENYTx0Cr6B9OxSCRKUzYUw", + "discordChannelLink": "https://discordapp.com/channels/118339803660943369/367575898313981952", + "discordSubChannel": "Discord 频道", + "chooseAnotherPlatform": "选择其它平台", + "explore": "功能简介", + "plugins": "插件列表", + "lsc": "大型建造中", + "currentTheme": "主题:", + "chibaheit": "吃吧黑特", + "lilywhite": "莉莉白", + "nowLoading": "少女祈祷中", + "stable": "正式版", + "beta": "测试版", + "others": "其它", + "hostedAt": "托管于 {{site}}", + "oldVersions": "历史版本", + "windowsNightlies": "Windows 每夜构建", + "linuxAndMacOsNightlies": "Linux 与 macOS 每夜构建", + "sourceCode": "源代码", + "closeDialog": "关闭弹出框", + "errorMessage": "啊啦啦,网页变成了 🐢。我们会进行修复。", + "reload": "重新载入", + "downloads": "下载列表", + "noContent": "我们正在努力,请稍后再来。", + "returnToHome": "返回首页" +} diff --git a/messages/zh-hant.json b/messages/zh-hant.json new file mode 100644 index 0000000..f428a5e --- /dev/null +++ b/messages/zh-hant.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format", + "language": "繁體中文", + "name": "poi", + "description": "可擴展的「艦隊 Collection」瀏覽器", + "github": "GitHub", + "telegram": "Telegram", + "opencollective": "OpenCollective", + "weibo": "新浪微博", + "download": "下載 {{version}}", + "linuxX64": "64 位 Linux 版", + "linuxArm": "ARM Linux 版", + "linuxDebX64": "64 位 Debian / Ubuntu 版", + "linuxDebArm": "ARM Debian / Ubuntu 版", + "linuxRpmX64": "64 位 Fedora / CentOS 版", + "macosX64": "64 位 macOS 版", + "macosArm": "ARM macOS 版", + "winIa32": "32 位 Windows 版", + "winIa32Setup": "32 位 Windows 安裝包", + "winX64": "64 位 Windows 版", + "winX64Setup": "64 位 Windows 安裝包", + "winArm": "ARM Windows 版", + "stableHint": "正式版,適合大部分人使用", + "betaHint": "測試版,包含最新的功能", + "otherVersions": "瀏覽完整列表", + "telegramGroupLink": "https://t.me/joinchat/ENYTx0Cr6B9OxSCRKUzYUw", + "discordChannelLink": "https://discordapp.com/channels/118339803660943369/367575898313981952", + "discordSubChannel": "Discord 頻道", + "chooseAnotherPlatform": "選擇其它平臺", + "explore": "功能簡介", + "plugins": "擴展列表", + "lsc": "大型建造中", + "currentTheme": "主題:", + "chibaheit": "吃吧黑特", + "lilywhite": "莉莉白", + "nowLoading": "少女祈禱中", + "stable": "正式版", + "beta": "測試版", + "others": "其它", + "hostedAt": "託管於 {{site}}", + "oldVersions": "歷史版本", + "windowsNightlies": "Windows 每夜構建", + "linuxAndMacOsNightlies": "Linux 與 macOS 每夜構建", + "sourceCode": "源代碼", + "closeDialog": "關閉彈出框", + "errorMessage": "啊啦啦,網頁變成了 🐢。我們會進行修復。", + "reload": "重新載入", + "downloads": "下載列表", + "noContent": "我們正在努力,請稍後再來。", + "returnToHome": "回到首頁" +} diff --git a/next.config.js b/next.config.js index 1735ffe..2b069be 100644 --- a/next.config.js +++ b/next.config.js @@ -1,3 +1,4 @@ +import { paraglide } from '@inlang/paraglide-next/plugin' import { setupDevPlatform } from '@cloudflare/next-on-pages/next-dev' /** * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful @@ -22,4 +23,10 @@ if (process.env.NODE_ENV === 'development') { await setupDevPlatform() } -export default config +export default paraglide({ + paraglide: { + project: './project.inlang', + outdir: './src/paraglide', + }, + ...config, +}) diff --git a/package.json b/package.json index ce35eb2..05ce55f 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@cloudflare/next-on-pages": "^1.13.3", + "@inlang/paraglide-next": "0.5.2", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-navigation-menu": "^1.2.0", @@ -51,7 +52,8 @@ "prettier": "^3.3.3", "prettier-plugin-tailwindcss": "^0.6.5", "tailwindcss": "^3.4.3", - "typescript": "^5.5.3" + "typescript": "^5.5.3", + "@inlang/paraglide-js": "1.11.2" }, "ct3aMetadata": { "initVersion": "7.37.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d779ed2..be2432b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@cloudflare/next-on-pages': specifier: ^1.13.3 version: 1.13.3(@cloudflare/workers-types@4.20240925.0)(vercel@37.6.0)(wrangler@3.78.12(@cloudflare/workers-types@4.20240925.0)) + '@inlang/paraglide-next': + specifier: 0.5.2 + version: 0.5.2(next@14.2.13(@playwright/test@1.47.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) '@radix-ui/react-dropdown-menu': specifier: ^2.1.1 version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -75,6 +78,9 @@ importers: '@cloudflare/workers-types': specifier: ^4.20240925.0 version: 4.20240925.0 + '@inlang/paraglide-js': + specifier: 1.11.2 + version: 1.11.2 '@playwright/test': specifier: ^1.47.2 version: 1.47.2 @@ -420,6 +426,20 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead + '@inlang/detect-json-formatting@1.0.0': + resolution: {integrity: sha512-o0jeI8U4TgNlsPwI0y92jld8/18Loh2KEgHCYCJ42rCOdxFrA8R60cydlEd2/6jkdHFn5DxKj8rOyiKv3z9uOw==} + + '@inlang/paraglide-js@1.11.2': + resolution: {integrity: sha512-T9HCQO30Sq6L8tXQfdJI2CNMeNQxtMepJyoBYgK5QEN2LuIUqaoTfsZ2GryAqwFdAEj5FSM5Kdnf7f6shFqBHw==} + hasBin: true + + '@inlang/paraglide-next@0.5.2': + resolution: {integrity: sha512-ecX1VTNvgTH3o6/Ks228m+I65kOw1KUXWP7Oia38VgZmMEHLCQc8TEmP0Xfl/OpaCPXxQxyQ3qqODVbnSJX3pg==} + hasBin: true + peerDependencies: + next: ^13.0.0 || ^14.0.0 || ^15.0.0 + react: ^18 || ^19 + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1195,6 +1215,9 @@ packages: async-sema@3.1.1: resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -1203,6 +1226,9 @@ packages: resolution: {integrity: sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==} engines: {node: '>=4'} + axios@1.7.7: + resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -1313,10 +1339,18 @@ packages: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + commander@11.1.0: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -1328,6 +1362,10 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + engines: {node: ^14.18.0 || >=16.10.0} + console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} @@ -1402,6 +1440,14 @@ packages: supports-color: optional: true + dedent@1.5.1: + resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + deep-equal@2.2.3: resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} engines: {node: '>= 0.4'} @@ -1420,6 +1466,10 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} @@ -1969,6 +2019,15 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -1976,6 +2035,10 @@ packages: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + fs-extra@11.1.0: resolution: {integrity: sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==} engines: {node: '>=14.14'} @@ -2096,6 +2159,10 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + guess-json-indent@2.0.0: + resolution: {integrity: sha512-3Tm6R43KhtZWEVSHZnFmYMV9+gf3Vu0HXNNYtPVk2s7o8eGwYlJPHrjLtYw/7HBc10YxV+bfzKMuOf24z5qFng==} + engines: {node: '>=16.17.0'} + has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -2343,6 +2410,11 @@ packages: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} @@ -2430,6 +2502,14 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + mime@3.0.0: resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} engines: {node: '>=10.0.0'} @@ -2791,6 +2871,10 @@ packages: resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} + posthog-node@3.1.3: + resolution: {integrity: sha512-UaOOoWEUYTcaaDe1w0fgHW/sXvFr3RO0l7yI7RUDzkZNZCfwXNO9r3pc14d1EtNppF/SHBrV5hNiZZATpf/vUw==} + engines: {node: '>=15.0.0'} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2872,6 +2956,9 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} @@ -2879,6 +2966,10 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -3007,9 +3098,15 @@ packages: rollup-pluginutils@2.8.2: resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} + rsc-env@0.0.2: + resolution: {integrity: sha512-ixLbILtzlGEBl25ATa+jBwdKY6GgoN8XwFho+7ycVpCCJ9ijXlWQB0UnLGGU6aWtL+pTzlcaKI7W0xVQjnL5uA==} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rusha@0.8.14: + resolution: {integrity: sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==} + safe-array-concat@1.1.2: resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} engines: {node: '>=0.4'} @@ -3730,6 +3827,36 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@inlang/detect-json-formatting@1.0.0': + dependencies: + guess-json-indent: 2.0.0 + + '@inlang/paraglide-js@1.11.2': + dependencies: + '@inlang/detect-json-formatting': 1.0.0 + commander: 11.1.0 + consola: 3.2.3 + dedent: 1.5.1 + json5: 2.2.3 + posthog-node: 3.1.3 + transitivePeerDependencies: + - babel-plugin-macros + - debug + + '@inlang/paraglide-next@0.5.2(next@14.2.13(@playwright/test@1.47.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': + dependencies: + '@inlang/paraglide-js': 1.11.2 + commander: 12.1.0 + consola: 3.2.3 + glob: 10.4.5 + next: 14.2.13(@playwright/test@1.47.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + qs: 6.13.0 + react: 18.3.1 + rsc-env: 0.0.2 + transitivePeerDependencies: + - babel-plugin-macros + - debug + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -4611,12 +4738,22 @@ snapshots: async-sema@3.1.1: {} + asynckit@0.4.0: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 axe-core@4.10.0: {} + axios@1.7.7: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + axobject-query@4.1.0: {} balanced-match@1.0.2: {} @@ -4728,14 +4865,22 @@ snapshots: color-support@1.1.3: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + commander@11.1.0: {} + commander@12.1.0: {} + commander@4.1.1: {} comment-parser@1.4.1: {} concat-map@0.0.1: {} + consola@3.2.3: {} + console-control-strings@1.1.0: {} content-type@1.0.4: {} @@ -4790,6 +4935,8 @@ snapshots: dependencies: ms: 2.1.3 + dedent@1.5.1: {} + deep-equal@2.2.3: dependencies: array-buffer-byte-length: 1.0.1 @@ -4827,6 +4974,8 @@ snapshots: defu@6.1.4: {} + delayed-stream@1.0.0: {} + delegates@1.0.0: {} depd@1.1.2: {} @@ -5471,6 +5620,8 @@ snapshots: flatted@3.3.1: {} + follow-redirects@1.15.9: {} + for-each@0.3.3: dependencies: is-callable: 1.2.7 @@ -5480,6 +5631,12 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + fs-extra@11.1.0: dependencies: graceful-fs: 4.2.11 @@ -5622,6 +5779,8 @@ snapshots: graphemer@1.4.0: {} + guess-json-indent@2.0.0: {} + has-bigints@1.0.2: {} has-flag@4.0.0: {} @@ -5858,6 +6017,8 @@ snapshots: dependencies: minimist: 1.2.8 + json5@2.2.3: {} + jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 @@ -5943,6 +6104,12 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + mime@3.0.0: {} mimic-fn@2.1.0: {} @@ -6279,6 +6446,13 @@ snapshots: picocolors: 1.1.0 source-map-js: 1.2.1 + posthog-node@3.1.3: + dependencies: + axios: 1.7.7 + rusha: 0.8.14 + transitivePeerDependencies: + - debug + prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: @@ -6305,6 +6479,8 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 + proxy-from-env@1.1.0: {} + pump@3.0.2: dependencies: end-of-stream: 1.4.4 @@ -6312,6 +6488,10 @@ snapshots: punycode@2.3.1: {} + qs@6.13.0: + dependencies: + side-channel: 1.0.6 + queue-microtask@1.2.3: {} random@5.1.0: {} @@ -6444,10 +6624,14 @@ snapshots: dependencies: estree-walker: 0.6.1 + rsc-env@0.0.2: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 + rusha@0.8.14: {} + safe-array-concat@1.1.2: dependencies: call-bind: 1.0.7 diff --git a/project.inlang/.gitignore b/project.inlang/.gitignore new file mode 100644 index 0000000..5e46596 --- /dev/null +++ b/project.inlang/.gitignore @@ -0,0 +1 @@ +cache \ No newline at end of file diff --git a/project.inlang/project_id b/project.inlang/project_id new file mode 100644 index 0000000..76cd13f --- /dev/null +++ b/project.inlang/project_id @@ -0,0 +1 @@ +45e6514208ab6410e2847a37e7a30c287d1e83860e740c87b053efe61a39a5ec \ No newline at end of file diff --git a/project.inlang/settings.json b/project.inlang/settings.json new file mode 100644 index 0000000..0a70a97 --- /dev/null +++ b/project.inlang/settings.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://inlang.com/schema/project-settings", + "sourceLanguageTag": "ja", + "languageTags": [ + "zh-hans", + "zh-hant", + "en", + "ja", + "fr", + "ko" + ], + "modules": [ + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@latest/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@latest/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-without-source@latest/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@latest/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@latest/dist/index.js" + ], + "plugin.inlang.messageFormat": { + "pathPattern": "./messages/{languageTag}.json" + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9c0694e..7ebe1e0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,3 +1,5 @@ +import { LanguageProvider } from '@inlang/paraglide-next' +import { languageTag } from '~/paraglide/runtime.js' import '~/styles/globals.css' import { GeistSans } from 'geist/font/sans' @@ -16,22 +18,24 @@ export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode }>) { return ( - - - - - {children} - - - + + + + + + {children} + + + + ) } diff --git a/src/components/theme-chooser.tsx b/src/components/theme-chooser.tsx index a97e268..ccc5071 100644 --- a/src/components/theme-chooser.tsx +++ b/src/components/theme-chooser.tsx @@ -3,6 +3,7 @@ import { MoonIcon, SunIcon } from 'lucide-react' import { useTheme } from 'next-themes' +import * as m from '~/paraglide/messages.js' import { Button } from '~/components/ui/button' import { DropdownMenu, @@ -33,8 +34,12 @@ export const ThemeChooser = () => { - - + + {m.lilywhite()} + + + {m.chibaheit()} + 跟随系统 diff --git a/src/lib/i18n.ts b/src/lib/i18n.ts new file mode 100644 index 0000000..9a7c7c4 --- /dev/null +++ b/src/lib/i18n.ts @@ -0,0 +1,11 @@ +// file generated by the Paraglide-Next init command +import { PrefixStrategy, Navigation, Middleware } from '@inlang/paraglide-next' +import type { AvailableLanguageTag } from '~/paraglide/runtime' + +const strategy = PrefixStrategy({ + prefixDefault: 'always', +}) + +export const middleware = Middleware({ strategy }) +export const { Link, useRouter, usePathname, redirect, permanentRedirect } = + Navigation({ strategy }) diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 0000000..b194935 --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,24 @@ +// file generated by the Paraglide-Next init command +import { middleware as paraglide } from '~/lib/i18n' +import type { NextRequest } from 'next/server' + +export function middleware(request: NextRequest) { + // feel free to edit the request / response + // and chain in other middlewares + const response = paraglide(request) + return response +} + +export const config = { + runtime: 'experimental-edge', + matcher: [ + /* + * Match all request paths except for the ones starting with: + * - api (API routes) + * - _next/static (static files) + * - _next/image (image optimization files) + * - favicon.ico (favicon file) + */ + '/((?!api|_next/static|_next/image|favicon.ico).*)', + ], +}