mirror of
https://github.com/arthur-pbty/moon.git
synced 2026-06-03 15:07:31 +02:00
first commit
This commit is contained in:
+694
@@ -0,0 +1,694 @@
|
||||
/**
|
||||
* Internationalization system supporting 11 languages
|
||||
*/
|
||||
|
||||
export type Locale = 'en' | 'fr' | 'es' | 'de' | 'pt' | 'it' | 'ja' | 'zh' | 'ar' | 'ru' | 'hi';
|
||||
|
||||
export const LOCALES: { code: Locale; name: string; flag: string; dir?: 'rtl' }[] = [
|
||||
{ code: 'en', name: 'English', flag: '🇬🇧' },
|
||||
{ code: 'fr', name: 'Français', flag: '🇫🇷' },
|
||||
{ code: 'es', name: 'Español', flag: '🇪🇸' },
|
||||
{ code: 'de', name: 'Deutsch', flag: '🇩🇪' },
|
||||
{ code: 'pt', name: 'Português', flag: '🇧🇷' },
|
||||
{ code: 'it', name: 'Italiano', flag: '🇮🇹' },
|
||||
{ code: 'ja', name: '日本語', flag: '🇯🇵' },
|
||||
{ code: 'zh', name: '中文', flag: '🇨🇳' },
|
||||
{ code: 'ar', name: 'العربية', flag: '🇸🇦', dir: 'rtl' },
|
||||
{ code: 'ru', name: 'Русский', flag: '🇷🇺' },
|
||||
{ code: 'hi', name: 'हिन्दी', flag: '🇮🇳' },
|
||||
];
|
||||
|
||||
type TranslationKeys = {
|
||||
// Navigation
|
||||
nav_home: string;
|
||||
nav_calendar: string;
|
||||
nav_fullmoons: string;
|
||||
nav_simulator: string;
|
||||
nav_moon3d: string;
|
||||
nav_articles: string;
|
||||
nav_quiz: string;
|
||||
// Hero
|
||||
hero_title: string;
|
||||
hero_subtitle: string;
|
||||
// Next full moon
|
||||
next_full_moon: string;
|
||||
countdown_days: string;
|
||||
countdown_hours: string;
|
||||
countdown_minutes: string;
|
||||
countdown_seconds: string;
|
||||
// Calendar
|
||||
calendar_title: string;
|
||||
calendar_subtitle: string;
|
||||
new_moon: string;
|
||||
first_quarter: string;
|
||||
full_moon: string;
|
||||
last_quarter: string;
|
||||
waxing_crescent: string;
|
||||
waxing_gibbous: string;
|
||||
waning_gibbous: string;
|
||||
waning_crescent: string;
|
||||
// Full moon names
|
||||
fullmoons_title: string;
|
||||
fullmoons_subtitle: string;
|
||||
// Simulator
|
||||
simulator_title: string;
|
||||
simulator_subtitle: string;
|
||||
simulator_date: string;
|
||||
simulator_illumination: string;
|
||||
simulator_age: string;
|
||||
simulator_days: string;
|
||||
simulator_zodiac: string;
|
||||
// 3D Moon
|
||||
moon3d_title: string;
|
||||
moon3d_subtitle: string;
|
||||
moon3d_drag: string;
|
||||
moon3d_scroll: string;
|
||||
// Visibility
|
||||
visibility_title: string;
|
||||
visibility_subtitle: string;
|
||||
// Articles
|
||||
articles_title: string;
|
||||
articles_subtitle: string;
|
||||
// Quiz
|
||||
quiz_title: string;
|
||||
quiz_subtitle: string;
|
||||
quiz_start: string;
|
||||
quiz_next: string;
|
||||
quiz_results: string;
|
||||
quiz_score: string;
|
||||
quiz_restart: string;
|
||||
quiz_correct: string;
|
||||
quiz_wrong: string;
|
||||
// Infographics
|
||||
infographics_title: string;
|
||||
infographics_subtitle: string;
|
||||
// PDF
|
||||
pdf_download: string;
|
||||
pdf_title: string;
|
||||
pdf_generated: string;
|
||||
pdf_col_month: string;
|
||||
pdf_col_date: string;
|
||||
pdf_col_time: string;
|
||||
pdf_col_name: string;
|
||||
// Articles
|
||||
articles_read: string;
|
||||
// General
|
||||
months: string[];
|
||||
loading: string;
|
||||
current_phase: string;
|
||||
explore: string;
|
||||
learn_more: string;
|
||||
// Footer
|
||||
footer_text: string;
|
||||
footer_description: string;
|
||||
// Culture sections
|
||||
culture_native: string;
|
||||
culture_celtic: string;
|
||||
culture_hindu: string;
|
||||
culture_chinese: string;
|
||||
effects_title: string;
|
||||
effects_human: string;
|
||||
effects_animals: string;
|
||||
effects_tides: string;
|
||||
// Phase descriptions
|
||||
phase_desc_new: string;
|
||||
phase_desc_waxing_crescent: string;
|
||||
phase_desc_first_quarter: string;
|
||||
phase_desc_waxing_gibbous: string;
|
||||
phase_desc_full: string;
|
||||
phase_desc_waning_gibbous: string;
|
||||
phase_desc_last_quarter: string;
|
||||
phase_desc_waning_crescent: string;
|
||||
};
|
||||
|
||||
const translations: Record<Locale, TranslationKeys> = {
|
||||
en: {
|
||||
nav_home: 'Home',
|
||||
nav_calendar: 'Calendar',
|
||||
nav_fullmoons: 'Full Moons',
|
||||
nav_simulator: 'Simulator',
|
||||
nav_moon3d: '3D Moon',
|
||||
nav_articles: 'Articles',
|
||||
nav_quiz: 'Quiz',
|
||||
hero_title: 'Discover the Magic of the Moon',
|
||||
hero_subtitle: 'Explore lunar phases, full moon traditions, and the cosmic rhythms that have guided humanity for millennia.',
|
||||
next_full_moon: 'Next Full Moon',
|
||||
countdown_days: 'days',
|
||||
countdown_hours: 'hours',
|
||||
countdown_minutes: 'min',
|
||||
countdown_seconds: 'sec',
|
||||
calendar_title: 'Lunar Calendar',
|
||||
calendar_subtitle: 'All moon phases calculated automatically for the current year with exact times.',
|
||||
new_moon: 'New Moon',
|
||||
first_quarter: 'First Quarter',
|
||||
full_moon: 'Full Moon',
|
||||
last_quarter: 'Last Quarter',
|
||||
waxing_crescent: 'Waxing Crescent',
|
||||
waxing_gibbous: 'Waxing Gibbous',
|
||||
waning_gibbous: 'Waning Gibbous',
|
||||
waning_crescent: 'Waning Crescent',
|
||||
fullmoons_title: 'Traditional Full Moon Names',
|
||||
fullmoons_subtitle: 'Each month\'s full moon carries a traditional name rooted in ancient cultures.',
|
||||
simulator_title: 'Lunar Phase Simulator',
|
||||
simulator_subtitle: 'See how the moon looks on any date you choose.',
|
||||
simulator_date: 'Select a date',
|
||||
simulator_illumination: 'Illumination',
|
||||
simulator_age: 'Moon Age',
|
||||
simulator_days: 'days',
|
||||
simulator_zodiac: 'Zodiac Sign',
|
||||
moon3d_title: '3D Moon Visualization',
|
||||
moon3d_subtitle: 'Interactive 3D model — drag to rotate, scroll to zoom.',
|
||||
moon3d_drag: 'Drag to rotate',
|
||||
moon3d_scroll: 'Scroll to zoom',
|
||||
visibility_title: 'Moon Visibility Map',
|
||||
visibility_subtitle: 'See where the moon is visible around the world right now.',
|
||||
articles_title: 'Lunar Articles',
|
||||
articles_subtitle: 'Explore the rich history, mythology, and science of the moon.',
|
||||
quiz_title: 'Moon Quiz',
|
||||
quiz_subtitle: 'Test your knowledge about the moon and its phases!',
|
||||
quiz_start: 'Start Quiz',
|
||||
quiz_next: 'Next Question',
|
||||
quiz_results: 'Your Results',
|
||||
quiz_score: 'Score',
|
||||
quiz_restart: 'Restart',
|
||||
quiz_correct: 'Correct!',
|
||||
quiz_wrong: 'Wrong!',
|
||||
infographics_title: 'Lunar Infographics',
|
||||
infographics_subtitle: 'Visual data about moon phases, tides, and celestial cycles.',
|
||||
pdf_download: 'Download PDF Calendar',
|
||||
pdf_title: 'Lunar Calendar',
|
||||
pdf_generated: 'Generated',
|
||||
pdf_col_month: 'Month',
|
||||
pdf_col_date: 'Date',
|
||||
pdf_col_time: 'Time',
|
||||
pdf_col_name: 'Name',
|
||||
articles_read: 'Read Article',
|
||||
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
||||
loading: 'Loading...',
|
||||
current_phase: 'Current Phase',
|
||||
explore: 'Explore',
|
||||
learn_more: 'Learn More',
|
||||
footer_text: 'Moon Phases — Your complete guide to the lunar cycle',
|
||||
footer_description: 'All lunar data calculated automatically using astronomical algorithms.',
|
||||
culture_native: 'Native American',
|
||||
culture_celtic: 'Celtic',
|
||||
culture_hindu: 'Hindu',
|
||||
culture_chinese: 'Chinese',
|
||||
effects_title: 'Effects',
|
||||
effects_human: 'On Humans',
|
||||
effects_animals: 'On Animals',
|
||||
effects_tides: 'On Tides',
|
||||
phase_desc_new: 'The moon is between the Earth and the Sun, invisible from Earth. A time for new beginnings.',
|
||||
phase_desc_waxing_crescent: 'A sliver of light appears. Time for setting intentions and planting seeds.',
|
||||
phase_desc_first_quarter: 'Half the moon is illuminated. A time for making decisions and taking action.',
|
||||
phase_desc_waxing_gibbous: 'More than half illuminated and growing. Time to refine and adjust plans.',
|
||||
phase_desc_full: 'The moon is fully illuminated. Peak energy, completion, and celebration.',
|
||||
phase_desc_waning_gibbous: 'Light begins to fade. Time for gratitude and sharing wisdom.',
|
||||
phase_desc_last_quarter: 'Half illuminated and waning. Time for release and forgiveness.',
|
||||
phase_desc_waning_crescent: 'A fading sliver. Time for rest, reflection, and surrender.',
|
||||
},
|
||||
fr: {
|
||||
nav_home: 'Accueil',
|
||||
nav_calendar: 'Calendrier',
|
||||
nav_fullmoons: 'Pleines Lunes',
|
||||
nav_simulator: 'Simulateur',
|
||||
nav_moon3d: 'Lune 3D',
|
||||
nav_articles: 'Articles',
|
||||
nav_quiz: 'Quiz',
|
||||
hero_title: 'Découvrez la Magie de la Lune',
|
||||
hero_subtitle: 'Explorez les phases lunaires, les traditions des pleines lunes et les rythmes cosmiques qui guident l\'humanité depuis des millénaires.',
|
||||
next_full_moon: 'Prochaine Pleine Lune',
|
||||
countdown_days: 'jours',
|
||||
countdown_hours: 'heures',
|
||||
countdown_minutes: 'min',
|
||||
countdown_seconds: 'sec',
|
||||
calendar_title: 'Calendrier Lunaire',
|
||||
calendar_subtitle: 'Toutes les phases lunaires calculées automatiquement pour l\'année en cours avec les heures exactes.',
|
||||
new_moon: 'Nouvelle Lune',
|
||||
first_quarter: 'Premier Quartier',
|
||||
full_moon: 'Pleine Lune',
|
||||
last_quarter: 'Dernier Quartier',
|
||||
waxing_crescent: 'Croissant Croissant',
|
||||
waxing_gibbous: 'Gibbeuse Croissante',
|
||||
waning_gibbous: 'Gibbeuse Décroissante',
|
||||
waning_crescent: 'Croissant Décroissant',
|
||||
fullmoons_title: 'Noms Traditionnels des Pleines Lunes',
|
||||
fullmoons_subtitle: 'Chaque pleine lune mensuelle porte un nom traditionnel issu de cultures anciennes.',
|
||||
simulator_title: 'Simulateur de Phases Lunaires',
|
||||
simulator_subtitle: 'Voyez à quoi ressemble la lune à la date de votre choix.',
|
||||
simulator_date: 'Choisir une date',
|
||||
simulator_illumination: 'Illumination',
|
||||
simulator_age: 'Âge de la Lune',
|
||||
simulator_days: 'jours',
|
||||
simulator_zodiac: 'Signe du Zodiaque',
|
||||
moon3d_title: 'Visualisation 3D de la Lune',
|
||||
moon3d_subtitle: 'Modèle 3D interactif — glissez pour tourner, scrollez pour zoomer.',
|
||||
moon3d_drag: 'Glissez pour tourner',
|
||||
moon3d_scroll: 'Scrollez pour zoomer',
|
||||
visibility_title: 'Carte de Visibilité Lunaire',
|
||||
visibility_subtitle: 'Voyez où la lune est visible dans le monde en ce moment.',
|
||||
articles_title: 'Articles Lunaires',
|
||||
articles_subtitle: 'Explorez la riche histoire, la mythologie et la science de la lune.',
|
||||
quiz_title: 'Quiz Lunaire',
|
||||
quiz_subtitle: 'Testez vos connaissances sur la lune et ses phases !',
|
||||
quiz_start: 'Commencer le Quiz',
|
||||
quiz_next: 'Question Suivante',
|
||||
quiz_results: 'Vos Résultats',
|
||||
quiz_score: 'Score',
|
||||
quiz_restart: 'Recommencer',
|
||||
quiz_correct: 'Correct !',
|
||||
quiz_wrong: 'Faux !',
|
||||
infographics_title: 'Infographies Lunaires',
|
||||
infographics_subtitle: 'Données visuelles sur les phases lunaires, les marées et les cycles célestes.',
|
||||
pdf_download: 'Télécharger le Calendrier PDF',
|
||||
pdf_title: 'Calendrier Lunaire',
|
||||
pdf_generated: 'Généré le',
|
||||
pdf_col_month: 'Mois',
|
||||
pdf_col_date: 'Date',
|
||||
pdf_col_time: 'Heure',
|
||||
pdf_col_name: 'Nom',
|
||||
articles_read: 'Lire l\'article',
|
||||
months: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
|
||||
loading: 'Chargement...',
|
||||
current_phase: 'Phase Actuelle',
|
||||
explore: 'Explorer',
|
||||
learn_more: 'En savoir plus',
|
||||
footer_text: 'Phases de la Lune — Votre guide complet du cycle lunaire',
|
||||
footer_description: 'Toutes les données lunaires calculées automatiquement par algorithmes astronomiques.',
|
||||
culture_native: 'Amérindien',
|
||||
culture_celtic: 'Celtique',
|
||||
culture_hindu: 'Hindou',
|
||||
culture_chinese: 'Chinois',
|
||||
effects_title: 'Effets',
|
||||
effects_human: 'Sur l\'Homme',
|
||||
effects_animals: 'Sur les Animaux',
|
||||
effects_tides: 'Sur les Marées',
|
||||
phase_desc_new: 'La lune est entre la Terre et le Soleil, invisible. C\'est le moment des nouveaux départs.',
|
||||
phase_desc_waxing_crescent: 'Un éclat de lumière apparaît. Temps de fixer ses intentions.',
|
||||
phase_desc_first_quarter: 'La moitié de la lune est éclairée. Temps de prendre des décisions.',
|
||||
phase_desc_waxing_gibbous: 'Plus de la moitié éclairée et croissante. Temps d\'affiner ses plans.',
|
||||
phase_desc_full: 'La lune est entièrement éclairée. Énergie maximale, accomplissement.',
|
||||
phase_desc_waning_gibbous: 'La lumière commence à décliner. Temps de gratitude.',
|
||||
phase_desc_last_quarter: 'Moitié éclairée et décroissante. Temps de lâcher prise.',
|
||||
phase_desc_waning_crescent: 'Un croissant qui s\'efface. Temps de repos et de réflexion.',
|
||||
},
|
||||
es: {
|
||||
nav_home: 'Inicio',
|
||||
nav_calendar: 'Calendario',
|
||||
nav_fullmoons: 'Lunas Llenas',
|
||||
nav_simulator: 'Simulador',
|
||||
nav_moon3d: 'Luna 3D',
|
||||
nav_articles: 'Artículos',
|
||||
nav_quiz: 'Quiz',
|
||||
hero_title: 'Descubre la Magia de la Luna',
|
||||
hero_subtitle: 'Explora las fases lunares, las tradiciones de la luna llena y los ritmos cósmicos que han guiado a la humanidad durante milenios.',
|
||||
next_full_moon: 'Próxima Luna Llena',
|
||||
countdown_days: 'días',
|
||||
countdown_hours: 'horas',
|
||||
countdown_minutes: 'min',
|
||||
countdown_seconds: 'seg',
|
||||
calendar_title: 'Calendario Lunar',
|
||||
calendar_subtitle: 'Todas las fases lunares calculadas automáticamente con horas exactas.',
|
||||
new_moon: 'Luna Nueva',
|
||||
first_quarter: 'Cuarto Creciente',
|
||||
full_moon: 'Luna Llena',
|
||||
last_quarter: 'Cuarto Menguante',
|
||||
waxing_crescent: 'Creciente',
|
||||
waxing_gibbous: 'Gibosa Creciente',
|
||||
waning_gibbous: 'Gibosa Menguante',
|
||||
waning_crescent: 'Menguante',
|
||||
fullmoons_title: 'Nombres Tradicionales de las Lunas Llenas',
|
||||
fullmoons_subtitle: 'Cada luna llena mensual tiene un nombre tradicional de culturas antiguas.',
|
||||
simulator_title: 'Simulador de Fases Lunares',
|
||||
simulator_subtitle: 'Observa cómo se ve la luna en cualquier fecha.',
|
||||
simulator_date: 'Selecciona una fecha',
|
||||
simulator_illumination: 'Iluminación',
|
||||
simulator_age: 'Edad de la Luna',
|
||||
simulator_days: 'días',
|
||||
simulator_zodiac: 'Signo Zodiacal',
|
||||
moon3d_title: 'Visualización 3D de la Luna',
|
||||
moon3d_subtitle: 'Modelo interactivo — arrastra para rotar, desplaza para zoom.',
|
||||
moon3d_drag: 'Arrastra para rotar',
|
||||
moon3d_scroll: 'Desplaza para zoom',
|
||||
visibility_title: 'Mapa de Visibilidad Lunar',
|
||||
visibility_subtitle: 'Observa dónde es visible la luna en el mundo ahora.',
|
||||
articles_title: 'Artículos Lunares',
|
||||
articles_subtitle: 'Explora la historia, mitología y ciencia de la luna.',
|
||||
quiz_title: 'Quiz Lunar',
|
||||
quiz_subtitle: '¡Pon a prueba tus conocimientos sobre la luna!',
|
||||
quiz_start: 'Iniciar Quiz',
|
||||
quiz_next: 'Siguiente Pregunta',
|
||||
quiz_results: 'Tus Resultados',
|
||||
quiz_score: 'Puntuación',
|
||||
quiz_restart: 'Reiniciar',
|
||||
quiz_correct: '¡Correcto!',
|
||||
quiz_wrong: '¡Incorrecto!',
|
||||
infographics_title: 'Infografías Lunares',
|
||||
infographics_subtitle: 'Datos visuales sobre fases lunares, mareas y ciclos celestes.',
|
||||
pdf_download: 'Descargar Calendario PDF',
|
||||
pdf_title: 'Calendario Lunar',
|
||||
pdf_generated: 'Generado',
|
||||
pdf_col_month: 'Mes',
|
||||
pdf_col_date: 'Fecha',
|
||||
pdf_col_time: 'Hora',
|
||||
pdf_col_name: 'Nombre',
|
||||
articles_read: 'Leer artículo',
|
||||
months: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
|
||||
loading: 'Cargando...',
|
||||
current_phase: 'Fase Actual',
|
||||
explore: 'Explorar',
|
||||
learn_more: 'Saber más',
|
||||
footer_text: 'Fases de la Luna — Tu guía completa del ciclo lunar',
|
||||
footer_description: 'Datos lunares calculados automáticamente con algoritmos astronómicos.',
|
||||
culture_native: 'Nativo Americano',
|
||||
culture_celtic: 'Celta',
|
||||
culture_hindu: 'Hindú',
|
||||
culture_chinese: 'Chino',
|
||||
effects_title: 'Efectos',
|
||||
effects_human: 'En Humanos',
|
||||
effects_animals: 'En Animales',
|
||||
effects_tides: 'En Mareas',
|
||||
phase_desc_new: 'La luna está entre la Tierra y el Sol, invisible. Momento para nuevos comienzos.',
|
||||
phase_desc_waxing_crescent: 'Aparece un brillo de luz. Momento para fijar intenciones.',
|
||||
phase_desc_first_quarter: 'La mitad de la luna está iluminada. Momento de tomar decisiones.',
|
||||
phase_desc_waxing_gibbous: 'Más de la mitad iluminada. Momento de refinar planes.',
|
||||
phase_desc_full: 'La luna está completamente iluminada. Energía máxima y celebración.',
|
||||
phase_desc_waning_gibbous: 'La luz comienza a disminuir. Momento de gratitud.',
|
||||
phase_desc_last_quarter: 'Mitad iluminada y menguante. Momento de dejar ir.',
|
||||
phase_desc_waning_crescent: 'Un creciente que se desvanece. Momento de descanso.',
|
||||
},
|
||||
de: {
|
||||
nav_home: 'Start',
|
||||
nav_calendar: 'Kalender',
|
||||
nav_fullmoons: 'Vollmonde',
|
||||
nav_simulator: 'Simulator',
|
||||
nav_moon3d: '3D Mond',
|
||||
nav_articles: 'Artikel',
|
||||
nav_quiz: 'Quiz',
|
||||
hero_title: 'Entdecke die Magie des Mondes',
|
||||
hero_subtitle: 'Erkunde Mondphasen, Vollmond-Traditionen und kosmische Rhythmen, die die Menschheit seit Jahrtausenden leiten.',
|
||||
next_full_moon: 'Nächster Vollmond',
|
||||
countdown_days: 'Tage',
|
||||
countdown_hours: 'Stunden',
|
||||
countdown_minutes: 'Min',
|
||||
countdown_seconds: 'Sek',
|
||||
calendar_title: 'Mondkalender',
|
||||
calendar_subtitle: 'Alle Mondphasen automatisch berechnet mit genauen Zeiten.',
|
||||
new_moon: 'Neumond',
|
||||
first_quarter: 'Erstes Viertel',
|
||||
full_moon: 'Vollmond',
|
||||
last_quarter: 'Letztes Viertel',
|
||||
waxing_crescent: 'Zunehmende Sichel',
|
||||
waxing_gibbous: 'Zunehmender Mond',
|
||||
waning_gibbous: 'Abnehmender Mond',
|
||||
waning_crescent: 'Abnehmende Sichel',
|
||||
fullmoons_title: 'Traditionelle Vollmond-Namen',
|
||||
fullmoons_subtitle: 'Jeder monatliche Vollmond trägt einen traditionellen Namen.',
|
||||
simulator_title: 'Mondphasen-Simulator',
|
||||
simulator_subtitle: 'Sehen Sie, wie der Mond an jedem Datum aussieht.',
|
||||
simulator_date: 'Datum wählen',
|
||||
simulator_illumination: 'Beleuchtung',
|
||||
simulator_age: 'Mondalter',
|
||||
simulator_days: 'Tage',
|
||||
simulator_zodiac: 'Sternzeichen',
|
||||
moon3d_title: '3D Mond-Visualisierung',
|
||||
moon3d_subtitle: 'Interaktives 3D-Modell — ziehen zum Drehen, scrollen zum Zoomen.',
|
||||
moon3d_drag: 'Ziehen zum Drehen',
|
||||
moon3d_scroll: 'Scrollen zum Zoomen',
|
||||
visibility_title: 'Mond-Sichtbarkeitskarte',
|
||||
visibility_subtitle: 'Sehen Sie, wo der Mond weltweit sichtbar ist.',
|
||||
articles_title: 'Mond-Artikel',
|
||||
articles_subtitle: 'Erkunde Geschichte, Mythologie und Wissenschaft des Mondes.',
|
||||
quiz_title: 'Mond-Quiz',
|
||||
quiz_subtitle: 'Teste dein Wissen über den Mond!',
|
||||
quiz_start: 'Quiz starten',
|
||||
quiz_next: 'Nächste Frage',
|
||||
quiz_results: 'Deine Ergebnisse',
|
||||
quiz_score: 'Punkte',
|
||||
quiz_restart: 'Neustart',
|
||||
quiz_correct: 'Richtig!',
|
||||
quiz_wrong: 'Falsch!',
|
||||
infographics_title: 'Mond-Infografiken',
|
||||
infographics_subtitle: 'Visuelle Daten über Mondphasen, Gezeiten und Zyklen.',
|
||||
pdf_download: 'PDF-Kalender herunterladen',
|
||||
pdf_title: 'Mondkalender',
|
||||
pdf_generated: 'Erstellt am',
|
||||
pdf_col_month: 'Monat',
|
||||
pdf_col_date: 'Datum',
|
||||
pdf_col_time: 'Zeit',
|
||||
pdf_col_name: 'Name',
|
||||
articles_read: 'Artikel lesen',
|
||||
months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
|
||||
loading: 'Laden...',
|
||||
current_phase: 'Aktuelle Phase',
|
||||
explore: 'Erkunden',
|
||||
learn_more: 'Mehr erfahren',
|
||||
footer_text: 'Mondphasen — Ihr kompletter Führer zum Mondzyklus',
|
||||
footer_description: 'Alle Monddaten automatisch durch astronomische Algorithmen berechnet.',
|
||||
culture_native: 'Indianisch',
|
||||
culture_celtic: 'Keltisch',
|
||||
culture_hindu: 'Hindu',
|
||||
culture_chinese: 'Chinesisch',
|
||||
effects_title: 'Auswirkungen',
|
||||
effects_human: 'Auf Menschen',
|
||||
effects_animals: 'Auf Tiere',
|
||||
effects_tides: 'Auf Gezeiten',
|
||||
phase_desc_new: 'Der Mond steht zwischen Erde und Sonne. Zeit für Neuanfänge.',
|
||||
phase_desc_waxing_crescent: 'Ein Lichtschimmer erscheint. Zeit für Absichten.',
|
||||
phase_desc_first_quarter: 'Die Hälfte des Mondes ist beleuchtet. Entscheidungszeit.',
|
||||
phase_desc_waxing_gibbous: 'Mehr als die Hälfte beleuchtet. Zeit zum Verfeinern.',
|
||||
phase_desc_full: 'Der Mond ist voll beleuchtet. Höchste Energie.',
|
||||
phase_desc_waning_gibbous: 'Das Licht beginnt zu schwinden. Zeit der Dankbarkeit.',
|
||||
phase_desc_last_quarter: 'Halb beleuchtet und abnehmend. Zeit des Loslassens.',
|
||||
phase_desc_waning_crescent: 'Eine schwindende Sichel. Ruhezeit.',
|
||||
},
|
||||
pt: {
|
||||
nav_home: 'Início', nav_calendar: 'Calendário', nav_fullmoons: 'Luas Cheias', nav_simulator: 'Simulador',
|
||||
nav_moon3d: 'Lua 3D', nav_articles: 'Artigos', nav_quiz: 'Quiz',
|
||||
hero_title: 'Descubra a Magia da Lua', hero_subtitle: 'Explore fases lunares e tradições.',
|
||||
next_full_moon: 'Próxima Lua Cheia', countdown_days: 'dias', countdown_hours: 'horas', countdown_minutes: 'min', countdown_seconds: 'seg',
|
||||
calendar_title: 'Calendário Lunar', calendar_subtitle: 'Fases calculadas automaticamente.',
|
||||
new_moon: 'Lua Nova', first_quarter: 'Quarto Crescente', full_moon: 'Lua Cheia', last_quarter: 'Quarto Minguante',
|
||||
waxing_crescent: 'Crescente', waxing_gibbous: 'Gibosa Crescente', waning_gibbous: 'Gibosa Minguante', waning_crescent: 'Minguante',
|
||||
fullmoons_title: 'Nomes Tradicionais', fullmoons_subtitle: 'Cada lua cheia tem um nome tradicional.',
|
||||
simulator_title: 'Simulador de Fases', simulator_subtitle: 'Veja a lua em qualquer data.',
|
||||
simulator_date: 'Selecione a data', simulator_illumination: 'Iluminação', simulator_age: 'Idade da Lua', simulator_days: 'dias', simulator_zodiac: 'Signo',
|
||||
moon3d_title: 'Lua 3D', moon3d_subtitle: 'Modelo interativo.', moon3d_drag: 'Arraste para girar', moon3d_scroll: 'Scroll para zoom',
|
||||
visibility_title: 'Visibilidade Lunar', visibility_subtitle: 'Onde a lua é visível agora.',
|
||||
articles_title: 'Artigos', articles_subtitle: 'História e ciência da lua.',
|
||||
quiz_title: 'Quiz Lunar', quiz_subtitle: 'Teste seus conhecimentos!',
|
||||
quiz_start: 'Iniciar', quiz_next: 'Próxima', quiz_results: 'Resultados', quiz_score: 'Pontos', quiz_restart: 'Reiniciar',
|
||||
quiz_correct: 'Correto!', quiz_wrong: 'Errado!',
|
||||
infographics_title: 'Infográficos', infographics_subtitle: 'Dados visuais sobre a lua.',
|
||||
pdf_download: 'Baixar PDF', pdf_title: 'Calendário Lunar',
|
||||
pdf_generated: 'Gerado em', pdf_col_month: 'Mês', pdf_col_date: 'Data', pdf_col_time: 'Hora', pdf_col_name: 'Nome', articles_read: 'Ler artigo',
|
||||
months: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho','Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
|
||||
loading: 'Carregando...', current_phase: 'Fase Atual', explore: 'Explorar', learn_more: 'Saiba mais',
|
||||
footer_text: 'Fases da Lua — Seu guia completo', footer_description: 'Dados calculados automaticamente.',
|
||||
culture_native: 'Nativo Americano', culture_celtic: 'Celta', culture_hindu: 'Hindu', culture_chinese: 'Chinês',
|
||||
effects_title: 'Efeitos', effects_human: 'Nos Humanos', effects_animals: 'Nos Animais', effects_tides: 'Nas Marés',
|
||||
phase_desc_new: 'Lua invisível. Novos começos.', phase_desc_waxing_crescent: 'Brilho aparece. Intenções.',
|
||||
phase_desc_first_quarter: 'Metade iluminada. Decisões.', phase_desc_waxing_gibbous: 'Mais da metade. Ajustar planos.',
|
||||
phase_desc_full: 'Totalmente iluminada. Energia máxima.', phase_desc_waning_gibbous: 'Luz diminui. Gratidão.',
|
||||
phase_desc_last_quarter: 'Metade e minguante. Liberação.', phase_desc_waning_crescent: 'Crescente sumindo. Descanso.',
|
||||
},
|
||||
it: {
|
||||
nav_home: 'Home', nav_calendar: 'Calendario', nav_fullmoons: 'Lune Piene', nav_simulator: 'Simulatore',
|
||||
nav_moon3d: 'Luna 3D', nav_articles: 'Articoli', nav_quiz: 'Quiz',
|
||||
hero_title: 'Scopri la Magia della Luna', hero_subtitle: 'Esplora fasi lunari e tradizioni.',
|
||||
next_full_moon: 'Prossima Luna Piena', countdown_days: 'giorni', countdown_hours: 'ore', countdown_minutes: 'min', countdown_seconds: 'sec',
|
||||
calendar_title: 'Calendario Lunare', calendar_subtitle: 'Fasi calcolate automaticamente.',
|
||||
new_moon: 'Luna Nuova', first_quarter: 'Primo Quarto', full_moon: 'Luna Piena', last_quarter: 'Ultimo Quarto',
|
||||
waxing_crescent: 'Crescente', waxing_gibbous: 'Gibbosa Crescente', waning_gibbous: 'Gibbosa Calante', waning_crescent: 'Calante',
|
||||
fullmoons_title: 'Nomi Tradizionali', fullmoons_subtitle: 'Ogni luna piena ha un nome tradizionale.',
|
||||
simulator_title: 'Simulatore di Fasi', simulator_subtitle: 'Vedi la luna in qualsiasi data.',
|
||||
simulator_date: 'Seleziona data', simulator_illumination: 'Illuminazione', simulator_age: 'Età della Luna', simulator_days: 'giorni', simulator_zodiac: 'Segno',
|
||||
moon3d_title: 'Luna 3D', moon3d_subtitle: 'Modello interattivo.', moon3d_drag: 'Trascina per ruotare', moon3d_scroll: 'Scorri per zoom',
|
||||
visibility_title: 'Visibilità Lunare', visibility_subtitle: 'Dove la luna è visibile ora.',
|
||||
articles_title: 'Articoli', articles_subtitle: 'Storia e scienza della luna.',
|
||||
quiz_title: 'Quiz Lunare', quiz_subtitle: 'Metti alla prova le tue conoscenze!',
|
||||
quiz_start: 'Inizia', quiz_next: 'Prossima', quiz_results: 'Risultati', quiz_score: 'Punteggio', quiz_restart: 'Ricomincia',
|
||||
quiz_correct: 'Corretto!', quiz_wrong: 'Sbagliato!',
|
||||
infographics_title: 'Infografiche', infographics_subtitle: 'Dati visivi sulla luna.',
|
||||
pdf_download: 'Scarica PDF', pdf_title: 'Calendario Lunare',
|
||||
pdf_generated: 'Generato il', pdf_col_month: 'Mese', pdf_col_date: 'Data', pdf_col_time: 'Ora', pdf_col_name: 'Nome', articles_read: 'Leggi articolo',
|
||||
months: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno','Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],
|
||||
loading: 'Caricamento...', current_phase: 'Fase Attuale', explore: 'Esplora', learn_more: 'Scopri di più',
|
||||
footer_text: 'Fasi della Luna — La tua guida completa', footer_description: 'Dati calcolati automaticamente.',
|
||||
culture_native: 'Nativi Americani', culture_celtic: 'Celtico', culture_hindu: 'Indù', culture_chinese: 'Cinese',
|
||||
effects_title: 'Effetti', effects_human: 'Sugli Umani', effects_animals: 'Sugli Animali', effects_tides: 'Sulle Maree',
|
||||
phase_desc_new: 'Luna invisibile. Nuovi inizi.', phase_desc_waxing_crescent: 'Brilla una luce. Intenzioni.',
|
||||
phase_desc_first_quarter: 'Metà illuminata. Decisioni.', phase_desc_waxing_gibbous: 'Più della metà. Affinare.',
|
||||
phase_desc_full: 'Completamente illuminata. Massima energia.', phase_desc_waning_gibbous: 'Luce cala. Gratitudine.',
|
||||
phase_desc_last_quarter: 'Metà calante. Lasciare andare.', phase_desc_waning_crescent: 'Falce che svanisce. Riposo.',
|
||||
},
|
||||
ja: {
|
||||
nav_home: 'ホーム', nav_calendar: 'カレンダー', nav_fullmoons: '満月', nav_simulator: 'シミュレータ',
|
||||
nav_moon3d: '3D月', nav_articles: '記事', nav_quiz: 'クイズ',
|
||||
hero_title: '月の魔法を発見しよう', hero_subtitle: '月の満ち欠け、満月の伝統、宇宙のリズムを探索。',
|
||||
next_full_moon: '次の満月', countdown_days: '日', countdown_hours: '時間', countdown_minutes: '分', countdown_seconds: '秒',
|
||||
calendar_title: '月暦', calendar_subtitle: '全ての月相を自動計算。',
|
||||
new_moon: '新月', first_quarter: '上弦の月', full_moon: '満月', last_quarter: '下弦の月',
|
||||
waxing_crescent: '三日月', waxing_gibbous: '十三夜月', waning_gibbous: '更待月', waning_crescent: '二十六夜',
|
||||
fullmoons_title: '伝統的な満月の名前', fullmoons_subtitle: '毎月の満月には伝統的な名前があります。',
|
||||
simulator_title: '月相シミュレータ', simulator_subtitle: '任意の日の月を確認。',
|
||||
simulator_date: '日付を選択', simulator_illumination: '輝面比', simulator_age: '月齢', simulator_days: '日', simulator_zodiac: '星座',
|
||||
moon3d_title: '3D月', moon3d_subtitle: 'インタラクティブ3Dモデル。', moon3d_drag: 'ドラッグで回転', moon3d_scroll: 'スクロールでズーム',
|
||||
visibility_title: '月の可視性マップ', visibility_subtitle: '世界中で月が見える場所。',
|
||||
articles_title: '記事', articles_subtitle: '月の歴史と科学。',
|
||||
quiz_title: '月クイズ', quiz_subtitle: '月の知識をテスト!',
|
||||
quiz_start: '開始', quiz_next: '次へ', quiz_results: '結果', quiz_score: 'スコア', quiz_restart: '再開',
|
||||
quiz_correct: '正解!', quiz_wrong: '不正解!',
|
||||
infographics_title: 'インフォグラフィック', infographics_subtitle: '月のデータを視覚化。',
|
||||
pdf_download: 'PDFダウンロード', pdf_title: '月暦',
|
||||
pdf_generated: '生成日', pdf_col_month: '月', pdf_col_date: '日付', pdf_col_time: '時間', pdf_col_name: '名前', articles_read: '記事を読む',
|
||||
months: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
|
||||
loading: '読み込み中...', current_phase: '現在の月相', explore: '探索', learn_more: '詳しく',
|
||||
footer_text: '月の満ち欠け — 完全ガイド', footer_description: '天文アルゴリズムで自動計算。',
|
||||
culture_native: 'ネイティブアメリカン', culture_celtic: 'ケルト', culture_hindu: 'ヒンドゥー', culture_chinese: '中国',
|
||||
effects_title: '影響', effects_human: '人間への影響', effects_animals: '動物への影響', effects_tides: '潮汐への影響',
|
||||
phase_desc_new: '月は見えません。新しい始まり。', phase_desc_waxing_crescent: '光が現れる。意図を設定。',
|
||||
phase_desc_first_quarter: '半分が照らされる。決断の時。', phase_desc_waxing_gibbous: '半分以上。計画を調整。',
|
||||
phase_desc_full: '完全に照らされる。最大エネルギー。', phase_desc_waning_gibbous: '光が減少。感謝の時。',
|
||||
phase_desc_last_quarter: '半分で減少中。手放す時。', phase_desc_waning_crescent: '消えゆく三日月。休息。',
|
||||
},
|
||||
zh: {
|
||||
nav_home: '首页', nav_calendar: '日历', nav_fullmoons: '满月', nav_simulator: '模拟器',
|
||||
nav_moon3d: '3D月球', nav_articles: '文章', nav_quiz: '测验',
|
||||
hero_title: '探索月亮的魔力', hero_subtitle: '探索月相、满月传统和宇宙节律。',
|
||||
next_full_moon: '下一个满月', countdown_days: '天', countdown_hours: '小时', countdown_minutes: '分', countdown_seconds: '秒',
|
||||
calendar_title: '月历', calendar_subtitle: '自动计算所有月相。',
|
||||
new_moon: '新月', first_quarter: '上弦月', full_moon: '满月', last_quarter: '下弦月',
|
||||
waxing_crescent: '娥眉月', waxing_gibbous: '盈凸月', waning_gibbous: '亏凸月', waning_crescent: '残月',
|
||||
fullmoons_title: '传统满月名称', fullmoons_subtitle: '每个月的满月都有传统名称。',
|
||||
simulator_title: '月相模拟器', simulator_subtitle: '查看任意日期的月亮。',
|
||||
simulator_date: '选择日期', simulator_illumination: '照明度', simulator_age: '月龄', simulator_days: '天', simulator_zodiac: '星座',
|
||||
moon3d_title: '3D月球', moon3d_subtitle: '交互式3D模型。', moon3d_drag: '拖动旋转', moon3d_scroll: '滚动缩放',
|
||||
visibility_title: '月球可见性地图', visibility_subtitle: '查看月球在全球的可见位置。',
|
||||
articles_title: '文章', articles_subtitle: '月球的历史和科学。',
|
||||
quiz_title: '月球测验', quiz_subtitle: '测试你的月球知识!',
|
||||
quiz_start: '开始', quiz_next: '下一题', quiz_results: '结果', quiz_score: '得分', quiz_restart: '重新开始',
|
||||
quiz_correct: '正确!', quiz_wrong: '错误!',
|
||||
infographics_title: '信息图', infographics_subtitle: '月球数据可视化。',
|
||||
pdf_download: '下载PDF', pdf_title: '月历',
|
||||
pdf_generated: '生成于', pdf_col_month: '月份', pdf_col_date: '日期', pdf_col_time: '时间', pdf_col_name: '名称', articles_read: '阅读文章',
|
||||
months: ['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'],
|
||||
loading: '加载中...', current_phase: '当前月相', explore: '探索', learn_more: '了解更多',
|
||||
footer_text: '月相 — 完整指南', footer_description: '天文算法自动计算。',
|
||||
culture_native: '美洲原住民', culture_celtic: '凯尔特', culture_hindu: '印度教', culture_chinese: '中国',
|
||||
effects_title: '影响', effects_human: '对人类', effects_animals: '对动物', effects_tides: '对潮汐',
|
||||
phase_desc_new: '月亮不可见。新的开始。', phase_desc_waxing_crescent: '光芒出现。设定意图。',
|
||||
phase_desc_first_quarter: '一半被照亮。做出决定。', phase_desc_waxing_gibbous: '超过一半。调整计划。',
|
||||
phase_desc_full: '完全被照亮。最大能量。', phase_desc_waning_gibbous: '光线减弱。感恩时刻。',
|
||||
phase_desc_last_quarter: '一半减弱。放下。', phase_desc_waning_crescent: '消逝的月牙。休息。',
|
||||
},
|
||||
ar: {
|
||||
nav_home: 'الرئيسية', nav_calendar: 'التقويم', nav_fullmoons: 'البدر', nav_simulator: 'المحاكي',
|
||||
nav_moon3d: 'القمر ثلاثي الأبعاد', nav_articles: 'مقالات', nav_quiz: 'اختبار',
|
||||
hero_title: 'اكتشف سحر القمر', hero_subtitle: 'استكشف أطوار القمر والتقاليد.',
|
||||
next_full_moon: 'البدر القادم', countdown_days: 'أيام', countdown_hours: 'ساعات', countdown_minutes: 'دقائق', countdown_seconds: 'ثوان',
|
||||
calendar_title: 'التقويم القمري', calendar_subtitle: 'جميع أطوار القمر محسوبة تلقائياً.',
|
||||
new_moon: 'محاق', first_quarter: 'تربيع أول', full_moon: 'بدر', last_quarter: 'تربيع أخير',
|
||||
waxing_crescent: 'هلال متزايد', waxing_gibbous: 'أحدب متزايد', waning_gibbous: 'أحدب متناقص', waning_crescent: 'هلال متناقص',
|
||||
fullmoons_title: 'أسماء البدر التقليدية', fullmoons_subtitle: 'لكل بدر شهري اسم تقليدي.',
|
||||
simulator_title: 'محاكي أطوار القمر', simulator_subtitle: 'شاهد القمر في أي تاريخ.',
|
||||
simulator_date: 'اختر تاريخاً', simulator_illumination: 'الإضاءة', simulator_age: 'عمر القمر', simulator_days: 'أيام', simulator_zodiac: 'البرج',
|
||||
moon3d_title: 'القمر ثلاثي الأبعاد', moon3d_subtitle: 'نموذج تفاعلي.', moon3d_drag: 'اسحب للتدوير', moon3d_scroll: 'مرر للتكبير',
|
||||
visibility_title: 'خريطة رؤية القمر', visibility_subtitle: 'أين القمر مرئي الآن.',
|
||||
articles_title: 'مقالات', articles_subtitle: 'تاريخ وعلم القمر.',
|
||||
quiz_title: 'اختبار القمر', quiz_subtitle: 'اختبر معلوماتك!',
|
||||
quiz_start: 'ابدأ', quiz_next: 'التالي', quiz_results: 'النتائج', quiz_score: 'النقاط', quiz_restart: 'إعادة',
|
||||
quiz_correct: 'صحيح!', quiz_wrong: 'خطأ!',
|
||||
infographics_title: 'رسوم بيانية', infographics_subtitle: 'بيانات مرئية عن القمر.',
|
||||
pdf_download: 'تحميل PDF', pdf_title: 'التقويم القمري',
|
||||
pdf_generated: 'تم الإنشاء', pdf_col_month: 'الشهر', pdf_col_date: 'التاريخ', pdf_col_time: 'الوقت', pdf_col_name: 'الاسم', articles_read: 'اقرأ المقال',
|
||||
months: ['يناير','فبراير','مارس','أبريل','مايو','يونيو','يوليو','أغسطس','سبتمبر','أكتوبر','نوفمبر','ديسمبر'],
|
||||
loading: 'جاري التحميل...', current_phase: 'الطور الحالي', explore: 'استكشف', learn_more: 'اعرف المزيد',
|
||||
footer_text: 'أطوار القمر — دليلك الكامل', footer_description: 'محسوبة تلقائياً.',
|
||||
culture_native: 'أمريكي أصلي', culture_celtic: 'كلتي', culture_hindu: 'هندوسي', culture_chinese: 'صيني',
|
||||
effects_title: 'التأثيرات', effects_human: 'على البشر', effects_animals: 'على الحيوانات', effects_tides: 'على المد والجزر',
|
||||
phase_desc_new: 'القمر غير مرئي. بدايات جديدة.', phase_desc_waxing_crescent: 'يظهر ضوء. وقت النوايا.',
|
||||
phase_desc_first_quarter: 'نصف مضاء. وقت القرارات.', phase_desc_waxing_gibbous: 'أكثر من النصف. تعديل الخطط.',
|
||||
phase_desc_full: 'مضاء بالكامل. أقصى طاقة.', phase_desc_waning_gibbous: 'يتراجع الضوء. وقت الامتنان.',
|
||||
phase_desc_last_quarter: 'نصف متناقص. وقت التحرر.', phase_desc_waning_crescent: 'هلال يتلاشى. راحة.',
|
||||
},
|
||||
ru: {
|
||||
nav_home: 'Главная', nav_calendar: 'Календарь', nav_fullmoons: 'Полнолуния', nav_simulator: 'Симулятор',
|
||||
nav_moon3d: '3D Луна', nav_articles: 'Статьи', nav_quiz: 'Викторина',
|
||||
hero_title: 'Откройте Магию Луны', hero_subtitle: 'Исследуйте фазы Луны и традиции.',
|
||||
next_full_moon: 'Следующее Полнолуние', countdown_days: 'дней', countdown_hours: 'часов', countdown_minutes: 'мин', countdown_seconds: 'сек',
|
||||
calendar_title: 'Лунный Календарь', calendar_subtitle: 'Все фазы рассчитаны автоматически.',
|
||||
new_moon: 'Новолуние', first_quarter: 'Первая четверть', full_moon: 'Полнолуние', last_quarter: 'Последняя четверть',
|
||||
waxing_crescent: 'Растущий серп', waxing_gibbous: 'Растущая Луна', waning_gibbous: 'Убывающая Луна', waning_crescent: 'Убывающий серп',
|
||||
fullmoons_title: 'Традиционные Названия', fullmoons_subtitle: 'У каждого полнолуния есть традиционное название.',
|
||||
simulator_title: 'Симулятор Фаз', simulator_subtitle: 'Посмотрите Луну на любую дату.',
|
||||
simulator_date: 'Выберите дату', simulator_illumination: 'Освещённость', simulator_age: 'Возраст Луны', simulator_days: 'дней', simulator_zodiac: 'Знак зодиака',
|
||||
moon3d_title: '3D Луна', moon3d_subtitle: 'Интерактивная модель.', moon3d_drag: 'Тяните для вращения', moon3d_scroll: 'Прокрутка для масштаба',
|
||||
visibility_title: 'Карта Видимости', visibility_subtitle: 'Где Луна видна сейчас.',
|
||||
articles_title: 'Статьи', articles_subtitle: 'История и наука о Луне.',
|
||||
quiz_title: 'Лунная Викторина', quiz_subtitle: 'Проверьте свои знания!',
|
||||
quiz_start: 'Начать', quiz_next: 'Далее', quiz_results: 'Результаты', quiz_score: 'Баллы', quiz_restart: 'Заново',
|
||||
quiz_correct: 'Верно!', quiz_wrong: 'Неверно!',
|
||||
infographics_title: 'Инфографика', infographics_subtitle: 'Визуальные данные о Луне.',
|
||||
pdf_download: 'Скачать PDF', pdf_title: 'Лунный Календарь',
|
||||
pdf_generated: 'Создано', pdf_col_month: 'Месяц', pdf_col_date: 'Дата', pdf_col_time: 'Время', pdf_col_name: 'Название', articles_read: 'Читать статью',
|
||||
months: ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],
|
||||
loading: 'Загрузка...', current_phase: 'Текущая фаза', explore: 'Исследовать', learn_more: 'Подробнее',
|
||||
footer_text: 'Фазы Луны — Полное руководство', footer_description: 'Рассчитано автоматически.',
|
||||
culture_native: 'Индейский', culture_celtic: 'Кельтский', culture_hindu: 'Индуистский', culture_chinese: 'Китайский',
|
||||
effects_title: 'Влияние', effects_human: 'На людей', effects_animals: 'На животных', effects_tides: 'На приливы',
|
||||
phase_desc_new: 'Луна не видна. Новые начинания.', phase_desc_waxing_crescent: 'Появляется свет. Время намерений.',
|
||||
phase_desc_first_quarter: 'Половина освещена. Время решений.', phase_desc_waxing_gibbous: 'Больше половины. Корректировка.',
|
||||
phase_desc_full: 'Полностью освещена. Максимальная энергия.', phase_desc_waning_gibbous: 'Свет убывает. Благодарность.',
|
||||
phase_desc_last_quarter: 'Половина убывает. Отпускание.', phase_desc_waning_crescent: 'Тающий серп. Отдых.',
|
||||
},
|
||||
hi: {
|
||||
nav_home: 'होम', nav_calendar: 'कैलेंडर', nav_fullmoons: 'पूर्णिमा', nav_simulator: 'सिम्युलेटर',
|
||||
nav_moon3d: '3D चंद्रमा', nav_articles: 'लेख', nav_quiz: 'क्विज़',
|
||||
hero_title: 'चंद्रमा का जादू खोजें', hero_subtitle: 'चंद्र कलाओं और परंपराओं का अन्वेषण करें।',
|
||||
next_full_moon: 'अगली पूर्णिमा', countdown_days: 'दिन', countdown_hours: 'घंटे', countdown_minutes: 'मिनट', countdown_seconds: 'सेकंड',
|
||||
calendar_title: 'चंद्र कैलेंडर', calendar_subtitle: 'सभी चंद्र कलाएं स्वचालित रूप से गणना।',
|
||||
new_moon: 'अमावस्या', first_quarter: 'शुक्ल पक्ष', full_moon: 'पूर्णिमा', last_quarter: 'कृष्ण पक्ष',
|
||||
waxing_crescent: 'बढ़ता हिलाल', waxing_gibbous: 'बढ़ता चंद्र', waning_gibbous: 'घटता चंद्र', waning_crescent: 'घटता हिलाल',
|
||||
fullmoons_title: 'पारंपरिक नाम', fullmoons_subtitle: 'हर पूर्णिमा का एक पारंपरिक नाम है।',
|
||||
simulator_title: 'चंद्र कला सिम्युलेटर', simulator_subtitle: 'किसी भी तारीख का चंद्रमा देखें।',
|
||||
simulator_date: 'तारीख चुनें', simulator_illumination: 'प्रकाश', simulator_age: 'चंद्र आयु', simulator_days: 'दिन', simulator_zodiac: 'राशि',
|
||||
moon3d_title: '3D चंद्रमा', moon3d_subtitle: 'इंटरैक्टिव मॉडल।', moon3d_drag: 'घुमाने के लिए खींचें', moon3d_scroll: 'ज़ूम के लिए स्क्रॉल',
|
||||
visibility_title: 'दृश्यता मानचित्र', visibility_subtitle: 'चंद्रमा कहाँ दिखाई दे रहा है।',
|
||||
articles_title: 'लेख', articles_subtitle: 'चंद्रमा का इतिहास और विज्ञान।',
|
||||
quiz_title: 'चंद्र क्विज़', quiz_subtitle: 'अपना ज्ञान परखें!',
|
||||
quiz_start: 'शुरू करें', quiz_next: 'अगला', quiz_results: 'परिणाम', quiz_score: 'अंक', quiz_restart: 'पुनः आरंभ',
|
||||
quiz_correct: 'सही!', quiz_wrong: 'गलत!',
|
||||
infographics_title: 'इन्फ़ोग्राफ़िक्स', infographics_subtitle: 'दृश्य डेटा।',
|
||||
pdf_download: 'PDF डाउनलोड', pdf_title: 'चंद्र कैलेंडर',
|
||||
pdf_generated: 'बनाया गया', pdf_col_month: 'महीना', pdf_col_date: 'तारीख', pdf_col_time: 'समय', pdf_col_name: 'नाम', articles_read: 'लेख पढ़ें',
|
||||
months: ['जनवरी','फरवरी','मार्च','अप्रैल','मई','जून','जुलाई','अगस्त','सितंबर','अक्टूबर','नवंबर','दिसंबर'],
|
||||
loading: 'लोड हो रहा है...', current_phase: 'वर्तमान कला', explore: 'अन्वेषण', learn_more: 'और जानें',
|
||||
footer_text: 'चंद्र कलाएं — पूर्ण गाइड', footer_description: 'स्वचालित रूप से गणना।',
|
||||
culture_native: 'मूल अमेरिकी', culture_celtic: 'केल्टिक', culture_hindu: 'हिंदू', culture_chinese: 'चीनी',
|
||||
effects_title: 'प्रभाव', effects_human: 'मनुष्यों पर', effects_animals: 'जानवरों पर', effects_tides: 'ज्वार पर',
|
||||
phase_desc_new: 'चंद्रमा अदृश्य। नई शुरुआत।', phase_desc_waxing_crescent: 'प्रकाश दिखता है। इरादे तय करें।',
|
||||
phase_desc_first_quarter: 'आधा प्रकाशित। निर्णय का समय।', phase_desc_waxing_gibbous: 'आधे से अधिक। योजना समायोजन।',
|
||||
phase_desc_full: 'पूर्ण प्रकाशित। अधिकतम ऊर्जा।', phase_desc_waning_gibbous: 'प्रकाश कम। कृतज्ञता।',
|
||||
phase_desc_last_quarter: 'आधा घटता। छोड़ना।', phase_desc_waning_crescent: 'मिटता हिलाल। विश्राम।',
|
||||
},
|
||||
};
|
||||
|
||||
export function t(key: keyof TranslationKeys, locale: Locale = 'en'): string | string[] {
|
||||
return translations[locale]?.[key] ?? translations.en[key] ?? key;
|
||||
}
|
||||
|
||||
export function ts(key: keyof TranslationKeys, locale: Locale = 'en'): string {
|
||||
const val = t(key, locale);
|
||||
return Array.isArray(val) ? val.join(', ') : val;
|
||||
}
|
||||
|
||||
export function getMonths(locale: Locale = 'en'): string[] {
|
||||
return translations[locale]?.months ?? translations.en.months;
|
||||
}
|
||||
|
||||
export function detectLocale(): Locale {
|
||||
if (typeof navigator === 'undefined') return 'en';
|
||||
const lang = navigator.language?.slice(0, 2) as Locale;
|
||||
return translations[lang] ? lang : 'en';
|
||||
}
|
||||
+500
@@ -0,0 +1,500 @@
|
||||
/**
|
||||
* Lunar Calculation Engine
|
||||
* Based on Jean Meeus' Astronomical Algorithms
|
||||
* Calculates moon phases, illumination, age, and positions
|
||||
*/
|
||||
|
||||
// Synodic month (average lunation period) in days
|
||||
const SYNODIC_MONTH = 29.53058868;
|
||||
|
||||
// Known new moon reference: January 6, 2000, 18:14 UTC (Julian date)
|
||||
const KNOWN_NEW_MOON_JD = 2451550.1;
|
||||
|
||||
export type MoonPhaseName = 'new_moon' | 'waxing_crescent' | 'first_quarter' | 'waxing_gibbous' | 'full_moon' | 'waning_gibbous' | 'last_quarter' | 'waning_crescent';
|
||||
|
||||
export interface MoonPhaseInfo {
|
||||
phase: number; // 0-1 (0 = new moon, 0.5 = full moon)
|
||||
phaseName: MoonPhaseName;
|
||||
illumination: number; // 0-100%
|
||||
age: number; // days since new moon
|
||||
emoji: string;
|
||||
angleDeg: number; // 0-360
|
||||
}
|
||||
|
||||
export interface MoonEvent {
|
||||
date: Date;
|
||||
phase: 'new_moon' | 'first_quarter' | 'full_moon' | 'last_quarter';
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface FullMoonInfo {
|
||||
date: Date;
|
||||
traditionalName: string;
|
||||
month: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Date to Julian Date
|
||||
*/
|
||||
export function dateToJD(date: Date): number {
|
||||
const y = date.getUTCFullYear();
|
||||
const m = date.getUTCMonth() + 1;
|
||||
const d = date.getUTCDate() + date.getUTCHours() / 24 + date.getUTCMinutes() / 1440 + date.getUTCSeconds() / 86400;
|
||||
|
||||
let yr = y;
|
||||
let mo = m;
|
||||
if (mo <= 2) {
|
||||
yr -= 1;
|
||||
mo += 12;
|
||||
}
|
||||
|
||||
const A = Math.floor(yr / 100);
|
||||
const B = 2 - A + Math.floor(A / 4);
|
||||
|
||||
return Math.floor(365.25 * (yr + 4716)) + Math.floor(30.6001 * (mo + 1)) + d + B - 1524.5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Julian Date to Date
|
||||
*/
|
||||
export function jdToDate(jd: number): Date {
|
||||
const z = Math.floor(jd + 0.5);
|
||||
const f = jd + 0.5 - z;
|
||||
let A: number;
|
||||
|
||||
if (z < 2299161) {
|
||||
A = z;
|
||||
} else {
|
||||
const alpha = Math.floor((z - 1867216.25) / 36524.25);
|
||||
A = z + 1 + alpha - Math.floor(alpha / 4);
|
||||
}
|
||||
|
||||
const B = A + 1524;
|
||||
const C = Math.floor((B - 122.1) / 365.25);
|
||||
const D = Math.floor(365.25 * C);
|
||||
const E = Math.floor((B - D) / 30.6001);
|
||||
|
||||
const day = B - D - Math.floor(30.6001 * E);
|
||||
const month = E < 14 ? E - 1 : E - 13;
|
||||
const year = month > 2 ? C - 4716 : C - 4715;
|
||||
|
||||
const hours = f * 24;
|
||||
const h = Math.floor(hours);
|
||||
const mins = Math.floor((hours - h) * 60);
|
||||
const secs = Math.floor(((hours - h) * 60 - mins) * 60);
|
||||
|
||||
return new Date(Date.UTC(year, month - 1, day, h, mins, secs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate moon phase for a given date
|
||||
* Returns a value between 0 and 1 (0 = new moon, 0.5 = full moon)
|
||||
*/
|
||||
export function getMoonPhase(date: Date): number {
|
||||
const jd = dateToJD(date);
|
||||
const daysSinceNew = jd - KNOWN_NEW_MOON_JD;
|
||||
const cycles = daysSinceNew / SYNODIC_MONTH;
|
||||
const phase = cycles - Math.floor(cycles);
|
||||
return phase < 0 ? phase + 1 : phase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get detailed moon phase information
|
||||
*/
|
||||
export function getMoonPhaseInfo(date: Date): MoonPhaseInfo {
|
||||
const phase = getMoonPhase(date);
|
||||
const age = phase * SYNODIC_MONTH;
|
||||
const angleDeg = phase * 360;
|
||||
|
||||
// Illumination (simplified: 0 at new moon, 100 at full moon)
|
||||
const illumination = Math.round((1 - Math.cos(phase * 2 * Math.PI)) / 2 * 100);
|
||||
|
||||
let phaseName: MoonPhaseName;
|
||||
let emoji: string;
|
||||
|
||||
if (phase < 0.0625) {
|
||||
phaseName = 'new_moon';
|
||||
emoji = '🌑';
|
||||
} else if (phase < 0.1875) {
|
||||
phaseName = 'waxing_crescent';
|
||||
emoji = '🌒';
|
||||
} else if (phase < 0.3125) {
|
||||
phaseName = 'first_quarter';
|
||||
emoji = '🌓';
|
||||
} else if (phase < 0.4375) {
|
||||
phaseName = 'waxing_gibbous';
|
||||
emoji = '🌔';
|
||||
} else if (phase < 0.5625) {
|
||||
phaseName = 'full_moon';
|
||||
emoji = '🌕';
|
||||
} else if (phase < 0.6875) {
|
||||
phaseName = 'waning_gibbous';
|
||||
emoji = '🌖';
|
||||
} else if (phase < 0.8125) {
|
||||
phaseName = 'last_quarter';
|
||||
emoji = '🌗';
|
||||
} else if (phase < 0.9375) {
|
||||
phaseName = 'waning_crescent';
|
||||
emoji = '🌘';
|
||||
} else {
|
||||
phaseName = 'new_moon';
|
||||
emoji = '🌑';
|
||||
}
|
||||
|
||||
return { phase, phaseName, illumination, age, emoji, angleDeg };
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate more precise moon phase times using iterative refinement
|
||||
* targetPhase: 0 = new, 0.25 = first quarter, 0.5 = full, 0.75 = last quarter
|
||||
*/
|
||||
function findPhaseEvent(startJD: number, targetPhase: number): number {
|
||||
// Search forward from startJD
|
||||
let jd = startJD;
|
||||
const step = 1; // 1 day step
|
||||
|
||||
// Coarse search
|
||||
let prevDiff = 999;
|
||||
for (let i = 0; i < 35; i++) {
|
||||
const daysSinceNew = (jd + i * step) - KNOWN_NEW_MOON_JD;
|
||||
const cycles = daysSinceNew / SYNODIC_MONTH;
|
||||
const phase = cycles - Math.floor(cycles);
|
||||
let diff = phase - targetPhase;
|
||||
if (diff < -0.5) diff += 1;
|
||||
if (diff > 0.5) diff -= 1;
|
||||
const absDiff = Math.abs(diff);
|
||||
|
||||
if (absDiff < prevDiff) {
|
||||
prevDiff = absDiff;
|
||||
jd = startJD + i * step;
|
||||
}
|
||||
}
|
||||
|
||||
// Fine search: binary search refinement
|
||||
let lo = jd - 1;
|
||||
let hi = jd + 1;
|
||||
|
||||
for (let iter = 0; iter < 50; iter++) {
|
||||
const mid = (lo + hi) / 2;
|
||||
const daysSinceNew = mid - KNOWN_NEW_MOON_JD;
|
||||
const cycles = daysSinceNew / SYNODIC_MONTH;
|
||||
const phase = cycles - Math.floor(cycles);
|
||||
let diff = phase - targetPhase;
|
||||
if (diff < -0.5) diff += 1;
|
||||
if (diff > 0.5) diff -= 1;
|
||||
|
||||
if (Math.abs(diff) < 0.00001) break;
|
||||
|
||||
if (diff < 0) {
|
||||
lo = mid;
|
||||
} else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
|
||||
return (lo + hi) / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all moon phase events for a given year
|
||||
*/
|
||||
export function getMoonEventsForYear(year: number): MoonEvent[] {
|
||||
const events: MoonEvent[] = [];
|
||||
const startJD = dateToJD(new Date(Date.UTC(year, 0, 1)));
|
||||
const endJD = dateToJD(new Date(Date.UTC(year, 11, 31, 23, 59, 59)));
|
||||
|
||||
const phases: { target: number; name: 'new_moon' | 'first_quarter' | 'full_moon' | 'last_quarter' }[] = [
|
||||
{ target: 0, name: 'new_moon' },
|
||||
{ target: 0.25, name: 'first_quarter' },
|
||||
{ target: 0.5, name: 'full_moon' },
|
||||
{ target: 0.75, name: 'last_quarter' },
|
||||
];
|
||||
|
||||
// Start from a bit before the year to catch early events
|
||||
const searchStart = startJD - 35;
|
||||
|
||||
for (const { target, name } of phases) {
|
||||
// Find all occurrences through the year
|
||||
let currentJD = searchStart;
|
||||
while (currentJD < endJD + 1) {
|
||||
const eventJD = findPhaseEvent(currentJD, target);
|
||||
if (eventJD >= startJD && eventJD <= endJD + 1) {
|
||||
const date = jdToDate(eventJD);
|
||||
if (date.getUTCFullYear() === year) {
|
||||
events.push({ date, phase: name, name });
|
||||
}
|
||||
}
|
||||
currentJD = eventJD + 25; // Jump ~25 days to find next cycle
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by date
|
||||
events.sort((a, b) => a.date.getTime() - b.date.getTime());
|
||||
|
||||
// Remove duplicates (same phase within 2 days)
|
||||
const filtered: MoonEvent[] = [];
|
||||
for (const event of events) {
|
||||
const isDuplicate = filtered.some(
|
||||
(e) => e.phase === event.phase && Math.abs(e.date.getTime() - event.date.getTime()) < 2 * 24 * 60 * 60 * 1000
|
||||
);
|
||||
if (!isDuplicate) {
|
||||
filtered.push(event);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next full moon from a given date
|
||||
*/
|
||||
export function getNextFullMoon(from: Date = new Date()): Date {
|
||||
const jd = dateToJD(from);
|
||||
const eventJD = findPhaseEvent(jd, 0.5);
|
||||
const result = jdToDate(eventJD);
|
||||
|
||||
// If result is in the past, search from a bit later
|
||||
if (result.getTime() < from.getTime()) {
|
||||
const nextJD = findPhaseEvent(jd + 25, 0.5);
|
||||
return jdToDate(nextJD);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next new moon from a given date
|
||||
*/
|
||||
export function getNextNewMoon(from: Date = new Date()): Date {
|
||||
const jd = dateToJD(from);
|
||||
const eventJD = findPhaseEvent(jd, 0);
|
||||
const result = jdToDate(eventJD);
|
||||
|
||||
if (result.getTime() < from.getTime()) {
|
||||
const nextJD = findPhaseEvent(jd + 25, 0);
|
||||
return jdToDate(nextJD);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traditional full moon names by month (Northern Hemisphere)
|
||||
*/
|
||||
export const FULL_MOON_NAMES: Record<number, { en: string; fr: string; es: string; de: string; pt: string; it: string; ja: string; zh: string; ar: string; ru: string; hi: string }> = {
|
||||
1: {
|
||||
en: 'Wolf Moon', fr: 'Lune du Loup', es: 'Luna del Lobo', de: 'Wolfsmond',
|
||||
pt: 'Lua do Lobo', it: 'Luna del Lupo', ja: 'ウルフムーン', zh: '狼月',
|
||||
ar: 'قمر الذئب', ru: 'Волчья Луна', hi: 'भेड़िया चंद्रमा'
|
||||
},
|
||||
2: {
|
||||
en: 'Snow Moon', fr: 'Lune de Neige', es: 'Luna de Nieve', de: 'Schneemond',
|
||||
pt: 'Lua da Neve', it: 'Luna della Neve', ja: 'スノームーン', zh: '雪月',
|
||||
ar: 'قمر الثلج', ru: 'Снежная Луна', hi: 'हिम चंद्रमा'
|
||||
},
|
||||
3: {
|
||||
en: 'Worm Moon', fr: 'Lune du Ver', es: 'Luna del Gusano', de: 'Wurmmond',
|
||||
pt: 'Lua da Minhoca', it: 'Luna del Verme', ja: 'ワームムーン', zh: '蠕虫月',
|
||||
ar: 'قمر الدودة', ru: 'Червячная Луна', hi: 'कीट चंद्रमा'
|
||||
},
|
||||
4: {
|
||||
en: 'Pink Moon', fr: 'Lune Rose', es: 'Luna Rosa', de: 'Rosa Mond',
|
||||
pt: 'Lua Rosa', it: 'Luna Rosa', ja: 'ピンクムーン', zh: '粉红月',
|
||||
ar: 'القمر الوردي', ru: 'Розовая Луна', hi: 'गुलाबी चंद्रमा'
|
||||
},
|
||||
5: {
|
||||
en: 'Flower Moon', fr: 'Lune des Fleurs', es: 'Luna de las Flores', de: 'Blumenmond',
|
||||
pt: 'Lua das Flores', it: 'Luna dei Fiori', ja: 'フラワームーン', zh: '花月',
|
||||
ar: 'قمر الزهور', ru: 'Цветочная Луна', hi: 'फूल चंद्रमा'
|
||||
},
|
||||
6: {
|
||||
en: 'Strawberry Moon', fr: 'Lune des Fraises', es: 'Luna de Fresa', de: 'Erdbeermond',
|
||||
pt: 'Lua do Morango', it: 'Luna delle Fragole', ja: 'ストロベリームーン', zh: '草莓月',
|
||||
ar: 'قمر الفراولة', ru: 'Клубничная Луна', hi: 'स्ट्रॉबेरी चंद्रमा'
|
||||
},
|
||||
7: {
|
||||
en: 'Buck Moon', fr: 'Lune du Cerf', es: 'Luna del Ciervo', de: 'Bockmond',
|
||||
pt: 'Lua do Cervo', it: 'Luna del Cervo', ja: 'バックムーン', zh: '雄鹿月',
|
||||
ar: 'قمر الغزال', ru: 'Оленья Луна', hi: 'हिरण चंद्रमा'
|
||||
},
|
||||
8: {
|
||||
en: 'Sturgeon Moon', fr: 'Lune de l\'Esturgeon', es: 'Luna del Esturión', de: 'Störmond',
|
||||
pt: 'Lua do Esturjão', it: 'Luna dello Storione', ja: 'スタージョンムーン', zh: '鲟鱼月',
|
||||
ar: 'قمر سمك الحفش', ru: 'Осетровая Луна', hi: 'स्टर्जन चंद्रमा'
|
||||
},
|
||||
9: {
|
||||
en: 'Harvest Moon', fr: 'Lune des Moissons', es: 'Luna de la Cosecha', de: 'Erntemond',
|
||||
pt: 'Lua da Colheita', it: 'Luna del Raccolto', ja: 'ハーベストムーン', zh: '收获月',
|
||||
ar: 'قمر الحصاد', ru: 'Луна Урожая', hi: 'फसल चंद्रमा'
|
||||
},
|
||||
10: {
|
||||
en: 'Hunter\'s Moon', fr: 'Lune du Chasseur', es: 'Luna del Cazador', de: 'Jägermond',
|
||||
pt: 'Lua do Caçador', it: 'Luna del Cacciatore', ja: 'ハンターズムーン', zh: '猎人月',
|
||||
ar: 'قمر الصياد', ru: 'Охотничья Луна', hi: 'शिकारी चंद्रमा'
|
||||
},
|
||||
11: {
|
||||
en: 'Beaver Moon', fr: 'Lune du Castor', es: 'Luna del Castor', de: 'Bibermond',
|
||||
pt: 'Lua do Castor', it: 'Luna del Castoro', ja: 'ビーバームーン', zh: '海狸月',
|
||||
ar: 'قمر القندس', ru: 'Бобровая Луна', hi: 'बीवर चंद्रमा'
|
||||
},
|
||||
12: {
|
||||
en: 'Cold Moon', fr: 'Lune Froide', es: 'Luna Fría', de: 'Kalter Mond',
|
||||
pt: 'Lua Fria', it: 'Luna Fredda', ja: 'コールドムーン', zh: '冷月',
|
||||
ar: 'القمر البارد', ru: 'Холодная Луна', hi: 'ठंडा चंद्रमा'
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Get full moons for a given year with traditional names
|
||||
*/
|
||||
export function getFullMoonsForYear(year: number): FullMoonInfo[] {
|
||||
const events = getMoonEventsForYear(year);
|
||||
return events
|
||||
.filter((e) => e.phase === 'full_moon')
|
||||
.map((e) => ({
|
||||
date: e.date,
|
||||
traditionalName: FULL_MOON_NAMES[e.date.getUTCMonth() + 1]?.en || 'Full Moon',
|
||||
month: e.date.getUTCMonth() + 1,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate approximate moon position (simplified)
|
||||
* Returns ecliptic longitude in degrees
|
||||
*/
|
||||
export function getMoonEclipticLongitude(date: Date): number {
|
||||
const jd = dateToJD(date);
|
||||
const T = (jd - 2451545.0) / 36525; // Julian centuries from J2000
|
||||
|
||||
// Mean longitude of the Moon
|
||||
let L0 = 218.3165 + 481267.8813 * T;
|
||||
L0 = L0 % 360;
|
||||
if (L0 < 0) L0 += 360;
|
||||
|
||||
return L0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate approximate moon declination (for visibility map)
|
||||
*/
|
||||
export function getMoonDeclination(date: Date): number {
|
||||
const jd = dateToJD(date);
|
||||
const T = (jd - 2451545.0) / 36525;
|
||||
|
||||
// Simplified calculation
|
||||
const D = (297.85 + 445267.1115 * T) % 360;
|
||||
const M = (357.53 + 35999.0503 * T) % 360;
|
||||
const Mp = (134.96 + 477198.8676 * T) % 360;
|
||||
const F = (93.27 + 483202.0175 * T) % 360;
|
||||
|
||||
const dRad = D * Math.PI / 180;
|
||||
const mRad = M * Math.PI / 180;
|
||||
const mpRad = Mp * Math.PI / 180;
|
||||
const fRad = F * Math.PI / 180;
|
||||
|
||||
// Moon's ecliptic latitude (simplified)
|
||||
const beta = 5.128 * Math.sin(fRad)
|
||||
+ 0.2806 * Math.sin(mpRad + fRad)
|
||||
+ 0.2777 * Math.sin(mpRad - fRad)
|
||||
+ 0.1732 * Math.sin(2 * dRad - fRad);
|
||||
|
||||
// Ecliptic longitude (simplified)
|
||||
let lambda = 218.32 + 481267.883 * T
|
||||
+ 6.29 * Math.sin(mpRad)
|
||||
- 1.27 * Math.sin(2 * dRad - mpRad)
|
||||
+ 0.66 * Math.sin(2 * dRad)
|
||||
+ 0.21 * Math.sin(2 * mpRad)
|
||||
- 0.19 * Math.sin(mRad)
|
||||
- 0.11 * Math.sin(2 * fRad);
|
||||
lambda = lambda % 360;
|
||||
|
||||
// Obliquity of ecliptic
|
||||
const epsilon = 23.439 - 0.00000036 * (jd - 2451545.0);
|
||||
const epsRad = epsilon * Math.PI / 180;
|
||||
const lambdaRad = lambda * Math.PI / 180;
|
||||
const betaRad = beta * Math.PI / 180;
|
||||
|
||||
// Declination
|
||||
const declination = Math.asin(
|
||||
Math.sin(betaRad) * Math.cos(epsRad) + Math.cos(betaRad) * Math.sin(epsRad) * Math.sin(lambdaRad)
|
||||
) * 180 / Math.PI;
|
||||
|
||||
return declination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate moon right ascension (for visibility)
|
||||
*/
|
||||
export function getMoonRightAscension(date: Date): number {
|
||||
const jd = dateToJD(date);
|
||||
const T = (jd - 2451545.0) / 36525;
|
||||
|
||||
const Mp = (134.96 + 477198.8676 * T) % 360;
|
||||
const D = (297.85 + 445267.1115 * T) % 360;
|
||||
const M = (357.53 + 35999.0503 * T) % 360;
|
||||
const F = (93.27 + 483202.0175 * T) % 360;
|
||||
|
||||
const mpRad = Mp * Math.PI / 180;
|
||||
const dRad = D * Math.PI / 180;
|
||||
const mRad = M * Math.PI / 180;
|
||||
const fRad = F * Math.PI / 180;
|
||||
|
||||
let lambda = 218.32 + 481267.883 * T
|
||||
+ 6.29 * Math.sin(mpRad)
|
||||
- 1.27 * Math.sin(2 * dRad - mpRad)
|
||||
+ 0.66 * Math.sin(2 * dRad)
|
||||
+ 0.21 * Math.sin(2 * mpRad)
|
||||
- 0.19 * Math.sin(mRad)
|
||||
- 0.11 * Math.sin(2 * fRad);
|
||||
lambda = lambda % 360;
|
||||
|
||||
const beta = 5.128 * Math.sin(fRad);
|
||||
|
||||
const epsilon = 23.439 - 0.00000036 * (jd - 2451545.0);
|
||||
const epsRad = epsilon * Math.PI / 180;
|
||||
const lambdaRad = lambda * Math.PI / 180;
|
||||
const betaRad = beta * Math.PI / 180;
|
||||
|
||||
const ra = Math.atan2(
|
||||
Math.sin(lambdaRad) * Math.cos(epsRad) - Math.tan(betaRad) * Math.sin(epsRad),
|
||||
Math.cos(lambdaRad)
|
||||
) * 180 / Math.PI;
|
||||
|
||||
return ((ra % 360) + 360) % 360;
|
||||
}
|
||||
|
||||
/**
|
||||
* Countdown to next full moon
|
||||
*/
|
||||
export function getCountdownToNextFullMoon(from: Date = new Date()): { days: number; hours: number; minutes: number; seconds: number; totalMs: number } {
|
||||
const nextFull = getNextFullMoon(from);
|
||||
const totalMs = nextFull.getTime() - from.getTime();
|
||||
|
||||
if (totalMs <= 0) return { days: 0, hours: 0, minutes: 0, seconds: 0, totalMs: 0 };
|
||||
|
||||
const days = Math.floor(totalMs / (1000 * 60 * 60 * 24));
|
||||
const hours = Math.floor((totalMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||
const minutes = Math.floor((totalMs % (1000 * 60 * 60)) / (1000 * 60));
|
||||
const seconds = Math.floor((totalMs % (1000 * 60)) / 1000);
|
||||
|
||||
return { days, hours, minutes, seconds, totalMs };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get moon events for a specific month
|
||||
*/
|
||||
export function getMoonEventsForMonth(year: number, month: number): MoonEvent[] {
|
||||
const allEvents = getMoonEventsForYear(year);
|
||||
return allEvents.filter(e => e.date.getUTCMonth() + 1 === month);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get zodiac sign based on ecliptic longitude
|
||||
*/
|
||||
export function getMoonZodiacSign(date: Date): string {
|
||||
const lon = getMoonEclipticLongitude(date);
|
||||
const signs = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo',
|
||||
'Libra', 'Scorpio', 'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces'];
|
||||
const index = Math.floor(lon / 30) % 12;
|
||||
return signs[index];
|
||||
}
|
||||
Reference in New Issue
Block a user