1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-07-30 18:29:37 +02:00

Enhance localization support; update error messages and add translations for adventure calendar

This commit is contained in:
Sean Morley 2024-12-14 09:56:12 -05:00
parent 9bf0849b92
commit 0376709325
17 changed files with 212 additions and 68 deletions

View file

@ -38,10 +38,10 @@ services:
- DJANGO_ADMIN_USERNAME=admin - DJANGO_ADMIN_USERNAME=admin
- DJANGO_ADMIN_PASSWORD=admin - DJANGO_ADMIN_PASSWORD=admin
- DJANGO_ADMIN_EMAIL=admin@example.com - DJANGO_ADMIN_EMAIL=admin@example.com
- PUBLIC_URL='http://localhost:8016' # Match the outward port, used for the creation of image urls - PUBLIC_URL=http://localhost:8016 # Match the outward port, used for the creation of image urls
- CSRF_TRUSTED_ORIGINS=http://localhost:8016,http://localhost:8015 # Comma separated list of trusted origins for CSRF - CSRF_TRUSTED_ORIGINS=http://localhost:8016,http://localhost:8015 # Comma separated list of trusted origins for CSRF
- DEBUG=False - DEBUG=False
- FRONTEND_URL='http://localhost:8015' # Used for email generation. This should be the url of the frontend - FRONTEND_URL=http://localhost:8015 # Used for email generation. This should be the url of the frontend
ports: ports:
- "8016:80" - "8016:80"
depends_on: depends_on:

View file

