diff --git a/astro.config.mjs b/astro.config.mjs
index 71b125f..e82d97b 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -6,7 +6,7 @@ import AstroPWA from '@vite-pwa/astro';
export default defineConfig({
i18n: {
defaultLocale: 'en',
- locales: ['en', 'zh'],
+ locales: ['en', 'zh-CN', 'zh-TW', 'ja'],
routing: {
prefixDefaultLocale: false,
},
diff --git a/src/components/LanguageSwitcher.astro b/src/components/LanguageSwitcher.astro
index fa1ebec..26a6379 100644
--- a/src/components/LanguageSwitcher.astro
+++ b/src/components/LanguageSwitcher.astro
@@ -1,27 +1,23 @@
---
import { getSupportedLangs, getTranslator } from '@/i18n/utils';
-import i18n from '@/i18n';
import { IoChevronDown } from 'react-icons/io5';
const { url } = Astro;
-// 使用 fallbackLng 作为回退值
-const currentLocale =
- Astro.currentLocale ||
- (Array.isArray(i18n.options.fallbackLng)
- ? i18n.options.fallbackLng[0]
- : i18n.options.fallbackLng) ||
- 'en';
+const defaultLocaleCode = 'en'; // 明确默认语言代码
+
+const currentLocale = Astro.currentLocale || defaultLocaleCode;
const t = await getTranslator(currentLocale);
-const supportedLangs = getSupportedLangs();
-const defaultLocaleCode = 'en';
+const supportedLangs = getSupportedLangs(); // 如 ['en', 'zh-CN-CN', 'zh-CN-TW', 'ja']
let basePath = url.pathname;
-const prefix = `/${currentLocale}`;
+const currentLangPrefix = `/${currentLocale}`;
-// 只有当当前语言不是硬编码的默认语言时,才需要尝试移除前缀
-if (currentLocale !== defaultLocaleCode && basePath.startsWith(prefix)) {
- basePath = basePath.substring(prefix.length) || '/';
+if (
+ currentLocale !== defaultLocaleCode &&
+ basePath.startsWith(currentLangPrefix)
+) {
+ basePath = basePath.substring(currentLangPrefix.length) || '/'; // 获取前缀后的部分,空则为根
}
if (basePath !== '/' && !basePath.startsWith('/')) {
basePath = '/' + basePath;
@@ -45,8 +41,9 @@ const currentLangName =
const isDefaultLang = langCode === defaultLocaleCode;
let targetPath = isDefaultLang ? basePath : `/${langCode}${basePath}`;
targetPath = targetPath.replace('//', '/');
- if (targetPath === '' && isDefaultLang) targetPath = '/';
- if (targetPath === '' && !isDefaultLang) targetPath = `/${langCode}`;
+ if (isDefaultLang && targetPath === '') targetPath = '/';
+ if (!isDefaultLang && targetPath === `/${langCode}/`)
+ targetPath = `/${langCode}`;
return (
@@ -124,6 +121,8 @@ const currentLangName =
.language-list {
position: absolute;
top: calc(100% + 4px);
+
+ /* 根据需要调整 left/right */
right: 0;
left: auto;
z-index: 60;
diff --git a/src/i18n.ts b/src/i18n.ts
index 5b76db5..041274b 100644
--- a/src/i18n.ts
+++ b/src/i18n.ts
@@ -2,22 +2,28 @@ import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import enTranslation from './locales/en/translation.json';
-import zhTranslation from './locales/zh/translation.json';
+import zh_CN_Translation from './locales/zh-CN/translation.json';
+import zh_TW_Translation from './locales/zh-TW/translation.json';
+import jaTranslation from './locales/ja/translation.json';
const resources = {
en: {
translation: enTranslation,
},
- zh: {
- translation: zhTranslation,
+ ja: {
+ translation: jaTranslation,
+ },
+ 'zh-CN': {
+ translation: zh_CN_Translation,
+ },
+ 'zh-TW': {
+ translation: zh_TW_Translation,
},
};
i18n.use(initReactI18next).init({
- debug: true,
fallbackLng: 'en',
interpolation: { escapeValue: false },
- lng: 'en',
missingKeyHandler: (lngs, ns, key, fallbackValue, updateMissing, options) => {
const resolvedLng = lngs && lngs.length > 0 ? lngs[0] : i18n.language;
const value = i18n.getResource(resolvedLng, ns || 'translation', key);
diff --git a/src/i18n/utils.ts b/src/i18n/utils.ts
index 76a68b1..d58821d 100644
--- a/src/i18n/utils.ts
+++ b/src/i18n/utils.ts
@@ -1,18 +1,10 @@
import i18n from '@/i18n';
import type { TFunction } from 'i18next';
-/**
- * 获取指定语言的翻译函数 (t function)。
- * 这个函数是异步的,以防 i18next 需要异步加载资源或切换语言。
- * @param lng - 语言代码 (例如 'en', 'zh')。如果未提供,则使用当前或回退语言。
- * @returns Promise - 返回一个解析为翻译函数的 Promise。
- */
export async function getTranslator(lng?: string): Promise {
const targetLng =
lng || i18n.language || (i18n.options.fallbackLng as string[])[0];
- // 如果 i18n 实例的当前语言与目标语言不一致,则切换语言
- // 注意:changeLanguage 是异步的
if (i18n.language !== targetLng) {
await i18n.changeLanguage(targetLng);
}
@@ -20,10 +12,6 @@ export async function getTranslator(lng?: string): Promise {
return i18n.t;
}
-/**
- * 获取当前支持的语言列表
- * @returns string[]
- */
export function getSupportedLangs(): string[] {
return Object.keys(i18n.options.resources || {});
}
diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json
index 14f45bb..95633e3 100644
--- a/src/locales/en/translation.json
+++ b/src/locales/en/translation.json
@@ -6,7 +6,9 @@
},
"languages": {
"en": "English",
- "zh": "简体中文"
+ "zh-CN": "简体中文",
+ "zh-TW": "繁體中文",
+ "ja": "日本語"
},
"common": {
"save": "Save",
diff --git a/src/locales/ja/translation.json b/src/locales/ja/translation.json
new file mode 100644
index 0000000..2f51ded
--- /dev/null
+++ b/src/locales/ja/translation.json
@@ -0,0 +1,360 @@
+{
+ "site": {
+ "title": "Moodist:集中とリラックスのための環境サウンド",
+ "description": "Moodistは、厳選された{{count}}種類のサウンドを備えた、無料のオープンソース環境サウンドジェネレーターです。この多機能ツールで、リラックス、集中、または創造性のための理想的な雰囲気を作りましょう。",
+ "ogSiteName": "Moodist"
+ },
+ "languages": {
+ "en": "English",
+ "zh-CN": "简体中文",
+ "zh-TW": "繁體中文",
+ "ja": "日本語"
+ },
+ "common": {
+ "save": "保存",
+ "untitled": "無題",
+ "copy": "コピー",
+ "copied": "コピーしました!",
+ "override": "上書き",
+ "done": "完了!",
+ "reset": "リセット",
+ "play": "再生",
+ "close": "閉じる",
+ "reload": "再読み込み",
+ "start": "開始",
+ "pause": "一時停止",
+ "stop": "停止",
+ "back": "戻る",
+ "restart": "再開",
+ "cancel": "キャンセル",
+ "delete": "削除",
+ "plural-suffix": ""
+ },
+ "hero": {
+ "logo-alt": "Moodist ロゴ",
+ "title-line1": "Moodist",
+ "title-line2": "集中とリラックスのための環境音",
+ "desc-prefix": "無料、そして",
+ "desc-open-source": "オープンソース",
+ "sounds-count": "{{count}} 種類のサウンド"
+ },
+ "about": {
+ "section1": {
+ "title": "無料の環境サウンド",
+ "body": "日々の喧騒から逃れて、心を落ち着かせたいですか?集中力を高めたり、安らかな眠りに誘う完璧なサウンドスケープが必要ですか?Moodistは、あなたのための無料オープンソース環境サウンドジェネレーターです!サブスクリプションや登録は不要。Moodistで、心地よく没入感のあるオーディオ体験の世界を完全に無料で解き放ちましょう。"
+ },
+ "section2": {
+ "title": "厳選されたサウンド",
+ "body": "厳選された{{count}}種類のサウンドの広範なライブラリに飛び込みましょう。自然愛好家は、小川の穏やかなせせらぎ、リズミカルな波の音、またはキャンプファイヤーのパチパチと燃える暖かさの中に安らぎを見つけるでしょう。カフェの柔らかなざわめき、電車の規則的なガタンゴトンという音、または交通の静かなホワイトノイズで、街の風景が生き生きと蘇ります。より深い集中やリラクゼーションを求める方のために、Moodistはあなたの心の状態を高めるように設計されたバイノーラルビートとカラーノイズを提供します。"
+ },
+ "section3": {
+ "title": "あなたのサウンドスケープを作成",
+ "body": "Moodistの魅力は、そのシンプルさとカスタマイズ性にあります。複雑なメニューや紛らわしいオプションはありません。希望のサウンドを選択し、音量バランスを調整して再生ボタンを押すだけです。鳥の優しいさえずりと心地よい雨音をブレンドしたいですか?問題ありません!好きなだけサウンドを重ねて、あなただけのサウンドスケープ・オアシスを作りましょう。"
+ },
+ "section4": {
+ "title": "あらゆる瞬間のためのサウンド",
+ "body": "長い一日の後にリラックスしたいとき、仕事中に集中力を高めたいとき、または安らかな眠りに就きたいとき、Moodistはあなたにぴったりのサウンドスケープを用意しています。そして何よりも素晴らしいのは、完全に無料でオープンソースであるため、何の制約もなくその利点を享受できることです。今日からMoodistを使い始めて、あなたの新しい静寂と集中の聖域を発見してください!"
+ }
+ },
+ "donate": {
+ "prompt": "Moodistをお楽しみですか?",
+ "link-text": "寄付でサポートをお願いします!",
+ "section-title": "プロジェクトを支援",
+ "section-desc": "Moodistを広告なしで無料に保つためにご協力ください。",
+ "section-button": "コーヒー代を寄付する"
+ },
+ "source": {
+ "title": "オープンソース",
+ "desc": "Moodistは無料でオープンソースです!"
+ },
+ "toolbar": {
+ "menu-aria-label": "メニュー",
+ "global-volume-label": "全体の音量",
+ "items": {
+ "presets": "プリセット",
+ "share": "サウンドを共有",
+ "shuffle": "サウンドをシャッフル",
+ "sleep-timer": "スリープタイマー",
+ "countdown": "カウントダウンタイマー",
+ "pomodoro": "ポモドーロタイマー",
+ "notepad": "メモ帳",
+ "todo": "ToDoリスト",
+ "breathing": "呼吸エクササイズ",
+ "binaural": "バイノーラルビート",
+ "isochronic": "アイソクロニックトーン",
+ "shortcuts": "ショートカット",
+ "buy-me-a-coffee": "コーヒーをおごる",
+ "source-code": "ソースコード"
+ }
+ },
+ "scroll-to-top": {
+ "aria-label": "トップへスクロール"
+ },
+ "unselect": {
+ "tooltip": "すべてのサウンドの選択を解除します。",
+ "aria-label": "すべてのサウンドの選択を解除",
+ "restore": {
+ "tooltip": "選択解除したサウンドを復元します。",
+ "aria-label": "選択解除したサウンドを復元"
+ }
+ },
+ "favorite": {
+ "add": {
+ "aria-label": "{{label}} サウンドをお気に入りに追加"
+ },
+ "remove": {
+ "aria-label": "{{label}} サウンドをお気に入りから削除"
+ }
+ },
+ "volume": {
+ "aria-label": "{{label}} サウンドの音量"
+ },
+ "play-error": "再生するサウンドを選択してください。",
+ "use-moodist": "Moodistを使う",
+ "modals": {
+ "presets": {
+ "title": "サウンドプリセット",
+ "your-presets-title": "マイプリセット",
+ "empty": "まだプリセットがありません。",
+ "new-preset-title": "新規プリセット",
+ "placeholder": "プリセット名",
+ "play-button-tooltip": "プリセットを再生",
+ "play-button-aria-label": "プリセット {{label}} を再生",
+ "delete-button-tooltip": "プリセットを削除",
+ "delete-button-aria-label": "プリセット {{label}} を削除",
+ "no-selected-warning": "プリセットを作成するには、まずいくつかのサウンドを選択してください。"
+ },
+ "share-link": {
+ "title": "サウンドセレクションを共有!",
+ "description": "以下のリンクをコピーして、共有したい相手に送ってください。",
+ "copy-button-aria-label": "リンクをコピー"
+ },
+ "shared": {
+ "title": "新しいサウンドミックスが検出されました!",
+ "description": "誰かが以下のミックスをあなたと共有しました。現在のセレクションを上書きしますか?",
+ "snackbar-message": "完了!新しいセレクションを再生できます。"
+ },
+ "sleep-timer": {
+ "title": "スリープタイマー",
+ "description": "一定時間後にサウンドを停止します。",
+ "hours-label": "時間",
+ "minutes-label": "分"
+ },
+ "countdown": {
+ "title": "カウントダウンタイマー",
+ "description": "シンプルなカウントダウンタイマーです。",
+ "placeholder-hh": "時",
+ "placeholder-mm": "分",
+ "placeholder-ss": "秒"
+ },
+ "pomodoro": {
+ "title": "ポモドーロタイマー",
+ "settings-tooltip": "時間を変更",
+ "completed": "{{count}} 回完了",
+ "tabs": {
+ "pomodoro": "作業",
+ "short-break": "短い休憩",
+ "long-break": "長い休憩"
+ },
+ "settings": {
+ "title": "時間を変更",
+ "pomodoro-label": "作業時間",
+ "short-break-label": "短い休憩時間",
+ "long-break-label": "長い休憩時間",
+ "minutes-unit": "分"
+ }
+ },
+ "notepad": {
+ "title-label": "メモ帳",
+ "copy-tooltip": "メモをコピー",
+ "download-tooltip": "メモをダウンロード",
+ "clear-tooltip": "メモをクリア",
+ "restore-tooltip": "メモを復元",
+ "placeholder": "考え事を書き留めましょう...",
+ "counter-stats": "{{chars}} 文字 • {{words}} 単語"
+ },
+ "todo": {
+ "title": "ToDoリスト",
+ "description": "シンプルなToDoリストです。",
+ "add-placeholder": "やることを入力...",
+ "add-button": "追加",
+ "your-todos-label": "あなたのToDo",
+ "empty": "ToDoはまだありません。",
+ "delete-button-aria-label": "ToDoを削除"
+ },
+ "breathing": {
+ "title": "呼吸エクササイズ",
+ "phases": {
+ "inhale": "吸って",
+ "exhale": "吐いて",
+ "hold": "止めて"
+ },
+ "exercises": {
+ "box": "ボックス呼吸法",
+ "resonant": "レゾナント呼吸法",
+ "478": "4-7-8呼吸法"
+ }
+ },
+ "generators": {
+ "presets-label": "プリセット:",
+ "base-frequency-label": "基本周波数 (Hz):",
+ "volume-label": "音量:",
+ "presets": {
+ "delta": "デルタ波 (深い睡眠) 2 Hz",
+ "theta": "シータ波 (瞑想) 5 Hz",
+ "alpha": "アルファ波 (リラックス) 10 Hz",
+ "beta": "ベータ波 (集中) 20 Hz",
+ "gamma": "ガンマ波 (認知) 40 Hz",
+ "custom": "カスタム"
+ }
+ },
+ "binaural": {
+ "title": "バイノーラルビート",
+ "description": "バイノーラルビートジェネレーター。",
+ "beat-frequency-label": "ビート周波数 (Hz):"
+ },
+ "isochronic": {
+ "title": "アイソクロニックトーン",
+ "description": "アイソクロニックトーンジェネレーター。",
+ "tone-frequency-label": "トーン周波数 (Hz):"
+ },
+ "shortcuts": {
+ "title": "キーボードショートカット",
+ "labels": {
+ "toggle-play": "再生/一時停止 切り替え",
+ "unselect-all": "全サウンドの選択を解除"
+ }
+ },
+ "reload": {
+ "title": "新しいコンテンツが利用可能です",
+ "description": "新しいコンテンツが利用可能です。更新するには再読み込みボタンをクリックしてください。",
+ "closeButton": "閉じる",
+ "reloadButton": "再読み込み"
+ }
+ },
+ "sounds": {
+ "show-less": "少なく表示",
+ "show-more": "もっと表示",
+ "aria-label": "{{name}} サウンド",
+ "favorites": {
+ "title": "お気に入り"
+ },
+ "animals": {
+ "title": "動物",
+ "birds": "鳥のさえずり",
+ "seagulls": "カモメ",
+ "crickets": "コオロギ",
+ "wolf": "オオカミの遠吠え",
+ "owl": "フクロウ",
+ "frog": "カエル",
+ "dog-barking": "犬の吠え声",
+ "horse-galopp": "馬のギャロップ",
+ "cat-purring": "猫のゴロゴロ",
+ "crows": "カラス",
+ "whale": "クジラ",
+ "beehive": "ミツバチの巣",
+ "woodpecker": "キツツキ",
+ "chickens": "ニワトリ",
+ "cows": "牛",
+ "sheep": "羊"
+ },
+ "binaural": {
+ "title": "バイノーラル",
+ "binaural-delta": "デルタ波 (深い睡眠)",
+ "binaural-theta": "シータ波 (瞑想)",
+ "binaural-alpha": "アルファ波 (リラックス)",
+ "binaural-beta": "ベータ波 (集中)",
+ "binaural-gamma": "ガンマ波 (認知)"
+ },
+ "nature": {
+ "title": "自然",
+ "river": "川",
+ "waves": "波",
+ "campfire": "キャンプファイヤー",
+ "wind": "風",
+ "howling-wind": "風のうなり",
+ "wind-in-trees": "木々の間の風",
+ "waterfall": "滝",
+ "walk-in-snow": "雪の上を歩く",
+ "walk-on-leaves": "落ち葉の上を歩く",
+ "walk-on-gravel": "砂利の上を歩く",
+ "droplets": "水滴",
+ "jungle": "ジャングル"
+ },
+ "noise": {
+ "title": "ノイズ",
+ "white-noise": "ホワイトノイズ",
+ "pink-noise": "ピンクノイズ",
+ "brown-noise": "ブラウンノイズ"
+ },
+ "places": {
+ "title": "場所",
+ "cafe": "カフェ",
+ "airport": "空港",
+ "church": "教会",
+ "temple": "寺院",
+ "construction-site": "建設現場",
+ "underwater": "水中",
+ "crowded-bar": "混雑したバー",
+ "night-village": "夜の村",
+ "subway-station": "地下鉄の駅",
+ "office": "オフィス",
+ "supermarket": "スーパーマーケット",
+ "carousel": "メリーゴーランド",
+ "laboratory": "研究室",
+ "laundry-room": "ランドリールーム",
+ "restaurant": "レストラン",
+ "library": "図書館"
+ },
+ "rain": {
+ "title": "雨",
+ "light-rain": "小雨",
+ "heavy-rain": "大雨",
+ "thunder": "雷",
+ "rain-on-window": "窓に当たる雨",
+ "rain-on-car-roof": "車の屋根に当たる雨",
+ "rain-on-umbrella": "傘に当たる雨",
+ "rain-on-tent": "テントに当たる雨",
+ "rain-on-leaves": "葉に当たる雨"
+ },
+ "things": {
+ "title": "物",
+ "keyboard": "キーボード",
+ "typewriter": "タイプライター",
+ "paper": "紙",
+ "clock": "時計",
+ "wind-chimes": "風鈴",
+ "singing-bowl": "シンギングボウル",
+ "ceiling-fan": "シーリングファン",
+ "dryer": "乾燥機",
+ "slide-projector": "スライドプロジェクター",
+ "boiling-water": "沸騰したお湯",
+ "bubbles": "泡",
+ "tuning-radio": "ラジオのチューニング",
+ "morse-code": "モールス信号",
+ "washing-machine": "洗濯機",
+ "vinyl-effect": "レコードノイズ",
+ "windshield-wipers": "ワイパー"
+ },
+ "transport": {
+ "title": "乗り物",
+ "train": "電車",
+ "inside-a-train": "電車の中",
+ "airplane": "飛行機",
+ "submarine": "潜水艦",
+ "sailboat": "帆船",
+ "rowing-boat": "手漕ぎボート"
+ },
+ "urban": {
+ "title": "都市",
+ "highway": "高速道路",
+ "road": "道路",
+ "ambulance-siren": "救急車のサイレン",
+ "busy-street": "賑やかな通り",
+ "crowd": "人混み",
+ "traffic": "交通",
+ "fireworks": "花火"
+ }
+ },
+ "created-by": "{{authorLink}} によって作成されました"
+}
diff --git a/src/locales/zh/translation.json b/src/locales/zh-CN/translation.json
similarity index 99%
rename from src/locales/zh/translation.json
rename to src/locales/zh-CN/translation.json
index fd16a4a..c468097 100644
--- a/src/locales/zh/translation.json
+++ b/src/locales/zh-CN/translation.json
@@ -6,7 +6,9 @@
},
"languages": {
"en": "English",
- "zh": "简体中文"
+ "zh-CN": "简体中文",
+ "zh-TW": "繁體中文",
+ "ja": "日本語"
},
"common": {
"save": "保存",
diff --git a/src/locales/zh-TW/translation.json b/src/locales/zh-TW/translation.json
new file mode 100644
index 0000000..a1c7339
--- /dev/null
+++ b/src/locales/zh-TW/translation.json
@@ -0,0 +1,360 @@
+{
+ "site": {
+ "title": "Moodist:營造專注與平靜的環境之聲",
+ "description": "Moodist 是一款免費且開源的環境聲音產生器,收錄了 {{count}} 種精心挑選的聲音。用這款多功能工具為放鬆、專注或激發創造力打造理想氛圍。",
+ "ogSiteName": "Moodist"
+ },
+ "languages": {
+ "en": "English",
+ "zh-CN": "简体中文",
+ "zh-TW": "繁體中文",
+ "ja": "日本語"
+ },
+ "common": {
+ "save": "儲存",
+ "untitled": "未命名",
+ "copy": "複製",
+ "copied": "已複製!",
+ "override": "覆蓋",
+ "done": "完成!",
+ "reset": "重設",
+ "play": "播放",
+ "close": "關閉",
+ "reload": "重新載入",
+ "start": "開始",
+ "pause": "暫停",
+ "stop": "停止",
+ "back": "返回",
+ "restart": "重新開始",
+ "cancel": "取消",
+ "delete": "刪除",
+ "plural-suffix": ""
+ },
+ "hero": {
+ "logo-alt": "Moodist 標誌",
+ "title-line1": "Moodist",
+ "title-line2": "專注與平靜的環境之聲",
+ "desc-prefix": "免費且",
+ "desc-open-source": "完全開源",
+ "sounds-count": "{{count}} 種聲音"
+ },
+ "about": {
+ "section1": {
+ "title": "免費環境聲音",
+ "body": "渴望逃離日常喧囂,尋覓片刻寧靜?需要理想的聲音環境來提升專注力,或是安然入睡?不妨試試 Moodist——您的免費開源環境聲音產生器!無需訂閱註冊,即可免費解鎖一個舒緩、沉浸式的音訊世界。"
+ },
+ "section2": {
+ "title": "精選環境聲音",
+ "body": "探索包含 {{count}} 種精心挑選聲音的豐富音庫。自然愛好者們可以在潺潺溪流、規律的海浪拍岸,或是劈啪作響的溫暖營火中尋得慰藉;城市景觀則透過咖啡館的輕柔低語、火車有節奏的行進聲,或是平和的交通白噪音生動再現。對於尋求更深層次專注或放鬆的使用者,Moodist 還提供了旨在幫助調整心境的雙耳節拍和彩色噪音。"
+ },
+ "section3": {
+ "title": "打造您的專屬音景",
+ "body": "Moodist 的魅力在於其簡潔與個人化。沒有複雜的選單或令人困惑的選項——只需選擇心儀的聲音,調整音量平衡,即可播放。想將鳥兒的輕柔啁啾與舒緩的雨聲混合?沒問題!隨心疊加任意數量的聲音,創造您的專屬聲音綠洲。"
+ },
+ "section4": {
+ "title": "滿足不同時刻的需求",
+ "body": "無論您是想在漫長一天後放鬆身心,在工作學習時集中注意力,還是需要安寧的氛圍助您入睡,Moodist 都有適合您的理想音景。最棒的是,它完全免費且開源,讓您可以無任何負擔地享受。立即開始使用 Moodist,發現屬於您的寧靜與專注空間!"
+ }
+ },
+ "donate": {
+ "prompt": "喜歡 Moodist 嗎?",
+ "link-text": "透過贊助支持我們!",
+ "section-title": "支持專案",
+ "section-desc": "幫助 Moodist 保持免費和無廣告。",
+ "section-button": "贊助一杯咖啡"
+ },
+ "source": {
+ "title": "開源",
+ "desc": "Moodist 是免費且開源的!"
+ },
+ "toolbar": {
+ "menu-aria-label": "選單",
+ "global-volume-label": "全域音量",
+ "items": {
+ "presets": "預設",
+ "share": "分享聲音",
+ "shuffle": "隨機組合",
+ "sleep-timer": "睡眠定時器",
+ "countdown": "倒數計時器",
+ "pomodoro": "番茄工作法",
+ "notepad": "記事簿",
+ "todo": "待辦清單",
+ "breathing": "呼吸練習",
+ "binaural": "雙耳節拍",
+ "isochronic": "等時聲頻",
+ "shortcuts": "快速鍵",
+ "buy-me-a-coffee": "請我喝杯咖啡",
+ "source-code": "原始碼"
+ }
+ },
+ "scroll-to-top": {
+ "aria-label": "捲動到頂部"
+ },
+ "unselect": {
+ "tooltip": "取消選擇所有聲音。",
+ "aria-label": "取消選擇所有聲音",
+ "restore": {
+ "tooltip": "還原上次的選擇。",
+ "aria-label": "還原上次的選擇"
+ }
+ },
+ "favorite": {
+ "add": {
+ "aria-label": "收藏 {{label}} 聲音"
+ },
+ "remove": {
+ "aria-label": "取消收藏 {{label}} 聲音"
+ }
+ },
+ "volume": {
+ "aria-label": "{{label}} 聲音音量"
+ },
+ "play-error": "請先選擇要播放的聲音。",
+ "use-moodist": "開始使用 Moodist",
+ "modals": {
+ "presets": {
+ "title": "聲音預設",
+ "your-presets-title": "我的預設",
+ "empty": "您還沒有儲存任何預設。",
+ "new-preset-title": "新增預設",
+ "placeholder": "預設名稱",
+ "play-button-tooltip": "播放預設",
+ "play-button-aria-label": "播放預設 {{label}}",
+ "delete-button-tooltip": "刪除預設",
+ "delete-button-aria-label": "刪除預設 {{label}}",
+ "no-selected-warning": "請先選擇聲音,再建立預設。"
+ },
+ "share-link": {
+ "title": "分享您的聲音組合",
+ "description": "複製下方連結,分享給他人。",
+ "copy-button-aria-label": "複製連結"
+ },
+ "shared": {
+ "title": "偵測到分享的聲音組合!",
+ "description": "有人向您分享了以下聲音組合,是否覆蓋目前選擇?",
+ "snackbar-message": "載入成功!現在可以播放分享的組合了。"
+ },
+ "sleep-timer": {
+ "title": "睡眠定時器",
+ "description": "在設定的時間後自動停止播放聲音。",
+ "hours-label": "小時",
+ "minutes-label": "分鐘"
+ },
+ "countdown": {
+ "title": "倒數計時器",
+ "description": "簡潔實用的倒數計時器。",
+ "placeholder-hh": "時",
+ "placeholder-mm": "分",
+ "placeholder-ss": "秒"
+ },
+ "pomodoro": {
+ "title": "番茄工作法",
+ "settings-tooltip": "設定時長",
+ "completed": "已完成 {{count}} 個番茄鐘",
+ "tabs": {
+ "pomodoro": "工作",
+ "short-break": "短休息",
+ "long-break": "長休息"
+ },
+ "settings": {
+ "title": "設定時長",
+ "pomodoro-label": "工作時長",
+ "short-break-label": "短休息時長",
+ "long-break-label": "長休息時長",
+ "minutes-unit": "分鐘"
+ }
+ },
+ "notepad": {
+ "title-label": "隨手記",
+ "copy-tooltip": "複製筆記",
+ "download-tooltip": "下載筆記",
+ "clear-tooltip": "清空筆記",
+ "restore-tooltip": "還原筆記",
+ "placeholder": "記錄您的想法...",
+ "counter-stats": "{{chars}} 個字元 • {{words}} 個詞語"
+ },
+ "todo": {
+ "title": "待辦清單",
+ "description": "簡潔實用的待辦事項列表。",
+ "add-placeholder": "新增待辦事項...",
+ "add-button": "新增",
+ "your-todos-label": "我的待辦",
+ "empty": "這裡還沒有待辦事項。",
+ "delete-button-aria-label": "刪除此待辦事項"
+ },
+ "breathing": {
+ "title": "呼吸練習",
+ "phases": {
+ "inhale": "吸氣",
+ "exhale": "吐氣",
+ "hold": "屏息"
+ },
+ "exercises": {
+ "box": "方形呼吸法",
+ "resonant": "同步呼吸法",
+ "478": "4-7-8 呼吸法"
+ }
+ },
+ "generators": {
+ "presets-label": "預設:",
+ "base-frequency-label": "基礎頻率 (Hz):",
+ "volume-label": "音量:",
+ "presets": {
+ "delta": "Delta 波 (深度睡眠) 2 Hz",
+ "theta": "Theta 波 (冥想) 5 Hz",
+ "alpha": "Alpha 波 (放鬆) 10 Hz",
+ "beta": "Beta 波 (專注) 20 Hz",
+ "gamma": "Gamma 波 (認知) 40 Hz",
+ "custom": "自訂"
+ }
+ },
+ "binaural": {
+ "title": "雙耳節拍",
+ "description": "產生雙耳節拍聲音。",
+ "beat-frequency-label": "節拍頻率 (Hz):"
+ },
+ "isochronic": {
+ "title": "等時聲頻",
+ "description": "產生等時聲頻聲音。",
+ "tone-frequency-label": "聲頻頻率 (Hz):"
+ },
+ "shortcuts": {
+ "title": "鍵盤快速鍵",
+ "labels": {
+ "toggle-play": "播放/暫停",
+ "unselect-all": "取消全選聲音"
+ }
+ },
+ "reload": {
+ "title": "有新的更新可用",
+ "description": "偵測到新版本,點擊「重新載入」按鈕以更新。",
+ "closeButton": "關閉",
+ "reloadButton": "重新載入"
+ }
+ },
+ "sounds": {
+ "show-less": "收合",
+ "show-more": "展開更多",
+ "aria-label": "{{name}} 聲音",
+ "favorites": {
+ "title": "我的收藏"
+ },
+ "animals": {
+ "title": "動物",
+ "birds": "鳥鳴",
+ "seagulls": "海鷗",
+ "crickets": "蟋蟀",
+ "wolf": "狼嚎",
+ "owl": "貓頭鷹",
+ "frog": "蛙鳴",
+ "dog-barking": "狗吠",
+ "horse-galopp": "馬蹄聲",
+ "cat-purring": "貓呼嚕聲",
+ "crows": "烏鴉",
+ "whale": "鯨魚",
+ "beehive": "蜂巢",
+ "woodpecker": "啄木鳥",
+ "chickens": "雞鳴",
+ "cows": "牛叫",
+ "sheep": "羊叫"
+ },
+ "binaural": {
+ "title": "腦波",
+ "binaural-delta": "Delta 波 (深度睡眠)",
+ "binaural-theta": "Theta 波 (冥想)",
+ "binaural-alpha": "Alpha 波 (放鬆)",
+ "binaural-beta": "Beta 波 (專注)",
+ "binaural-gamma": "Gamma 波 (認知)"
+ },
+ "nature": {
+ "title": "自然",
+ "river": "河流",
+ "waves": "海浪",
+ "campfire": "營火",
+ "wind": "風聲",
+ "howling-wind": "風嘯聲",
+ "wind-in-trees": "林間風聲",
+ "waterfall": "瀑布",
+ "walk-in-snow": "雪地腳步",
+ "walk-on-leaves": "落葉腳步",
+ "walk-on-gravel": "碎石腳步",
+ "droplets": "水滴",
+ "jungle": "叢林聲"
+ },
+ "noise": {
+ "title": "噪音",
+ "white-noise": "白噪音",
+ "pink-noise": "粉紅噪音",
+ "brown-noise": "布朗噪音"
+ },
+ "places": {
+ "title": "場所",
+ "cafe": "咖啡館",
+ "airport": "機場",
+ "church": "教堂",
+ "temple": "寺廟",
+ "construction-site": "建築工地",
+ "underwater": "水下",
+ "crowded-bar": "嘈雜酒吧",
+ "night-village": "鄉村夜晚",
+ "subway-station": "地鐵站",
+ "office": "辦公室",
+ "supermarket": "超級市場",
+ "carousel": "旋轉木馬",
+ "laboratory": "實驗室",
+ "laundry-room": "洗衣間",
+ "restaurant": "餐廳",
+ "library": "圖書館"
+ },
+ "rain": {
+ "title": "雨聲",
+ "light-rain": "小雨",
+ "heavy-rain": "大雨",
+ "thunder": "雷聲",
+ "rain-on-window": "雨打窗戶",
+ "rain-on-car-roof": "雨打車頂",
+ "rain-on-umbrella": "雨打雨傘",
+ "rain-on-tent": "雨打帳篷",
+ "rain-on-leaves": "雨打樹葉"
+ },
+ "things": {
+ "title": "物品",
+ "keyboard": "鍵盤聲",
+ "typewriter": "打字機聲",
+ "paper": "紙張翻動",
+ "clock": "時鐘滴答",
+ "wind-chimes": "風鈴",
+ "singing-bowl": "頌缽",
+ "ceiling-fan": "吊扇",
+ "dryer": "烘乾機",
+ "slide-projector": "幻燈機",
+ "boiling-water": "沸水",
+ "bubbles": "氣泡",
+ "tuning-radio": "收音機調頻",
+ "morse-code": "摩斯電碼",
+ "washing-machine": "洗衣機",
+ "vinyl-effect": "黑膠唱片噪音",
+ "windshield-wipers": "雨刷"
+ },
+ "transport": {
+ "title": "交通",
+ "train": "火車聲",
+ "inside-a-train": "車廂內",
+ "airplane": "飛機聲",
+ "submarine": "潛艇聲",
+ "sailboat": "帆船航行",
+ "rowing-boat": "划艇聲"
+ },
+ "urban": {
+ "title": "城市",
+ "highway": "高速公路",
+ "road": "街道",
+ "ambulance-siren": "救護車警笛",
+ "busy-street": "繁忙街道",
+ "crowd": "人群嘈雜",
+ "traffic": "交通噪音",
+ "fireworks": "煙火"
+ }
+ },
+ "created-by": "由 {{authorLink}} 建立"
+}
diff --git a/src/pages/zh/index.astro b/src/pages/ja/index.astro
similarity index 100%
rename from src/pages/zh/index.astro
rename to src/pages/ja/index.astro
diff --git a/src/pages/zh-CN/index.astro b/src/pages/zh-CN/index.astro
new file mode 100644
index 0000000..821c8bc
--- /dev/null
+++ b/src/pages/zh-CN/index.astro
@@ -0,0 +1,20 @@
+---
+import Layout from '@/layouts/layout.astro';
+import Donate from '@/components/donate.astro';
+import Hero from '@/components/hero.astro';
+import About from '@/components/about.astro';
+import Source from '@/components/source.astro';
+import Footer from '@/components/footer.astro';
+import { App } from '@/components/app';
+
+const currentLocale = Astro.currentLocale || 'en';
+---
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/zh-TW/index.astro b/src/pages/zh-TW/index.astro
new file mode 100644
index 0000000..821c8bc
--- /dev/null
+++ b/src/pages/zh-TW/index.astro
@@ -0,0 +1,20 @@
+---
+import Layout from '@/layouts/layout.astro';
+import Donate from '@/components/donate.astro';
+import Hero from '@/components/hero.astro';
+import About from '@/components/about.astro';
+import Source from '@/components/source.astro';
+import Footer from '@/components/footer.astro';
+import { App } from '@/components/app';
+
+const currentLocale = Astro.currentLocale || 'en';
+---
+
+
+
+
+
+
+
+
+