diff --git a/src/components/about.astro b/src/components/about.astro index 6b28965..c7a309e 100644 --- a/src/components/about.astro +++ b/src/components/about.astro @@ -32,7 +32,9 @@ const paragraphKeys = [ )) } - + @@ -60,8 +62,7 @@ const paragraphKeys = [ & .paragraph { padding: 30px 0; background: linear-gradient( - transparent, - var(--color-neutral-50) 10%, + transparent var(--color-neutral-50) 10%, var(--color-neutral-50) 90%, transparent ); diff --git a/src/components/app/app.tsx b/src/components/app/app.tsx index 30f5bca..edcc45f 100644 --- a/src/components/app/app.tsx +++ b/src/components/app/app.tsx @@ -2,7 +2,7 @@ import { useMemo, useEffect } from 'react'; import { useShallow } from 'zustand/react/shallow'; import { BiSolidHeart } from 'react-icons/bi/index'; import { Howler } from 'howler'; -import { I18nextProvider, useTranslation } from 'react-i18next'; +import { I18nextProvider } from 'react-i18next'; import i18n from '@/i18n'; import { useSoundStore } from '@/stores/sound'; @@ -23,17 +23,14 @@ import type { Sound, Category as CategoryType } from '@/data/types'; import { subscribe } from '@/lib/event'; interface AppProps { - locale: string; // 接收来自 Astro 的 locale + locale: string; } export function App({ locale }: AppProps) { if (locale && i18n.language !== locale) { i18n.changeLanguage(locale); } - const { t } = useTranslation(); - const categoriesData = useMemo(() => sounds.categories, []); - const categories = categoriesData; // 暂时不翻译 const favorites = useSoundStore(useShallow(state => state.getFavorites())); const pause = useSoundStore(state => state.pause); @@ -48,7 +45,6 @@ export function App({ locale }: AppProps) { favorites.includes(sound.id), ); - // 暂时不翻译 sound labels return favorites .map(favoriteId => favoriteSoundsData.find(sound => sound.id === favoriteId), @@ -92,11 +88,11 @@ export function App({ locale }: AppProps) { icon: , id: 'favorites', sounds: favoriteSounds, - title: t('categories.favorites'), + titleKey: 'sounds.favorites.title', }); } - return [...favs, ...categories]; - }, [favoriteSounds, categories, t]); + return [...favs, ...categoriesData]; + }, [favoriteSounds, categoriesData]); return ( diff --git a/src/components/buttons/play/play.tsx b/src/components/buttons/play/play.tsx index ce7c15b..21b686f 100644 --- a/src/components/buttons/play/play.tsx +++ b/src/components/buttons/play/play.tsx @@ -44,14 +44,14 @@ export function PlayButton() { {' '} - {t('common.pause')} + {t('buttons.pause.label')} ) : ( <> {' '} - {t('common.play')} + {t('buttons.play.label')} )} diff --git a/src/components/buttons/unselect/unselect.tsx b/src/components/buttons/unselect/unselect.tsx index 8934128..7682138 100644 --- a/src/components/buttons/unselect/unselect.tsx +++ b/src/components/buttons/unselect/unselect.tsx @@ -11,13 +11,15 @@ import { fade, mix, slideX } from '@/lib/motion'; import styles from './unselect.module.css'; +import { useTranslation } from 'react-i18next'; + export function UnselectButton() { const noSelected = useSoundStore(state => state.noSelected()); const restoreHistory = useSoundStore(state => state.restoreHistory); const hasHistory = useSoundStore(state => !!state.history); const unselectAll = useSoundStore(state => state.unselectAll); const locked = useSoundStore(state => state.locked); - + const { t } = useTranslation(); const variants = { ...mix(fade(), slideX(15)), exit: { opacity: 0 }, @@ -45,16 +47,16 @@ export function UnselectButton() { showDelay={0} content={ hasHistory - ? 'Restore unselected sounds.' - : 'Unselect all sounds.' + ? t('buttons.unselect.restore.tooltip') + : t('buttons.unselect.tooltip') } > diff --git a/src/data/sounds/animals.tsx b/src/data/sounds/animals.tsx index cb7dcf1..b72bc3f 100644 --- a/src/data/sounds/animals.tsx +++ b/src/data/sounds/animals.tsx @@ -24,103 +24,104 @@ import type { Category } from '../types'; export const animals: Category = { icon: , id: 'animals', + // 修改 sounds: [ { icon: , id: 'birds', - label: 'Birds', + labelKey: 'sounds.animals.birds', src: '/sounds/animals/birds.mp3', }, { icon: , id: 'seagulls', - label: 'Seagulls', + labelKey: 'sounds.animals.seagulls', src: '/sounds/animals/seagulls.mp3', }, { icon: , id: 'crickets', - label: 'Crickets', + labelKey: 'sounds.animals.crickets', src: '/sounds/animals/crickets.mp3', }, { icon: , id: 'wolf', - label: 'Wolf', + labelKey: 'sounds.animals.wolf', src: '/sounds/animals/wolf.mp3', }, { icon: , id: 'owl', - label: 'Owl', + labelKey: 'sounds.animals.owl', src: '/sounds/animals/owl.mp3', }, { icon: , id: 'frog', - label: 'Frog', + labelKey: 'sounds.animals.frog', src: '/sounds/animals/frog.mp3', }, { icon: , id: 'dog-barking', - label: 'Dog Barking', + labelKey: 'sounds.animals.dog-barking', src: '/sounds/animals/dog-barking.mp3', }, { icon: , id: 'horse-galopp', - label: 'Horse Galopp', + labelKey: 'sounds.animals.horse-galopp', src: '/sounds/animals/horse-galopp.mp3', }, { icon: , id: 'cat-purring', - label: 'Cat Purring', + labelKey: 'sounds.animals.cat-purring', src: '/sounds/animals/cat-purring.mp3', }, { icon: , id: 'crows', - label: 'Crows', + labelKey: 'sounds.animals.crows', src: '/sounds/animals/crows.mp3', }, { icon: , id: 'whale', - label: 'Whale', + labelKey: 'sounds.animals.whale', src: '/sounds/animals/whale.mp3', }, { icon: , id: 'beehive', - label: 'Beehive', + labelKey: 'sounds.animals.beehive', src: '/sounds/animals/beehive.mp3', }, { icon: , id: 'woodpecker', - label: 'Woodpecker', + labelKey: 'sounds.animals.woodpecker', src: '/sounds/animals/woodpecker.mp3', }, { icon: , id: 'chickens', - label: 'Chickens', + labelKey: 'sounds.animals.chickens', src: '/sounds/animals/chickens.mp3', }, { icon: , id: 'cows', - label: 'Cows', + labelKey: 'sounds.animals.cows', src: '/sounds/animals/cows.mp3', }, { icon: , id: 'sheep', - label: 'Sheep', + labelKey: 'sounds.animals.sheep', src: '/sounds/animals/sheep.mp3', }, ], - title: 'Animals', + titleKey: 'sounds.animals.title', }; diff --git a/src/data/sounds/binaural.tsx b/src/data/sounds/binaural.tsx index ffe96de..37a3556 100644 --- a/src/data/sounds/binaural.tsx +++ b/src/data/sounds/binaural.tsx @@ -6,37 +6,38 @@ import type { Category } from '../types'; export const binaural: Category = { icon: , id: 'binaural', + // 修改 sounds: [ { icon: , id: 'binaural-delta', - label: 'Delta', + labelKey: 'sounds.binaural.binaural-delta', src: '/sounds/binaural/binaural-delta.wav', }, { icon: , id: 'binaural-theta', - label: 'Theta', + labelKey: 'sounds.binaural.binaural-theta', src: '/sounds/binaural/binaural-theta.wav', }, { icon: , id: 'binaural-alpha', - label: 'Alpha', + labelKey: 'sounds.binaural.binaural-alpha', src: '/sounds/binaural/binaural-alpha.wav', }, { icon: , id: 'binaural-beta', - label: 'Beta', + labelKey: 'sounds.binaural.binaural-beta', src: '/sounds/binaural/binaural-beta.wav', }, { icon: , id: 'binaural-gamma', - label: 'Gamma', + labelKey: 'sounds.binaural.binaural-gamma', src: '/sounds/binaural/binaural-gamma.wav', }, ], - title: 'Binaural Beats', + titleKey: 'sounds.binaural.title', }; diff --git a/src/data/sounds/nature.tsx b/src/data/sounds/nature.tsx index f90d2ea..b638870 100644 --- a/src/data/sounds/nature.tsx +++ b/src/data/sounds/nature.tsx @@ -14,79 +14,80 @@ import type { Category } from '../types'; export const nature: Category = { icon: , id: 'nature', + // 修改 sounds: [ { icon: , id: 'river', - label: 'River', + labelKey: 'sounds.nature.river', src: '/sounds/nature/river.mp3', }, { icon: , id: 'waves', - label: 'Waves', + labelKey: 'sounds.nature.waves', src: '/sounds/nature/waves.mp3', }, { icon: , id: 'campfire', - label: 'Campfire', + labelKey: 'sounds.nature.campfire', src: '/sounds/nature/campfire.mp3', }, { icon: , id: 'wind', - label: 'Wind', + labelKey: 'sounds.nature.wind', src: '/sounds/nature/wind.mp3', }, { icon: , id: 'howling-wind', - label: 'Howling Wind', + labelKey: 'sounds.nature.howling-wind', src: '/sounds/nature/howling-wind.mp3', }, { icon: , id: 'wind-in-trees', - label: 'Wind in Trees', + labelKey: 'sounds.nature.wind-in-trees', src: '/sounds/nature/wind-in-trees.mp3', }, { icon: , id: 'waterfall', - label: 'Waterfall', + labelKey: 'sounds.nature.waterfall', src: '/sounds/nature/waterfall.mp3', }, { icon: , id: 'walk-in-snow', - label: 'Walk in Snow', + labelKey: 'sounds.nature.walk-in-snow', src: '/sounds/nature/walk-in-snow.mp3', }, { icon: , id: 'walk-on-leaves', - label: 'Walk on Leaves', + labelKey: 'sounds.nature.walk-on-leaves', src: '/sounds/nature/walk-on-leaves.mp3', }, { icon: , id: 'walk-on-gravel', - label: 'Walk on Gravel', + labelKey: 'sounds.nature.walk-on-gravel', src: '/sounds/nature/walk-on-gravel.mp3', }, { icon: , id: 'droplets', - label: 'Droplets', + labelKey: 'sounds.nature.droplets', src: '/sounds/nature/droplets.mp3', }, { icon: , id: 'jungle', - label: 'Jungle', + labelKey: 'sounds.nature.jungle', src: '/sounds/nature/jungle.mp3', }, ], - title: 'Nature', + titleKey: 'sounds.nature.title', }; diff --git a/src/data/sounds/noise.tsx b/src/data/sounds/noise.tsx index 5042001..279c935 100644 --- a/src/data/sounds/noise.tsx +++ b/src/data/sounds/noise.tsx @@ -6,25 +6,26 @@ import type { Category } from '../types'; export const noise: Category = { icon: , id: 'noise', + // 修改 sounds: [ { icon: , id: 'white-noise', - label: 'White Noise', + labelKey: 'sounds.noise.white-noise', src: '/sounds/noise/white-noise.wav', }, { icon: , id: 'pink-noise', - label: 'Pink Noise', + labelKey: 'sounds.noise.pink-noise', src: '/sounds/noise/pink-noise.wav', }, { icon: , id: 'brown-noise', - label: 'Brown Noise', + labelKey: 'sounds.noise.brown-noise', src: '/sounds/noise/brown-noise.wav', }, ], - title: 'Noise', + titleKey: 'sounds.noise.title', }; diff --git a/src/data/sounds/places.tsx b/src/data/sounds/places.tsx index b9c771a..88037ca 100644 --- a/src/data/sounds/places.tsx +++ b/src/data/sounds/places.tsx @@ -21,103 +21,104 @@ import type { Category } from '../types'; export const places: Category = { icon: , id: 'places', + // 修改 sounds: [ { icon: , id: 'cafe', - label: 'Cafe', + labelKey: 'sounds.places.cafe', src: '/sounds/places/cafe.mp3', }, { icon: , id: 'airport', - label: 'Airport', + labelKey: 'sounds.places.airport', src: '/sounds/places/airport.mp3', }, { icon: , id: 'church', - label: 'Church', + labelKey: 'sounds.places.church', src: '/sounds/places/church.mp3', }, { icon: , id: 'temple', - label: 'Temple', + labelKey: 'sounds.places.temple', src: '/sounds/places/temple.mp3', }, { icon: , id: 'construction-site', - label: 'Construction Site', + labelKey: 'sounds.places.construction-site', src: '/sounds/places/construction-site.mp3', }, { icon: , id: 'underwater', - label: 'Underwater', + labelKey: 'sounds.places.underwater', src: '/sounds/places/underwater.mp3', }, { icon: , id: 'crowded-bar', - label: 'Crowded Bar', + labelKey: 'sounds.places.crowded-bar', src: '/sounds/places/crowded-bar.mp3', }, { icon: , id: 'night-village', - label: 'Night Village', + labelKey: 'sounds.places.night-village', src: '/sounds/places/night-village.mp3', }, { icon: , id: 'subway-station', - label: 'Subway Station', + labelKey: 'sounds.places.subway-station', src: '/sounds/places/subway-station.mp3', }, { icon: , id: 'office', - label: 'Office', + labelKey: 'sounds.places.office', src: '/sounds/places/office.mp3', }, { icon: , id: 'supermarket', - label: 'Supermarket', + labelKey: 'sounds.places.supermarket', src: '/sounds/places/supermarket.mp3', }, { icon: , id: 'carousel', - label: 'Carousel', + labelKey: 'sounds.places.carousel', src: '/sounds/places/carousel.mp3', }, { icon: , id: 'laboratory', - label: 'Laboratory', + labelKey: 'sounds.places.laboratory', src: '/sounds/places/laboratory.mp3', }, { icon: , id: 'laundry-room', - label: 'Laundry Room', + labelKey: 'sounds.places.laundry-room', src: '/sounds/places/laundry-room.mp3', }, { icon: , id: 'restaurant', - label: 'Restaurant', + labelKey: 'sounds.places.restaurant', src: '/sounds/places/restaurant.mp3', }, { icon: , id: 'library', - label: 'Library', + labelKey: 'sounds.places.library', src: '/sounds/places/library.mp3', }, ], - title: 'Places', + titleKey: 'sounds.places.title', }; diff --git a/src/data/sounds/rain.tsx b/src/data/sounds/rain.tsx index 0a23a69..a5637ae 100644 --- a/src/data/sounds/rain.tsx +++ b/src/data/sounds/rain.tsx @@ -13,55 +13,56 @@ import type { Category } from '../types'; export const rain: Category = { icon: , id: 'rain', + // 修改 sounds: [ { icon: , id: 'light-rain', - label: 'Light Rain', + labelKey: 'sounds.rain.light-rain', src: '/sounds/rain/light-rain.mp3', }, { icon: , id: 'heavy-rain', - label: 'Heavy Rain', + labelKey: 'sounds.rain.heavy-rain', src: '/sounds/rain/heavy-rain.mp3', }, { icon: , id: 'thunder', - label: 'Thunder', + labelKey: 'sounds.rain.thunder', src: '/sounds/rain/thunder.mp3', }, { icon: , id: 'rain-on-window', - label: 'Rain on Window', + labelKey: 'sounds.rain.rain-on-window', src: '/sounds/rain/rain-on-window.mp3', }, { icon: , id: 'rain-on-car-roof', - label: 'Rain on Car Roof', + labelKey: 'sounds.rain.rain-on-car-roof', src: '/sounds/rain/rain-on-car-roof.mp3', }, { icon: , id: 'rain-on-umbrella', - label: 'Rain on Umbrella', + labelKey: 'sounds.rain.rain-on-umbrella', src: '/sounds/rain/rain-on-umbrella.mp3', }, { icon: , id: 'rain-on-tent', - label: 'Rain on Tent', + labelKey: 'sounds.rain.rain-on-tent', src: '/sounds/rain/rain-on-tent.mp3', }, { icon: , id: 'rain-on-leaves', - label: 'Rain on Leaves', + labelKey: 'sounds.rain.rain-on-leaves', src: '/sounds/rain/rain-on-leaves.mp3', }, ], - title: 'Rain', + titleKey: 'sounds.rain.title', }; diff --git a/src/data/sounds/things.tsx b/src/data/sounds/things.tsx index f5bb59f..a87f3d8 100644 --- a/src/data/sounds/things.tsx +++ b/src/data/sounds/things.tsx @@ -17,103 +17,104 @@ import type { Category } from '../types'; export const things: Category = { icon: , id: 'things', + // 修改 sounds: [ { icon: , id: 'keyboard', - label: 'Keyboard', + labelKey: 'sounds.things.keyboard', src: '/sounds/things/keyboard.mp3', }, { icon: , id: 'typewriter', - label: 'Typewriter', + labelKey: 'sounds.things.typewriter', src: '/sounds/things/typewriter.mp3', }, { icon: , id: 'paper', - label: 'Paper', + labelKey: 'sounds.things.paper', src: '/sounds/things/paper.mp3', }, { icon: , id: 'clock', - label: 'Clock', + labelKey: 'sounds.things.clock', src: '/sounds/things/clock.mp3', }, { icon: , id: 'wind-chimes', - label: 'Wind Chimes', + labelKey: 'sounds.things.wind-chimes', src: '/sounds/things/wind-chimes.mp3', }, { icon: , id: 'singing-bowl', - label: 'Singing Bowl', + labelKey: 'sounds.things.singing-bowl', src: '/sounds/things/singing-bowl.mp3', }, { icon: , id: 'ceiling-fan', - label: 'Ceiling Fan', + labelKey: 'sounds.things.ceiling-fan', src: '/sounds/things/ceiling-fan.mp3', }, { icon: , id: 'dryer', - label: 'Dryer', + labelKey: 'sounds.things.dryer', src: '/sounds/things/dryer.mp3', }, { icon: , id: 'slide-projector', - label: 'Slide Projector', + labelKey: 'sounds.things.slide-projector', src: '/sounds/things/slide-projector.mp3', }, { icon: , id: 'boiling-water', - label: 'Boiling Water', + labelKey: 'sounds.things.boiling-water', src: '/sounds/things/boiling-water.mp3', }, { icon: , id: 'bubbles', - label: 'Bubbles', + labelKey: 'sounds.things.bubbles', src: '/sounds/things/bubbles.mp3', }, { icon: , id: 'tuning-radio', - label: 'Tuning Radio', + labelKey: 'sounds.things.tuning-radio', src: '/sounds/things/tuning-radio.mp3', }, { icon: , id: 'morse-code', - label: 'Morse Code', + labelKey: 'sounds.things.morse-code', src: '/sounds/things/morse-code.mp3', }, { icon: , id: 'washing-machine', - label: 'Washing Machine', + labelKey: 'sounds.things.washing-machine', src: '/sounds/things/washing-machine.mp3', }, { icon: , id: 'vinyl-effect', - label: 'Vinyl Effect', + labelKey: 'sounds.things.vinyl-effect', src: '/sounds/things/vinyl-effect.mp3', }, { icon: , id: 'windshield-wipers', - label: 'Windshield Wipers', + labelKey: 'sounds.things.windshield-wipers', src: '/sounds/things/windshield-wipers.mp3', }, ], - title: 'Things', + titleKey: 'sounds.things.title', }; diff --git a/src/data/sounds/transport.tsx b/src/data/sounds/transport.tsx index 5273332..e93ba4b 100644 --- a/src/data/sounds/transport.tsx +++ b/src/data/sounds/transport.tsx @@ -8,43 +8,44 @@ import type { Category } from '../types'; export const transport: Category = { icon: , id: 'transport', + // 修改 sounds: [ { icon: , id: 'train', - label: 'Train', + labelKey: 'sounds.transport.train', src: '/sounds/transport/train.mp3', }, { icon: , id: 'inside-a-train', - label: 'Inside a Train', + labelKey: 'sounds.transport.inside-a-train', src: '/sounds/transport/inside-a-train.mp3', }, { icon: , id: 'airplane', - label: 'Airplane', + labelKey: 'sounds.transport.airplane', src: '/sounds/transport/airplane.mp3', }, { icon: , id: 'submarine', - label: 'Submarine', + labelKey: 'sounds.transport.submarine', src: '/sounds/transport/submarine.mp3', }, { icon: , id: 'sailboat', - label: 'Sailboat', + labelKey: 'sounds.transport.sailboat', src: '/sounds/transport/sailboat.mp3', }, { icon: , id: 'rowing-boat', - label: 'Rowing Boat', + labelKey: 'sounds.transport.rowing-boat', src: '/sounds/transport/rowing-boat.mp3', }, ], - title: 'Transport', + titleKey: 'sounds.transport.title', }; diff --git a/src/data/sounds/urban.tsx b/src/data/sounds/urban.tsx index 59cf3eb..4022695 100644 --- a/src/data/sounds/urban.tsx +++ b/src/data/sounds/urban.tsx @@ -9,49 +9,50 @@ import type { Category } from '../types'; export const urban: Category = { icon: , id: 'urban', + // 修改 sounds: [ { icon: , id: 'highway', - label: 'Highway', + labelKey: 'sounds.urban.highway', src: '/sounds/urban/highway.mp3', }, { icon: , id: 'road', - label: 'Road', + labelKey: 'sounds.urban.road', src: '/sounds/urban/road.mp3', }, { icon: , id: 'ambulance-siren', - label: 'Ambulance Siren', + labelKey: 'sounds.urban.ambulance-siren', src: '/sounds/urban/ambulance-siren.mp3', }, { icon: , id: 'busy-street', - label: 'Busy Street', + labelKey: 'sounds.urban.busy-street', src: '/sounds/urban/busy-street.mp3', }, { icon: , id: 'crowd', - label: 'Crowd', + labelKey: 'sounds.urban.crowd', src: '/sounds/urban/crowd.mp3', }, { icon: , id: 'traffic', - label: 'Traffic', + labelKey: 'sounds.urban.traffic', src: '/sounds/urban/traffic.mp3', }, { icon: , id: 'fireworks', - label: 'Fireworks', + labelKey: 'sounds.urban.fireworks', src: '/sounds/urban/fireworks.mp3', }, ], - title: 'Urban', + titleKey: 'sounds.urban.title', }; diff --git a/src/data/types.d.ts b/src/data/types.d.ts index 515d516..d467e0a 100644 --- a/src/data/types.d.ts +++ b/src/data/types.d.ts @@ -1,7 +1,7 @@ export interface Sound { icon: React.ReactNode; id: string; - label: string; + labelKey: string; src: string; } @@ -11,7 +11,7 @@ export interface Category { icon: React.ReactNode; id: string; sounds: Sounds; - title: string; + titleKey: string; } export type Categories = Array; diff --git a/src/i18n.ts b/src/i18n.ts index 3935317..5b76db5 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -16,15 +16,32 @@ const resources = { i18n.use(initReactI18next).init({ debug: true, fallbackLng: 'en', - interpolation: { - escapeValue: false, - }, + interpolation: { escapeValue: false }, lng: 'en', - react: { - useSuspense: false, - }, + 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); + if (typeof value === 'object' && value !== null) { + console.warn( + `i18next: Key '${key}' in namespace '${ + ns || 'translation' + }' resolved to an object, but expected a string. Check your t() call.`, + options, + ); + } else { + console.warn( + `i18next: Missing key '${key}' in namespace '${ + ns || 'translation' + }' for language(s) '${lngs.join(', ')}'.`, + ); + } + + return fallbackValue || key; + }, + react: { useSuspense: false }, resources, + returnObjects: true, }); export default i18n; diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 34e028a..52c7f52 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -8,14 +8,6 @@ "en": "English", "zh": "简体中文" }, - "languageSwitcher": { - "label": "Language selection" - }, - "common": { - "play": "Play", - "pause": "Pause", - "close": "Close" - }, "modals": { "reload": { "title": "New Content", @@ -23,13 +15,33 @@ "reloadButton": "Reload" } }, - "buttons": { - "playError": "Please first select a sound to play.", - "useMoodist": "Use Moodist" - }, - "categories": { - "favorites": "Favorites" + "play": { + "label": "Play", + "error": "Please select a sound to play." + }, + "favorite": { + "add": { + "aria-label": "Add {{label}} Sound to Favorites" + }, + "remove": { + "aria-label": "Remove {{label}} Sound from Favorites" + } + }, + "unselect": { + "tooltip": "Unselect all sounds.", + "aria-label": "Unselect All Sounds", + "restore": { + "tooltip": "Restore unselected sounds.", + "aria-label": "Restore Unselected Sounds" + } + }, + "pause": { + "label": "Pause" + }, + "use-moodist": { + "label": "Use Moodist" + } }, "about": { "section1": { @@ -48,5 +60,132 @@ "title": "Sounds for Every Moment", "body": "Whether you're looking to unwind after a long day, enhance your focus during work, or lull yourself into a peaceful sleep, Moodist has the perfect soundscape waiting for you. The best part? It's completely free and open-source, so you can enjoy its benefits without any strings attached. Start using Moodist today and discover your new haven of tranquility and focus!" } + }, + "volume": { + "aria-label": "{{label}} sound volume" + }, + "sounds": { + "show-less": "Show Less", + "show-more": "Show More", + "aria-label": "{{name}} sound", + "favorites": { + "title": "Favorites" + }, + "animals": { + "title": "Animals", + "birds": "Birds", + "seagulls": "Seagulls", + "crickets": "Crickets", + "wolf": "Wolf", + "owl": "Owl", + "frog": "Frog", + "dog-barking": "Dog Barking", + "horse-galopp": "Horse Galopp", + "cat-purring": "Cat Purring", + "crows": "Crows", + "whale": "Whale", + "beehive": "Beehive", + "woodpecker": "Woodpecker", + "chickens": "Chickens", + "cows": "Cows", + "sheep": "Sheep" + }, + "binaural": { + "title": "Binaural Beats", + "binaural-delta": "Delta", + "binaural-theta": "Theta", + "binaural-alpha": "Alpha", + "binaural-beta": "Beta", + "binaural-gamma": "Gamma" + }, + "nature": { + "title": "Nature", + "river": "River", + "waves": "Waves", + "campfire": "Campfire", + "wind": "Wind", + "howling-wind": "Howling Wind", + "wind-in-trees": "Wind in Trees", + "waterfall": "Waterfall", + "walk-in-snow": "Walk in Snow", + "walk-on-leaves": "Walk on Leaves", + "walk-on-gravel": "Walk on Gravel", + "droplets": "Droplets", + "jungle": "Jungle" + }, + "noise": { + "title": "Noise", + "white-noise": "White Noise", + "pink-noise": "Pink Noise", + "brown-noise": "Brown Noise" + }, + "places": { + "title": "Places", + "cafe": "Cafe", + "airport": "Airport", + "church": "Church", + "temple": "Temple", + "construction-site": "Construction Site", + "underwater": "Underwater", + "crowded-bar": "Crowded Bar", + "night-village": "Night Village", + "subway-station": "Subway Station", + "office": "Office", + "supermarket": "Supermarket", + "carousel": "Carousel", + "laboratory": "Laboratory", + "laundry-room": "Laundry Room", + "restaurant": "Restaurant", + "library": "Library" + }, + "rain": { + "title": "Rain", + "light-rain": "Light Rain", + "heavy-rain": "Heavy Rain", + "thunder": "Thunder", + "rain-on-window": "Rain on Window", + "rain-on-car-roof": "Rain on Car Roof", + "rain-on-umbrella": "Rain on Umbrella", + "rain-on-tent": "Rain on Tent", + "rain-on-leaves": "Rain on Leaves" + }, + "things": { + "title": "Things", + "keyboard": "Keyboard", + "typewriter": "Typewriter", + "paper": "Paper", + "clock": "Clock", + "wind-chimes": "Wind Chimes", + "singing-bowl": "Singing Bowl", + "ceiling-fan": "Ceiling Fan", + "dryer": "Dryer", + "slide-projector": "Slide Projector", + "boiling-water": "Boiling Water", + "bubbles": "Bubbles", + "tuning-radio": "Tuning Radio", + "morse-code": "Morse Code", + "washing-machine": "Washing Machine", + "vinyl-effect": "Vinyl Effect", + "windshield-wipers": "Windshield Wipers" + }, + "transport": { + "title": "Transport", + "train": "Train", + "inside-a-train": "Inside a Train", + "airplane": "Airplane", + "submarine": "Submarine", + "sailboat": "Sailboat", + "rowing-boat": "Rowing Boat" + }, + "urban": { + "title": "Urban", + "highway": "Highway", + "road": "Road", + "ambulance-siren": "Ambulance Siren", + "busy-street": "Busy Street", + "crowd": "Crowd", + "traffic": "Traffic", + "fireworks": "Fireworks" + } } } diff --git a/src/locales/zh/translation.json b/src/locales/zh/translation.json index af78eb3..9394c11 100644 --- a/src/locales/zh/translation.json +++ b/src/locales/zh/translation.json @@ -8,14 +8,6 @@ "en": "English", "zh": "简体中文" }, - "languageSwitcher": { - "label": "语言选择" - }, - "common": { - "play": "播放", - "pause": "暂停", - "close": "关闭" - }, "modals": { "reload": { "title": "发现新内容", @@ -24,11 +16,32 @@ } }, "buttons": { - "playError": "请先选择要播放的声音。", - "useMoodist": "使用 Moodist" - }, - "categories": { - "favorites": "收藏夹" + "play": { + "label": "播放", + "error": "请先选择要播放的声音。" + }, + "favorite": { + "add": { + "aria-label": "将 {{label}} 声音添加到收藏夹" + }, + "remove": { + "aria-label": "从收藏夹移除 {{label}} 声音" + } + }, + "unselect": { + "tooltip": "取消选择所有声音。", + "aria-label": "取消选择所有声音", + "restore": { + "tooltip": "恢复上次选择的声音。", + "aria-label": "恢复上次选择的声音" + } + }, + "pause": { + "label": "暂停" + }, + "use-moodist": { + "label": "使用 Moodist" + } }, "about": { "section1": { @@ -47,5 +60,132 @@ "title": "适合每一刻的声音", "body": "无论您是想在漫长的一天后放松身心,在工作时提高注意力,还是哄自己进入宁静的睡眠,Moodist 都有完美的声音景观等着您。最棒的是?它完全免费且开源,因此您可以无任何附加条件地享受其益处。立即开始使用 Moodist,发现您宁静与专注的新港湾!" } + }, + "volume": { + "aria-label": "{{label}} 声音音量" + }, + "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": "烟花" + } } }