@ -31,18 +31,18 @@ Here is a summary of the configuration options available in the `docker-compose.
### Backend Container (server) ### Backend Container (server)
| Name | Required | Description | Default Value | | Name | Required | Description | Default Value |
| ----------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | | ----------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
| `PGHOST` | Yes | Databse host. | db | | `PGHOST` | Yes | Databse host. | db |
| `PGDATABASE` | Yes | Database. | database | | `PGDATABASE` | Yes | Database. | database |
| `PGUSER` | Yes | Database user. | adventure | | `PGUSER` | Yes | Database user. | adventure |
| `PGPASSWORD` | Yes | Database password. | changeme123 | | `PGPASSWORD` | Yes | Database password. | changeme123 |
| `DJANGO_ADMIN_USERNAME` | Yes | Default username. | admin | | `DJANGO_ADMIN_USERNAME` | Yes | Default username. | admin |
| `DJANGO_ADMIN_PASSWORD` | Yes | Default password, change after inital login. | admin | | `DJANGO_ADMIN_PASSWORD` | Yes | Default password, change after inital login. | admin |
| `DJANGO_ADMIN_EMAIL` | Yes | Default user's email. | admin@example.com | | `DJANGO_ADMIN_EMAIL` | Yes | Default user's email. | admin@example.com |
| `PUBLIC_URL` | Yes | This needs to match the outward port of the server and be accessible from where the app is used. It is used for the creation of image urls. | 'http://localhost:8016' | | `PUBLIC_URL` | Yes | This needs to match the outward port of the server and be accessible from where the app is used. It is used for the creation of image urls. | http://localhost:8016 |
| `CSRF_TRUSTED_ORIGINS` | Yes | Need to be changed to the orgins where you use your backend server and frontend. These values are comma seperated. | http://localhost:8016 | | `CSRF_TRUSTED_ORIGINS` | Yes | Need to be changed to the orgins where you use your backend server and frontend. These values are comma seperated. | http://localhost:8016 |
| `FRONTEND_URL` | Yes | This is the publically accessible url to the **frontend** container. This link should be accessable for all users. Used for email generation. | 'http://localhost:8015' | | `FRONTEND_URL` | Yes | This is the publically accessible url to the **frontend** container. This link should be accessable for all users. Used for email generation. | http://localhost:8015 |
## Running the Containers ## Running the Containers

View file

@ -190,7 +190,8 @@
"set_to_pin": "Auf „Anpinnen“ setzen", "set_to_pin": "Auf „Anpinnen“ setzen",
"category_fetch_error": "Fehler beim Abrufen der Kategorien", "category_fetch_error": "Fehler beim Abrufen der Kategorien",
"copied_to_clipboard": "In die Zwischenablage kopiert!", "copied_to_clipboard": "In die Zwischenablage kopiert!",
"copy_failed": "Das Kopieren ist fehlgeschlagen" "copy_failed": "Das Kopieren ist fehlgeschlagen",
"adventure_calendar": "Abenteuerkalender"
}, },
"home": { "home": {
"desc_1": "Entdecken, planen und erkunden Sie mit Leichtigkeit", "desc_1": "Entdecken, planen und erkunden Sie mit Leichtigkeit",
@ -333,7 +334,13 @@
"verified": "Verifiziert", "verified": "Verifiziert",
"verify": "Verifizieren", "verify": "Verifizieren",
"verify_email_error": "Fehler bei der E-Mail-Bestätigung. \nVersuchen Sie es in ein paar Minuten noch einmal.", "verify_email_error": "Fehler bei der E-Mail-Bestätigung. \nVersuchen Sie es in ein paar Minuten noch einmal.",
"verify_email_success": "E-Mail-Bestätigung erfolgreich gesendet!" "verify_email_success": "E-Mail-Bestätigung erfolgreich gesendet!",
"add_email_blocked": "Sie können keine E-Mail-Adresse zu einem Konto hinzufügen, das durch die Zwei-Faktor-Authentifizierung geschützt ist.",
"required": "Dieses Feld ist erforderlich",
"csrf_failed": "CSRF-Token konnte nicht abgerufen werden",
"duplicate_email": "Diese E-Mail-Adresse wird bereits verwendet.",
"email_taken": "Diese E-Mail-Adresse wird bereits verwendet.",
"username_taken": "Dieser Benutzername wird bereits verwendet."
}, },
"checklist": { "checklist": {
"add_item": "Artikel hinzufügen", "add_item": "Artikel hinzufügen",
@ -453,5 +460,14 @@
"no_categories_found": "Keine Kategorien gefunden.", "no_categories_found": "Keine Kategorien gefunden.",
"select_category": "Kategorie auswählen", "select_category": "Kategorie auswählen",
"update_after_refresh": "Die Abenteuerkarten werden aktualisiert, sobald Sie die Seite aktualisieren." "update_after_refresh": "Die Abenteuerkarten werden aktualisiert, sobald Sie die Seite aktualisieren."
},
"dashboard": {
"add_some": "Warum beginnen Sie nicht mit der Planung Ihres nächsten Abenteuers? \nSie können ein neues Abenteuer hinzufügen, indem Sie auf die Schaltfläche unten klicken.",
"countries_visited": "Besuchte Länder",
"no_recent_adventures": "Keine aktuellen Abenteuer?",
"recent_adventures": "Aktuelle Abenteuer",
"total_adventures": "Totale Abenteuer",
"total_visited_regions": "Insgesamt besuchte Regionen",
"welcome_back": "Willkommen zurück"
} }
} }

View file

@ -208,6 +208,7 @@
"notes": "Notes", "notes": "Notes",
"checklists": "Checklists", "checklists": "Checklists",
"transportations": "Transportations", "transportations": "Transportations",
"adventure_calendar": "Adventure Calendar",
"day": "Day", "day": "Day",
"itineary_by_date": "Itinerary by Date", "itineary_by_date": "Itinerary by Date",
"nothing_planned": "Nothing planned for this day. Enjoy the journey!", "nothing_planned": "Nothing planned for this day. Enjoy the journey!",
@ -333,7 +334,13 @@
"email_verified_erorr_desc": "Your email could not be verified. Please try again.", "email_verified_erorr_desc": "Your email could not be verified. Please try again.",
"invalid_code": "Invalid MFA code", "invalid_code": "Invalid MFA code",
"invalid_credentials": "Invalid username or password", "invalid_credentials": "Invalid username or password",
"mfa_required": "Multi-factor authentication is required" "mfa_required": "Multi-factor authentication is required",
"required": "This field is required",
"add_email_blocked": "You cannot add an email address to an account protected by two-factor authentication.",
"duplicate_email": "This email address is already in use.",
"csrf_failed": "Failed to fetch CSRF token",
"email_taken": "This email address is already in use.",
"username_taken": "This username is already in use."
}, },
"collection": { "collection": {
"collection_created": "Collection created successfully!", "collection_created": "Collection created successfully!",
@ -453,5 +460,14 @@
"update_after_refresh": "The adventure cards will be updated once you refresh the page.", "update_after_refresh": "The adventure cards will be updated once you refresh the page.",
"select_category": "Select Category", "select_category": "Select Category",
"category_name": "Category Name" "category_name": "Category Name"
},
"dashboard": {
"welcome_back": "Welcome back",
"countries_visited": "Countries Visited",
"total_adventures": "Total Adventures",
"total_visited_regions": "Total Visited Regions",
"recent_adventures": "Recent Adventures",
"no_recent_adventures": "No recent adventures?",
"add_some": "Why not start planning your next adventure? You can add a new adventure by clicking the button below."
} }
} }

View file

@ -237,7 +237,8 @@
"set_to_pin": "Establecer en Fijar", "set_to_pin": "Establecer en Fijar",
"category_fetch_error": "Error al buscar categorías", "category_fetch_error": "Error al buscar categorías",
"copied_to_clipboard": "¡Copiado al portapapeles!", "copied_to_clipboard": "¡Copiado al portapapeles!",
"copy_failed": "Copia fallida" "copy_failed": "Copia fallida",
"adventure_calendar": "Calendario de aventuras"
}, },
"worldtravel": { "worldtravel": {
"all": "Todo", "all": "Todo",
@ -333,7 +334,13 @@
"email_verified_success": "Su correo electrónico ha sido verificado. \nAhora puedes iniciar sesión.", "email_verified_success": "Su correo electrónico ha sido verificado. \nAhora puedes iniciar sesión.",
"invalid_code": "Código MFA no válido", "invalid_code": "Código MFA no válido",
"invalid_credentials": "Nombre de usuario o contraseña no válidos", "invalid_credentials": "Nombre de usuario o contraseña no válidos",
"mfa_required": "Se requiere autenticación multifactor" "mfa_required": "Se requiere autenticación multifactor",
"add_email_blocked": "No puede agregar una dirección de correo electrónico a una cuenta protegida por autenticación de dos factores.",
"required": "Este campo es obligatorio",
"csrf_failed": "No se pudo recuperar el token CSRF",
"duplicate_email": "Esta dirección de correo electrónico ya está en uso.",
"email_taken": "Esta dirección de correo electrónico ya está en uso.",
"username_taken": "Este nombre de usuario ya está en uso."
}, },
"checklist": { "checklist": {
"add_item": "Agregar artículo", "add_item": "Agregar artículo",
@ -453,5 +460,14 @@
"no_categories_found": "No se encontraron categorías.", "no_categories_found": "No se encontraron categorías.",
"select_category": "Seleccionar categoría", "select_category": "Seleccionar categoría",
"update_after_refresh": "Las tarjetas de aventuras se actualizarán una vez que actualices la página." "update_after_refresh": "Las tarjetas de aventuras se actualizarán una vez que actualices la página."
},
"dashboard": {
"add_some": "¿Por qué no empezar a planificar tu próxima aventura? \nPuedes agregar una nueva aventura haciendo clic en el botón de abajo.",
"countries_visited": "Países visitados",
"no_recent_adventures": "¿Sin aventuras recientes?",
"recent_adventures": "Aventuras recientes",
"total_adventures": "Aventuras totales",
"total_visited_regions": "Total de regiones visitadas",
"welcome_back": "Bienvenido de nuevo"
} }
} }

View file

@ -190,7 +190,8 @@
"set_to_pin": "Définir sur Épingler", "set_to_pin": "Définir sur Épingler",
"category_fetch_error": "Erreur lors de la récupération des catégories", "category_fetch_error": "Erreur lors de la récupération des catégories",
"copied_to_clipboard": "Copié dans le presse-papier !", "copied_to_clipboard": "Copié dans le presse-papier !",
"copy_failed": "Échec de la copie" "copy_failed": "Échec de la copie",
"adventure_calendar": "Calendrier d'aventure"
}, },
"home": { "home": {
"desc_1": "Découvrez, planifiez et explorez en toute simplicité", "desc_1": "Découvrez, planifiez et explorez en toute simplicité",
@ -333,7 +334,13 @@
"verified": "Vérifié", "verified": "Vérifié",
"verify": "Vérifier", "verify": "Vérifier",
"verify_email_error": "Erreur lors de la vérification de l'e-mail. \nRéessayez dans quelques minutes.", "verify_email_error": "Erreur lors de la vérification de l'e-mail. \nRéessayez dans quelques minutes.",
"verify_email_success": "Vérification par e-mail envoyée avec succès !" "verify_email_success": "Vérification par e-mail envoyée avec succès !",
"add_email_blocked": "Vous ne pouvez pas ajouter une adresse e-mail à un compte protégé par une authentification à deux facteurs.",
"required": "Ce champ est obligatoire",
"csrf_failed": "Échec de la récupération du jeton CSRF",
"duplicate_email": "Cette adresse e-mail est déjà utilisée.",
"email_taken": "Cette adresse e-mail est déjà utilisée.",
"username_taken": "Ce nom d'utilisateur est déjà utilisé."
}, },
"checklist": { "checklist": {
"add_item": "Ajouter un article", "add_item": "Ajouter un article",
@ -453,5 +460,14 @@
"no_categories_found": "Aucune catégorie trouvée.", "no_categories_found": "Aucune catégorie trouvée.",
"select_category": "Sélectionnez une catégorie", "select_category": "Sélectionnez une catégorie",
"update_after_refresh": "Les cartes d'aventure seront mises à jour une fois que vous aurez actualisé la page." "update_after_refresh": "Les cartes d'aventure seront mises à jour une fois que vous aurez actualisé la page."
},
"dashboard": {
"add_some": "Pourquoi ne pas commencer à planifier votre prochaine aventure ? \nVous pouvez ajouter une nouvelle aventure en cliquant sur le bouton ci-dessous.",
"countries_visited": "Pays visités",
"no_recent_adventures": "Pas d'aventures récentes ?",
"recent_adventures": "Aventures récentes",
"total_adventures": "Aventures totales",
"total_visited_regions": "Total des régions visitées",
"welcome_back": "Content de te revoir"
} }
} }

View file

@ -190,7 +190,8 @@
"set_to_pin": "Imposta su Blocca", "set_to_pin": "Imposta su Blocca",
"category_fetch_error": "Errore durante il recupero delle categorie", "category_fetch_error": "Errore durante il recupero delle categorie",
"copied_to_clipboard": "Copiato negli appunti!", "copied_to_clipboard": "Copiato negli appunti!",
"copy_failed": "Copia non riuscita" "copy_failed": "Copia non riuscita",
"adventure_calendar": "Calendario delle avventure"
}, },
"home": { "home": {
"desc_1": "Scopri, pianifica ed esplora con facilità", "desc_1": "Scopri, pianifica ed esplora con facilità",
@ -333,7 +334,13 @@
"verified": "Verificato", "verified": "Verificato",
"verify_email_success": "Verifica email inviata con successo!", "verify_email_success": "Verifica email inviata con successo!",
"verify": "Verificare", "verify": "Verificare",
"verify_email_error": "Errore durante la verifica dell'e-mail. \nRiprova tra qualche minuto." "verify_email_error": "Errore durante la verifica dell'e-mail. \nRiprova tra qualche minuto.",
"add_email_blocked": "Non è possibile aggiungere un indirizzo email a un account protetto dall'autenticazione a due fattori.",
"required": "Questo campo è obbligatorio",
"csrf_failed": "Impossibile recuperare il token CSRF",
"duplicate_email": "Questo indirizzo email è già in uso.",
"email_taken": "Questo indirizzo email è già in uso.",
"username_taken": "Questo nome utente è già in uso."
}, },
"checklist": { "checklist": {
"add_item": "Aggiungi articolo", "add_item": "Aggiungi articolo",
@ -453,5 +460,14 @@
"no_categories_found": "Nessuna categoria trovata.", "no_categories_found": "Nessuna categoria trovata.",
"select_category": "Seleziona Categoria", "select_category": "Seleziona Categoria",
"update_after_refresh": "Le carte avventura verranno aggiornate una volta aggiornata la pagina." "update_after_refresh": "Le carte avventura verranno aggiornate una volta aggiornata la pagina."
},
"dashboard": {
"add_some": "Perché non iniziare a pianificare la tua prossima avventura? \nPuoi aggiungere una nuova avventura facendo clic sul pulsante in basso.",
"countries_visited": "Paesi visitati",
"no_recent_adventures": "Nessuna avventura recente?",
"recent_adventures": "Avventure recenti",
"total_adventures": "Avventure totali",
"total_visited_regions": "Totale regioni visitate",
"welcome_back": "Bentornato"
} }
} }

View file

@ -190,7 +190,8 @@
"set_to_pin": "Stel in op pin", "set_to_pin": "Stel in op pin",
"category_fetch_error": "Fout bij ophalen van categorieën", "category_fetch_error": "Fout bij ophalen van categorieën",
"copied_to_clipboard": "Gekopieerd naar klembord!", "copied_to_clipboard": "Gekopieerd naar klembord!",
"copy_failed": "Kopiëren mislukt" "copy_failed": "Kopiëren mislukt",
"adventure_calendar": "Avonturenkalender"
}, },
"home": { "home": {
"desc_1": "Ontdek, plan en verken met gemak", "desc_1": "Ontdek, plan en verken met gemak",
@ -333,7 +334,13 @@
"verified": "Geverifieerd", "verified": "Geverifieerd",
"verify": "Verifiëren", "verify": "Verifiëren",
"verify_email_error": "Fout bij het verifiëren van e-mailadres. \nProbeer het over een paar minuten opnieuw.", "verify_email_error": "Fout bij het verifiëren van e-mailadres. \nProbeer het over een paar minuten opnieuw.",
"verify_email_success": "E-mailverificatie succesvol verzonden!" "verify_email_success": "E-mailverificatie succesvol verzonden!",
"add_email_blocked": "U kunt geen e-mailadres toevoegen aan een account dat is beveiligd met tweefactorauthenticatie.",
"required": "Dit veld is verplicht",
"csrf_failed": "Kan CSRF-token niet ophalen",
"duplicate_email": "Dit e-mailadres is al in gebruik.",
"email_taken": "Dit e-mailadres is al in gebruik.",
"username_taken": "Deze gebruikersnaam is al in gebruik."
}, },
"checklist": { "checklist": {
"add_item": "Artikel toevoegen", "add_item": "Artikel toevoegen",
@ -453,5 +460,14 @@
"no_categories_found": "Geen categorieën gevonden.", "no_categories_found": "Geen categorieën gevonden.",
"select_category": "Selecteer categorie", "select_category": "Selecteer categorie",
"update_after_refresh": "De avonturenkaarten worden bijgewerkt zodra u de pagina vernieuwt." "update_after_refresh": "De avonturenkaarten worden bijgewerkt zodra u de pagina vernieuwt."
},
"dashboard": {
"add_some": "Waarom begint u niet met het plannen van uw volgende avontuur? \nJe kunt een nieuw avontuur toevoegen door op de onderstaande knop te klikken.",
"countries_visited": "Bezochte landen",
"no_recent_adventures": "Geen recente avonturen?",
"recent_adventures": "Recente avonturen",
"total_adventures": "Totale avonturen",
"total_visited_regions": "Totaal bezochte regio's",
"welcome_back": "Welkom terug"
} }
} }

View file

@ -237,7 +237,8 @@
"other": "Inne" "other": "Inne"
}, },
"copied_to_clipboard": "Skopiowano do schowka!", "copied_to_clipboard": "Skopiowano do schowka!",
"copy_failed": "Kopiowanie nie powiodło się" "copy_failed": "Kopiowanie nie powiodło się",
"adventure_calendar": "Kalendarz przygód"
}, },
"worldtravel": { "worldtravel": {
"country_list": "Lista krajów", "country_list": "Lista krajów",
@ -333,7 +334,13 @@
"verified": "Zweryfikowano", "verified": "Zweryfikowano",
"verify": "Zweryfikować", "verify": "Zweryfikować",
"verify_email_error": "Błąd podczas weryfikacji adresu e-mail. \nSpróbuj ponownie za kilka minut.", "verify_email_error": "Błąd podczas weryfikacji adresu e-mail. \nSpróbuj ponownie za kilka minut.",
"verify_email_success": "Weryfikacja e-mailowa została wysłana pomyślnie!" "verify_email_success": "Weryfikacja e-mailowa została wysłana pomyślnie!",
"add_email_blocked": "Nie można dodać adresu e-mail do konta chronionego uwierzytelnianiem dwuskładnikowym.",
"required": "To pole jest wymagane",
"csrf_failed": "Nie udało się pobrać tokena CSRF",
"duplicate_email": "Ten adres e-mail jest już używany.",
"email_taken": "Ten adres e-mail jest już używany.",
"username_taken": "Ta nazwa użytkownika jest już używana."
}, },
"collection": { "collection": {
"collection_created": "Kolekcja została pomyślnie utworzona!", "collection_created": "Kolekcja została pomyślnie utworzona!",
@ -453,5 +460,14 @@
"update_after_refresh": "Karty podróży zostaną zaktualizowane po odświeżeniu strony.", "update_after_refresh": "Karty podróży zostaną zaktualizowane po odświeżeniu strony.",
"select_category": "Wybierz kategorię", "select_category": "Wybierz kategorię",
"category_name": "Nazwa kategorii" "category_name": "Nazwa kategorii"
},
"dashboard": {
"add_some": "Dlaczego nie zacząć planować kolejnej przygody? \nMożesz dodać nową przygodę, klikając przycisk poniżej.",
"countries_visited": "Odwiedzone kraje",
"no_recent_adventures": "Brak nowych przygód?",
"recent_adventures": "Ostatnie przygody",
"total_adventures": "Totalne przygody",
"total_visited_regions": "Łączna liczba odwiedzonych regionów",
"welcome_back": "Witamy z powrotem"
} }
} }

View file

@ -190,7 +190,8 @@
"set_to_pin": "Ställ in på Pin", "set_to_pin": "Ställ in på Pin",
"category_fetch_error": "Det gick inte att hämta kategorier", "category_fetch_error": "Det gick inte att hämta kategorier",
"copied_to_clipboard": "Kopierat till urklipp!", "copied_to_clipboard": "Kopierat till urklipp!",
"copy_failed": "Kopieringen misslyckades" "copy_failed": "Kopieringen misslyckades",
"adventure_calendar": "Äventyrskalender"
}, },
"home": { "home": {
"desc_1": "Upptäck, planera och utforska med lätthet", "desc_1": "Upptäck, planera och utforska med lätthet",
@ -333,7 +334,13 @@
"verified": "Verifierad", "verified": "Verifierad",
"verify": "Kontrollera", "verify": "Kontrollera",
"verify_email_error": "Fel vid verifiering av e-post. \nFörsök igen om några minuter.", "verify_email_error": "Fel vid verifiering av e-post. \nFörsök igen om några minuter.",
"verify_email_success": "E-postverifiering har skickats!" "verify_email_success": "E-postverifiering har skickats!",
"add_email_blocked": "Du kan inte lägga till en e-postadress till ett konto som skyddas av tvåfaktorsautentisering.",
"required": "Detta fält är obligatoriskt",
"csrf_failed": "Det gick inte att hämta CSRF-token",
"duplicate_email": "Den här e-postadressen används redan.",
"email_taken": "Den här e-postadressen används redan.",
"username_taken": "Detta användarnamn används redan."
}, },
"checklist": { "checklist": {
"add_item": "Lägg till objekt", "add_item": "Lägg till objekt",
@ -453,5 +460,14 @@
"no_categories_found": "Inga kategorier hittades.", "no_categories_found": "Inga kategorier hittades.",
"select_category": "Välj Kategori", "select_category": "Välj Kategori",
"update_after_refresh": "Äventyrskorten kommer att uppdateras när du uppdaterar sidan." "update_after_refresh": "Äventyrskorten kommer att uppdateras när du uppdaterar sidan."
},
"dashboard": {
"add_some": "Varför inte börja planera ditt nästa äventyr? \nDu kan lägga till ett nytt äventyr genom att klicka på knappen nedan.",
"countries_visited": "Besökta länder",
"no_recent_adventures": "Inga nya äventyr?",
"recent_adventures": "Senaste äventyr",
"total_adventures": "Totala äventyr",
"total_visited_regions": "Totalt antal besökta regioner",
"welcome_back": "Välkommen tillbaka"
} }
} }

View file

@ -190,7 +190,8 @@
"set_to_pin": "设置为固定", "set_to_pin": "设置为固定",
"category_fetch_error": "获取类别时出错", "category_fetch_error": "获取类别时出错",
"copied_to_clipboard": "已复制到剪贴板!", "copied_to_clipboard": "已复制到剪贴板!",
"copy_failed": "复制失败" "copy_failed": "复制失败",
"adventure_calendar": "冒险日历"
}, },
"home": { "home": {
"desc_1": "轻松发现、规划和探索", "desc_1": "轻松发现、规划和探索",
@ -333,7 +334,13 @@
"verified": "已验证", "verified": "已验证",
"verify": "核实", "verify": "核实",
"verify_email_error": "验证电子邮件时出错。\n几分钟后重试。", "verify_email_error": "验证电子邮件时出错。\n几分钟后重试。",
"verify_email_success": "邮箱验证发送成功!" "verify_email_success": "邮箱验证发送成功!",
"add_email_blocked": "您无法将电子邮件地址添加到受双因素身份验证保护的帐户。",
"required": "此字段是必需的",
"csrf_failed": "获取 CSRF 令牌失败",
"duplicate_email": "该电子邮件地址已被使用。",
"email_taken": "该电子邮件地址已被使用。",
"username_taken": "该用户名已被使用。"
}, },
"checklist": { "checklist": {
"add_item": "添加项目", "add_item": "添加项目",
@ -453,5 +460,14 @@
"no_categories_found": "未找到类别。", "no_categories_found": "未找到类别。",
"select_category": "选择类别", "select_category": "选择类别",
"update_after_refresh": "刷新页面后,冒险卡将更新。" "update_after_refresh": "刷新页面后,冒险卡将更新。"
},
"dashboard": {
"add_some": "为什么不开始计划你的下一次冒险呢?\n您可以通过单击下面的按钮添加新的冒险。",
"countries_visited": "访问国家",
"no_recent_adventures": "最近没有冒险吗?",
"recent_adventures": "最近的冒险",
"total_adventures": "全面冒险",
"total_visited_regions": "总访问地区",
"welcome_back": "欢迎回来"
} }
} }

View file

@ -7,6 +7,7 @@
import TimeGrid from '@event-calendar/time-grid'; import TimeGrid from '@event-calendar/time-grid';
// @ts-ignore // @ts-ignore
import DayGrid from '@event-calendar/day-grid'; import DayGrid from '@event-calendar/day-grid';
import { t } from 'svelte-i18n';
export let data: PageData; export let data: PageData;
@ -20,6 +21,6 @@
}; };
</script> </script>
<h1 class="text-center text-2xl font-bold">Adventure Calendar</h1> <h1 class="text-center text-2xl font-bold">{$t('adventures.adventure_calendar')}</h1>
<Calendar {plugins} {options} /> <Calendar {plugins} {options} />

View file

@ -1,22 +1,19 @@
<script lang="ts"> <script lang="ts">
import AdventureCard from '$lib/components/AdventureCard.svelte'; import AdventureCard from '$lib/components/AdventureCard.svelte';
import type { PageData } from './$types'; import type { PageData } from './$types';
import { t } from 'svelte-i18n';
export let data: PageData; export let data: PageData;
const user = data.user; const user = data.user;
const recentAdventures = data.props.adventures; const recentAdventures = data.props.adventures;
const stats = data.props.stats; const stats = data.props.stats;
console.log(stats);
const inspirationQuote = 'The world is a book, and those who do not travel read only one page.';
const inspirationImage = 'https://picsum.photos/seed/inspiration/800/400';
</script> </script>
<div class="container mx-auto p-4"> <div class="container mx-auto p-4">
<!-- Welcome Message --> <!-- Welcome Message -->
<div class="mb-8"> <div class="mb-8">
<h1 class="text-4xl font-extrabold">Welcome back, {user?.first_name}!</h1> <h1 class="text-4xl font-extrabold">{$t('dashboard.welcome_back')}, {user?.first_name}!</h1>
</div> </div>
<!-- Stats --> <!-- Stats -->
@ -36,7 +33,7 @@
></path></svg ></path></svg
> >
</div> </div>
<div class="stat-title text-neutral-content">Countries Visited</div> <div class="stat-title text-neutral-content">{$t('dashboard.countries_visited')}</div>
<div class="stat-value text-primary">{stats.country_count}</div> <div class="stat-value text-primary">{stats.country_count}</div>
</div> </div>
<div class="stat"> <div class="stat">
@ -54,7 +51,7 @@
></path></svg ></path></svg
> >
</div> </div>
<div class="stat-title text-neutral-content">Total Adventures</div> <div class="stat-title text-neutral-content">{$t('dashboard.total_adventures')}</div>
<div class="stat-value text-secondary">{stats.adventure_count}</div> <div class="stat-value text-secondary">{stats.adventure_count}</div>
</div> </div>
<div class="stat"> <div class="stat">
@ -72,32 +69,31 @@
></path></svg ></path></svg
> >
</div> </div>
<div class="stat-title text-neutral-content">Total Visited Regions</div> <div class="stat-title text-neutral-content">{$t('dashboard.total_visited_regions')}</div>
<div class="stat-value text-success">{stats.visited_region_count}</div> <div class="stat-value text-success">{stats.visited_region_count}</div>
</div> </div>
</div> </div>
<!-- Recent Adventures --> <!-- Recent Adventures -->
<h2 class="text-3xl font-semibold mb-4">Recent Adventures</h2> {#if recentAdventures.length > 0}
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8"> <h2 class="text-3xl font-semibold mb-4">{$t('dashboard.recent_adventures')}</h2>
{#each recentAdventures as adventure} <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
<AdventureCard {adventure} user={data.user} readOnly /> {#each recentAdventures as adventure}
{/each} <AdventureCard {adventure} user={data.user} readOnly />
</div> {/each}
<!-- Inspiration -->
<div class="card lg:card-side bg-base-100 shadow-xl mb-8">
<figure class="lg:w-1/2">
<img src={inspirationImage} alt="Inspiration" class="w-full h-full object-cover" />
</figure>
<div class="card-body lg:w-1/2">
<h2 class="card-title">Get Inspired</h2>
<p class="text-lg italic">"{inspirationQuote}"</p>
<div class="card-actions justify-end">
<button class="btn btn-primary">Plan Your Next Adventure</button>
</div>
</div> </div>
</div> {/if}
<!-- Inspiration if there are no recent adventures -->
{#if recentAdventures.length === 0}
<div class="flex flex-col items-center justify-center bg-neutral shadow p-8 mb-8 rounded-lg">
<h2 class="text-3xl font-semibold mb-4">{$t('dashboard.no_recent_adventures')}</h2>
<p class="text-lg text-center">
{$t('dashboard.add_some')}
</p>
<a href="/adventures" class="btn btn-primary mt-4">{$t('map.add_adventure')}</a>
</div>
{/if}
</div> </div>
<svelte:head> <svelte:head>

View file

@ -100,7 +100,9 @@
emails = [...emails, { email: new_email, verified: false, primary: false }]; emails = [...emails, { email: new_email, verified: false, primary: false }];
new_email = ''; new_email = '';
} else { } else {
addToast('error', $t('settings.email_added_error')); let error = await res.json();
let error_code = error.errors[0].code;
addToast('error', $t(`settings.${error_code}`) || $t('settings.generic_error'));
} }
} }

View file

@ -41,11 +41,11 @@ export const actions: Actions = {
if (!csrfTokenFetch.ok) { if (!csrfTokenFetch.ok) {
event.locals.user = null; event.locals.user = null;
return fail(500, { message: 'Failed to fetch CSRF token' }); return fail(500, { message: 'settings.csrf_failed' });
} }
if (password1 !== password2) { if (password1 !== password2) {
return fail(400, { message: 'Passwords do not match' }); return fail(400, { message: 'settings.password_does_not_match' });
} }
const tokenPromise = await csrfTokenFetch.json(); const tokenPromise = await csrfTokenFetch.json();
@ -69,7 +69,7 @@ export const actions: Actions = {
const loginResponse = await loginFetch.json(); const loginResponse = await loginFetch.json();
if (!loginFetch.ok) { if (!loginFetch.ok) {
return fail(loginFetch.status, loginResponse); return fail(loginFetch.status, { message: loginResponse.errors[0].code });
} else { } else {
const setCookieHeader = loginFetch.headers.get('Set-Cookie'); const setCookieHeader = loginFetch.headers.get('Set-Cookie');

View file

@ -94,7 +94,7 @@
</div> </div>
{#if $page.form?.message} {#if $page.form?.message}
<div class="text-center text-error mt-4">{$page.form?.message}</div> <div class="text-center text-error mt-4">{$t($page.form?.message)}</div>
{/if} {/if}
{:else} {:else}
<div class="flex justify-center"> <div class="flex justify-center">

View file

@ -21,13 +21,14 @@ export const load = (async (event) => {
body: JSON.stringify({ key: key }) body: JSON.stringify({ key: key })
}); });
if (!verifyFetch.ok) { if (verifyFetch.ok || verifyFetch.status == 401) {
return {
verified: true
};
} else {
let error_message = await verifyFetch.json(); let error_message = await verifyFetch.json();
console.error(error_message); console.error(error_message);
console.error('Failed to verify email'); console.error('Failed to verify email');
return { status: 404 }; return { status: 404 };
} }
return {
verified: true
};
}) satisfies PageServerLoad; }) satisfies PageServerLoad;