mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-08-02 19:55:18 +02:00
Add Lodging to Map, Sanitize MD, Optional Password Disable
This commit is contained in:
commit
6eb57d1d6e
38 changed files with 733 additions and 403 deletions
|
@ -71,7 +71,7 @@ class CustomUserAdmin(UserAdmin):
|
|||
readonly_fields = ('uuid',)
|
||||
search_fields = ('username',)
|
||||
fieldsets = UserAdmin.fieldsets + (
|
||||
(None, {'fields': ('profile_pic', 'uuid', 'public_profile')}),
|
||||
(None, {'fields': ('profile_pic', 'uuid', 'public_profile', 'disable_password')}),
|
||||
)
|
||||
def image_display(self, obj):
|
||||
if obj.profile_pic:
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 5.0.8 on 2025-03-17 01:15
|
||||
|
||||
import adventures.models
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('adventures', '0023_lodging_delete_hotel'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='attachment',
|
||||
name='file',
|
||||
field=models.FileField(upload_to=adventures.models.PathAndRename('attachments/'), validators=[adventures.models.validate_file_extension]),
|
||||
),
|
||||
]
|
|
@ -1,4 +1,4 @@
|
|||
from collections.abc import Collection
|
||||
from django.core.exceptions import ValidationError
|
||||
import os
|
||||
from typing import Iterable
|
||||
import uuid
|
||||
|
@ -10,6 +10,13 @@ from django.contrib.postgres.fields import ArrayField
|
|||
from django.forms import ValidationError
|
||||
from django_resized import ResizedImageField
|
||||
|
||||
def validate_file_extension(value):
|
||||
import os
|
||||
from django.core.exceptions import ValidationError
|
||||
ext = os.path.splitext(value.name)[1] # [0] returns path+filename
|
||||
valid_extensions = ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt', '.png', '.jpg', '.jpeg', '.gif', '.webp', '.mp4', '.mov', '.avi', '.mkv', '.mp3', '.wav', '.flac', '.ogg', '.m4a', '.wma', '.aac', '.opus', '.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.xz', '.zst', '.lz4', '.lzma', '.lzo', '.z', '.tar.gz', '.tar.bz2', '.tar.xz', '.tar.zst', '.tar.lz4', '.tar.lzma', '.tar.lzo', '.tar.z', 'gpx', 'md', 'pdf']
|
||||
if not ext.lower() in valid_extensions:
|
||||
raise ValidationError('Unsupported file extension.')
|
||||
|
||||
ADVENTURE_TYPES = [
|
||||
('general', 'General 🌍'),
|
||||
|
@ -306,7 +313,7 @@ class Attachment(models.Model):
|
|||
id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, primary_key=True)
|
||||
user_id = models.ForeignKey(
|
||||
User, on_delete=models.CASCADE, default=default_user_id)
|
||||
file = models.FileField(upload_to=PathAndRename('attachments/'))
|
||||
file = models.FileField(upload_to=PathAndRename('attachments/'),validators=[validate_file_extension])
|
||||
adventure = models.ForeignKey(Adventure, related_name='attachments', on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=200, null=True, blank=True)
|
||||
|
||||
|
|
|
@ -227,6 +227,10 @@ HEADLESS_FRONTEND_URLS = {
|
|||
"socialaccount_login_error": f"{FRONTEND_URL}/account/provider/callback",
|
||||
}
|
||||
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
'users.backends.NoPasswordAuthBackend',
|
||||
]
|
||||
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
SITE_ID = 1
|
||||
ACCOUNT_EMAIL_REQUIRED = True
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.urls import include, re_path, path
|
||||
from django.contrib import admin
|
||||
from django.views.generic import RedirectView, TemplateView
|
||||
from users.views import IsRegistrationDisabled, PublicUserListView, PublicUserDetailView, UserMetadataView, UpdateUserMetadataView, EnabledSocialProvidersView
|
||||
from users.views import IsRegistrationDisabled, PublicUserListView, PublicUserDetailView, UserMetadataView, UpdateUserMetadataView, EnabledSocialProvidersView, DisablePasswordAuthenticationView
|
||||
from .views import get_csrf_token, get_public_url, serve_protected_media
|
||||
from drf_yasg.views import get_schema_view
|
||||
from drf_yasg import openapi
|
||||
|
@ -29,6 +29,8 @@ urlpatterns = [
|
|||
|
||||
path('auth/social-providers/', EnabledSocialProvidersView.as_view(), name='enabled-social-providers'),
|
||||
|
||||
path('auth/disable-password/', DisablePasswordAuthenticationView.as_view(), name='disable-password-authentication'),
|
||||
|
||||
path('csrf/', get_csrf_token, name='get_csrf_token'),
|
||||
path('public-url/', get_public_url, name='get_public_url'),
|
||||
|
||||
|
|
16
backend/server/users/backends.py
Normal file
16
backend/server/users/backends.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from django.contrib.auth.backends import ModelBackend
|
||||
from allauth.socialaccount.models import SocialAccount
|
||||
|
||||
class NoPasswordAuthBackend(ModelBackend):
|
||||
def authenticate(self, request, username=None, password=None, **kwargs):
|
||||
print("NoPasswordAuthBackend")
|
||||
# First, attempt normal authentication
|
||||
user = super().authenticate(request, username=username, password=password, **kwargs)
|
||||
if user is None:
|
||||
return None
|
||||
|
||||
if SocialAccount.objects.filter(user=user).exists() and user.disable_password:
|
||||
# If yes, disable login via password
|
||||
return None
|
||||
|
||||
return user
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.0.8 on 2025-03-17 01:15
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0003_alter_customuser_email'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='disable_password',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
|
@ -8,6 +8,7 @@ class CustomUser(AbstractUser):
|
|||
profile_pic = ResizedImageField(force_format="WEBP", quality=75, null=True, blank=True, upload_to='profile-pics/')
|
||||
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
||||
public_profile = models.BooleanField(default=False)
|
||||
disable_password = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return self.username
|
|
@ -64,9 +64,11 @@ class UserDetailsSerializer(serializers.ModelSerializer):
|
|||
extra_fields.append('date_joined')
|
||||
if hasattr(UserModel, 'is_staff'):
|
||||
extra_fields.append('is_staff')
|
||||
if hasattr(UserModel, 'disable_password'):
|
||||
extra_fields.append('disable_password')
|
||||
|
||||
fields = ['pk', *extra_fields]
|
||||
read_only_fields = ('email', 'date_joined', 'is_staff', 'is_superuser', 'is_active', 'pk')
|
||||
read_only_fields = ('email', 'date_joined', 'is_staff', 'is_superuser', 'is_active', 'pk', 'disable_password')
|
||||
|
||||
def handle_public_profile_change(self, instance, validated_data):
|
||||
"""
|
||||
|
@ -94,8 +96,8 @@ class CustomUserDetailsSerializer(UserDetailsSerializer):
|
|||
|
||||
class Meta(UserDetailsSerializer.Meta):
|
||||
model = CustomUser
|
||||
fields = UserDetailsSerializer.Meta.fields + ['profile_pic', 'uuid', 'public_profile', 'has_password']
|
||||
read_only_fields = UserDetailsSerializer.Meta.read_only_fields + ('uuid', 'has_password')
|
||||
fields = UserDetailsSerializer.Meta.fields + ['profile_pic', 'uuid', 'public_profile', 'has_password', 'disable_password']
|
||||
read_only_fields = UserDetailsSerializer.Meta.read_only_fields + ('uuid', 'has_password', 'disable_password')
|
||||
|
||||
@staticmethod
|
||||
def get_has_password(instance):
|
||||
|
@ -120,5 +122,5 @@ class CustomUserDetailsSerializer(UserDetailsSerializer):
|
|||
representation.pop('pk', None)
|
||||
# Remove the email field
|
||||
representation.pop('email', None)
|
||||
|
||||
|
||||
return representation
|
||||
|
|
|
@ -13,6 +13,7 @@ from .serializers import CustomUserDetailsSerializer as PublicUserSerializer
|
|||
from allauth.socialaccount.models import SocialApp
|
||||
from adventures.serializers import AdventureSerializer, CollectionSerializer
|
||||
from adventures.models import Adventure, Collection
|
||||
from allauth.socialaccount.models import SocialAccount
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
@ -71,6 +72,7 @@ class PublicUserListView(APIView):
|
|||
# for every user, remove the field has_password
|
||||
for user in serializer.data:
|
||||
user.pop('has_password', None)
|
||||
user.pop('disable_password', None)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
class PublicUserDetailView(APIView):
|
||||
|
@ -171,4 +173,35 @@ class EnabledSocialProvidersView(APIView):
|
|||
'url': f"{getenv('PUBLIC_URL')}/accounts/{new_provider}/login/",
|
||||
'name': provider.name
|
||||
})
|
||||
return Response(providers, status=status.HTTP_200_OK)
|
||||
return Response(providers, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class DisablePasswordAuthenticationView(APIView):
|
||||
"""
|
||||
Disable password authentication for a user. This is used when a user signs up with a social provider.
|
||||
"""
|
||||
|
||||
# Allows the user to set the disable_password field to True if they have a social account linked
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@swagger_auto_schema(
|
||||
responses={
|
||||
200: openapi.Response('Password authentication disabled'),
|
||||
400: 'Bad Request'
|
||||
},
|
||||
operation_description="Disable password authentication."
|
||||
)
|
||||
def post(self, request):
|
||||
user = request.user
|
||||
if SocialAccount.objects.filter(user=user).exists():
|
||||
user.disable_password = True
|
||||
user.save()
|
||||
return Response({"detail": "Password authentication disabled."}, status=status.HTTP_200_OK)
|
||||
return Response({"detail": "No social account linked."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def delete(self, request):
|
||||
user = request.user
|
||||
user.disable_password = False
|
||||
user.save()
|
||||
return Response({"detail": "Password authentication enabled."}, status=status.HTTP_200_OK)
|
||||
|
|
@ -34,19 +34,23 @@ class CountrySerializer(serializers.ModelSerializer):
|
|||
|
||||
class RegionSerializer(serializers.ModelSerializer):
|
||||
num_cities = serializers.SerializerMethodField()
|
||||
country_name = serializers.CharField(source='country.name', read_only=True)
|
||||
class Meta:
|
||||
model = Region
|
||||
fields = '__all__'
|
||||
read_only_fields = ['id', 'name', 'country', 'longitude', 'latitude', 'num_cities']
|
||||
read_only_fields = ['id', 'name', 'country', 'longitude', 'latitude', 'num_cities', 'country_name']
|
||||
|
||||
def get_num_cities(self, obj):
|
||||
return City.objects.filter(region=obj).count()
|
||||
|
||||
class CitySerializer(serializers.ModelSerializer):
|
||||
region_name = serializers.CharField(source='region.name', read_only=True)
|
||||
country_name = serializers.CharField(source='region.country.name', read_only=True
|
||||
)
|
||||
class Meta:
|
||||
model = City
|
||||
fields = '__all__'
|
||||
read_only_fields = ['id', 'name', 'region', 'longitude', 'latitude']
|
||||
read_only_fields = ['id', 'name', 'region', 'longitude', 'latitude', 'region_name', 'country_name']
|
||||
|
||||
class VisitedRegionSerializer(CustomModelSerializer):
|
||||
longitude = serializers.DecimalField(source='region.longitude', max_digits=9, decimal_places=6, read_only=True)
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
"dependencies": {
|
||||
"@lukulent/svelte-umami": "^0.0.3",
|
||||
"@mapbox/togeojson": "^0.16.2",
|
||||
"dompurify": "^3.2.4",
|
||||
"emoji-picker-element": "^1.26.0",
|
||||
"gsap": "^3.12.7",
|
||||
"marked": "^15.0.4",
|
||||
|
|
16
frontend/pnpm-lock.yaml
generated
16
frontend/pnpm-lock.yaml
generated
|
@ -14,6 +14,9 @@ importers:
|
|||
'@mapbox/togeojson':
|
||||
specifier: ^0.16.2
|
||||
version: 0.16.2
|
||||
dompurify:
|
||||
specifier: ^3.2.4
|
||||
version: 3.2.4
|
||||
emoji-picker-element:
|
||||
specifier: ^1.26.0
|
||||
version: 1.26.0
|
||||
|
@ -816,6 +819,9 @@ packages:
|
|||
'@types/supercluster@7.1.3':
|
||||
resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==}
|
||||
|
||||
'@types/trusted-types@2.0.7':
|
||||
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
||||
|
||||
'@vercel/nft@0.27.2':
|
||||
resolution: {integrity: sha512-7LeioS1yE5hwPpQfD3DdH04tuugKjo5KrJk3yK5kAI3Lh76iSsK/ezoFQfzuT08X3ZASQOd1y9ePjLNI9+TxTQ==}
|
||||
engines: {node: '>=16'}
|
||||
|
@ -1093,6 +1099,9 @@ packages:
|
|||
dlv@1.1.3:
|
||||
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
|
||||
|
||||
dompurify@3.2.4:
|
||||
resolution: {integrity: sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==}
|
||||
|
||||
earcut@2.2.4:
|
||||
resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==}
|
||||
|
||||
|
@ -2828,6 +2837,9 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/geojson': 7946.0.14
|
||||
|
||||
'@types/trusted-types@2.0.7':
|
||||
optional: true
|
||||
|
||||
'@vercel/nft@0.27.2':
|
||||
dependencies:
|
||||
'@mapbox/node-pre-gyp': 1.0.11
|
||||
|
@ -3094,6 +3106,10 @@ snapshots:
|
|||
|
||||
dlv@1.1.3: {}
|
||||
|
||||
dompurify@3.2.4:
|
||||
optionalDependencies:
|
||||
'@types/trusted-types': 2.0.7
|
||||
|
||||
earcut@2.2.4: {}
|
||||
|
||||
eastasianwidth@0.2.0: {}
|
||||
|
|
1
frontend/src/app.d.ts
vendored
1
frontend/src/app.d.ts
vendored
|
@ -16,6 +16,7 @@ declare global {
|
|||
uuid: string;
|
||||
public_profile: boolean;
|
||||
has_password: boolean;
|
||||
disable_password: boolean;
|
||||
} | null;
|
||||
locale: string;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,57 @@
|
|||
|
||||
let categories: Category[] = [];
|
||||
|
||||
const allowedFileTypes = [
|
||||
'.pdf',
|
||||
'.doc',
|
||||
'.docx',
|
||||
'.xls',
|
||||
'.xlsx',
|
||||
'.ppt',
|
||||
'.pptx',
|
||||
'.txt',
|
||||
'.png',
|
||||
'.jpg',
|
||||
'.jpeg',
|
||||
'.gif',
|
||||
'.webp',
|
||||
'.mp4',
|
||||
'.mov',
|
||||
'.avi',
|
||||
'.mkv',
|
||||
'.mp3',
|
||||
'.wav',
|
||||
'.flac',
|
||||
'.ogg',
|
||||
'.m4a',
|
||||
'.wma',
|
||||
'.aac',
|
||||
'.opus',
|
||||
'.zip',
|
||||
'.rar',
|
||||
'.7z',
|
||||
'.tar',
|
||||
'.gz',
|
||||
'.bz2',
|
||||
'.xz',
|
||||
'.zst',
|
||||
'.lz4',
|
||||
'.lzma',
|
||||
'.lzo',
|
||||
'.z',
|
||||
'.tar.gz',
|
||||
'.tar.bz2',
|
||||
'.tar.xz',
|
||||
'.tar.zst',
|
||||
'.tar.lz4',
|
||||
'.tar.lzma',
|
||||
'.tar.lzo',
|
||||
'.tar.z',
|
||||
'gpx',
|
||||
'md',
|
||||
'pdf'
|
||||
];
|
||||
|
||||
export let initialLatLng: { lat: number; lng: number } | null = null; // Used to pass the location from the map selection to the modal
|
||||
|
||||
let fileInput: HTMLInputElement;
|
||||
|
@ -783,7 +834,7 @@
|
|||
type="file"
|
||||
id="fileInput"
|
||||
class="file-input file-input-bordered w-full max-w-xs"
|
||||
accept="image/*,video/*,audio/*,application/pdf,.gpx"
|
||||
accept={allowedFileTypes.join(',')}
|
||||
on:change={handleFileChange}
|
||||
/>
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { addToast } from '$lib/toasts';
|
||||
import type { City } from '$lib/types';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
@ -45,7 +46,10 @@
|
|||
<div class="card-body">
|
||||
<h2 class="card-title overflow-ellipsis">{city.name}</h2>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<div class="badge badge-neutral-300">{city.id}</div>
|
||||
<div class="badge badge-primary">
|
||||
{city.region_name}, {city.country_name}
|
||||
</div>
|
||||
<div class="badge badge-neutral-300">{city.region}</div>
|
||||
</div>
|
||||
<div class="card-actions justify-end">
|
||||
{#if !visited}
|
||||
|
|
|
@ -6,9 +6,18 @@
|
|||
import { addToast } from '$lib/toasts';
|
||||
import { t } from 'svelte-i18n';
|
||||
import DeleteWarning from './DeleteWarning.svelte';
|
||||
import { LODGING_TYPES_ICONS } from '$lib';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
function getLodgingIcon(type: string) {
|
||||
if (type in LODGING_TYPES_ICONS) {
|
||||
return LODGING_TYPES_ICONS[type as keyof typeof LODGING_TYPES_ICONS];
|
||||
} else {
|
||||
return '🏨';
|
||||
}
|
||||
}
|
||||
|
||||
export let lodging: Lodging;
|
||||
export let user: User | null = null;
|
||||
export let collection: Collection | null = null;
|
||||
|
@ -91,7 +100,7 @@
|
|||
<h2 class="card-title text-lg font-semibold truncate">{lodging.name}</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="badge badge-secondary">
|
||||
{$t(`lodging.${lodging.type}`)}
|
||||
{$t(`lodging.${lodging.type}`) + ' ' + getLodgingIcon(lodging.type)}
|
||||
</div>
|
||||
<!-- {#if hotel.type == 'plane' && hotel.flight_number}
|
||||
<div class="badge badge-neutral-200">{hotel.flight_number}</div>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { marked } from 'marked'; // Import the markdown parser
|
||||
import { t } from 'svelte-i18n';
|
||||
import DOMPurify from 'dompurify'; // Import DOMPurify to sanitize HTML
|
||||
|
||||
export let text: string | null | undefined = ''; // Markdown text
|
||||
export let editor_height: string = 'h-64'; // Editor height
|
||||
|
@ -8,7 +9,7 @@
|
|||
|
||||
// Function to parse markdown to HTML
|
||||
const renderMarkdown = (markdown: string) => {
|
||||
return marked(markdown);
|
||||
return marked(markdown) as string;
|
||||
};
|
||||
|
||||
// References for scroll syncing
|
||||
|
@ -61,7 +62,7 @@
|
|||
class="prose overflow-auto h-96 max-w-full w-full p-4 border border-base-300 rounded-lg bg-base-300"
|
||||
bind:this={previewRef}
|
||||
>
|
||||
{@html renderMarkdown(text || '')}
|
||||
{@html DOMPurify.sanitize(renderMarkdown(text || ''))}
|
||||
</article>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
@ -56,11 +56,14 @@
|
|||
<h2 class="card-title overflow-ellipsis">{region.name}</h2>
|
||||
<div>
|
||||
<div class="badge badge-primary">
|
||||
<p>{region.id}</p>
|
||||
<p>{region.country_name}</p>
|
||||
</div>
|
||||
<div class="badge badge-neutral-300">
|
||||
<p>{region.num_cities} {$t('worldtravel.cities')}</p>
|
||||
</div>
|
||||
<div class="badge badge-neutral-300">
|
||||
<p>{region.id}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-actions justify-end">
|
||||
<!-- <button class="btn btn-info" on:click={moreInfo}>More Info</button> -->
|
||||
|
|
|
@ -324,6 +324,20 @@ export let ADVENTURE_TYPE_ICONS = {
|
|||
other: '❓'
|
||||
};
|
||||
|
||||
export let LODGING_TYPES_ICONS = {
|
||||
hotel: '🏨',
|
||||
hostel: '🛏️',
|
||||
resort: '🏝️',
|
||||
bnb: '🍳',
|
||||
campground: '🏕️',
|
||||
cabin: '🏚️',
|
||||
apartment: '🏢',
|
||||
house: '🏠',
|
||||
villa: '🏡',
|
||||
motel: '🚗🏨',
|
||||
other: '❓'
|
||||
};
|
||||
|
||||
export function getAdventureTypeLabel(type: string) {
|
||||
// return the emoji ADVENTURE_TYPE_ICONS label for the given type if not found return ? emoji
|
||||
if (type in ADVENTURE_TYPE_ICONS) {
|
||||
|
|
|
@ -9,6 +9,7 @@ export type User = {
|
|||
uuid: string;
|
||||
public_profile: boolean;
|
||||
has_password: boolean;
|
||||
disable_password: boolean;
|
||||
};
|
||||
|
||||
export type Adventure = {
|
||||
|
@ -63,6 +64,7 @@ export type Region = {
|
|||
latitude: number;
|
||||
longitude: number;
|
||||
num_cities: number;
|
||||
country_name: string;
|
||||
};
|
||||
|
||||
export type City = {
|
||||
|
@ -71,6 +73,8 @@ export type City = {
|
|||
latitude: number | null;
|
||||
longitude: number | null;
|
||||
region: string;
|
||||
region_name: string;
|
||||
country_name: string;
|
||||
};
|
||||
|
||||
export type VisitedRegion = {
|
||||
|
|
|
@ -6,32 +6,32 @@
|
|||
"message": "Hergestellt mit ❤️ in den Vereinigten Staaten.",
|
||||
"nominatim_1": "Standortsuche und Geokodierung werden bereitgestellt von",
|
||||
"nominatim_2": "Deren Daten sind unter der ODbL-Lizenz lizenziert.",
|
||||
"oss_attributions": "Open-Source-Zuschreibungen",
|
||||
"oss_attributions": "Open Source Quellenangaben",
|
||||
"other_attributions": "Weitere Hinweise finden Sie in der README-Datei.",
|
||||
"source_code": "Quellcode"
|
||||
},
|
||||
"adventures": {
|
||||
"activities": {
|
||||
"activity": "Aktivität 🏄",
|
||||
"art_museums": "Kunst",
|
||||
"attraction": "Attraktion 🎢",
|
||||
"art_museums": "Kunst & Museen",
|
||||
"attraction": "Sehenswürdigkeit 🎢",
|
||||
"culture": "Kultur 🎭",
|
||||
"dining": "Essen 🍽️",
|
||||
"event": "Veranstaltung 🎉",
|
||||
"festivals": "Feste 🎪",
|
||||
"festivals": "Festivals 🎪",
|
||||
"fitness": "Fitness 🏋️",
|
||||
"general": "Allgemein 🌍",
|
||||
"hiking": "Wandern 🥾",
|
||||
"historical_sites": "Historische Stätten 🏛️",
|
||||
"lodging": "Unterkunft 🛌",
|
||||
"music_concerts": "Musik",
|
||||
"historical_sites": "Historische Denkmäler 🏛️",
|
||||
"lodging": "Herberge 🛌",
|
||||
"music_concerts": "Musik & Konzerte",
|
||||
"nightlife": "Nachtleben 🌃",
|
||||
"other": "Andere",
|
||||
"outdoor": "Draußen 🏞️",
|
||||
"other": "Sonstiges",
|
||||
"outdoor": "Outdoor 🏞️",
|
||||
"shopping": "Einkaufen 🛍️",
|
||||
"spiritual_journeys": "Spirituelle Reisen 🧘♀️",
|
||||
"transportation": "Transport 🚗",
|
||||
"volunteer_work": "Freiwilligenarbeit 🤝",
|
||||
"volunteer_work": "Ehrenamt 🤝",
|
||||
"water_sports": "Wassersport 🚤",
|
||||
"wildlife": "Wildtiere 🦒"
|
||||
},
|
||||
|
@ -44,8 +44,8 @@
|
|||
"delete": "Löschen",
|
||||
"edit_adventure": "Abenteuer bearbeiten",
|
||||
"no_image_found": "Kein Bild gefunden",
|
||||
"open_details": "Details öffnen",
|
||||
"remove_from_collection": "Aus der Sammlung entfernen",
|
||||
"open_details": "Details",
|
||||
"remove_from_collection": "Aus Sammlung entfernen",
|
||||
"adventure": "Abenteuer",
|
||||
"adventure_delete_success": "Abenteuer erfolgreich gelöscht!",
|
||||
"adventure_details": "Abenteuerdetails",
|
||||
|
@ -60,8 +60,8 @@
|
|||
"clear": "zurücksetzen",
|
||||
"close_filters": "Filter schließen",
|
||||
"collection": "Sammlung",
|
||||
"collection_adventures": "Sammlungsabenteuer berücksichtigen",
|
||||
"count_txt": "Ergebnisse, die Ihrer Suche entsprechen",
|
||||
"collection_adventures": "Abenteuer aus Sammlung berücksichtigen",
|
||||
"count_txt": "Suchergebnisse",
|
||||
"date": "Datum",
|
||||
"dates": "Termine",
|
||||
"delete_adventure": "Abenteuer löschen",
|
||||
|
@ -77,14 +77,14 @@
|
|||
"image_removed_success": "Bild erfolgreich entfernt!",
|
||||
"image_upload_error": "Fehler beim Hochladen des Bildes",
|
||||
"image_upload_success": "Bild erfolgreich hochgeladen!",
|
||||
"latitude": "Breite",
|
||||
"longitude": "Länge",
|
||||
"latitude": "Breitengrad",
|
||||
"longitude": "Längengrad",
|
||||
"my_collections": "Meine Sammlungen",
|
||||
"name": "Name",
|
||||
"no_image_url": "Unter dieser URL wurde kein Bild gefunden.",
|
||||
"not_found": "Abenteuer nicht gefunden",
|
||||
"not_found_desc": "Das von Ihnen gesuchte Abenteuer konnte nicht gefunden werden. \nBitte probieren Sie ein anderes Abenteuer aus oder schauen Sie später noch einmal vorbei.",
|
||||
"open_filters": "Öffnen Sie Filter",
|
||||
"not_found_desc": "Das von Ihnen gesuchte Abenteuer konnte nicht gefunden werden. \nBitte versuchen Sie ein anderes Abenteuer aus oder schauen Sie später noch mal vorbei.",
|
||||
"open_filters": "Filter öffnen",
|
||||
"order_by": "Sortieren nach",
|
||||
"order_direction": "Sortierreihenfolge",
|
||||
"planned": "Geplant",
|
||||
|
@ -94,7 +94,7 @@
|
|||
"share": "Teilen",
|
||||
"sort": "Sortieren",
|
||||
"sources": "Quellen",
|
||||
"start_before_end_error": "Das Startdatum muss vor dem Enddatum liegen",
|
||||
"start_before_end_error": "Das Start- muss vor dem Enddatum liegen",
|
||||
"unarchive": "Dearchivieren",
|
||||
"unarchived_collection_message": "Sammlung erfolgreich dearchiviert!",
|
||||
"updated": "Aktualisiert",
|
||||
|
@ -106,18 +106,18 @@
|
|||
"activity": "Aktivität",
|
||||
"activity_types": "Aktivitätstypen",
|
||||
"add": "Hinzufügen",
|
||||
"add_an_activity": "Fügen Sie eine Aktivität hinzu",
|
||||
"add_an_activity": "Aktivität hinzufügen",
|
||||
"add_notes": "Notizen hinzufügen",
|
||||
"adventure_create_error": "Das Abenteuer konnte nicht erstellt werden",
|
||||
"adventure_created": "Abenteuer erstellt",
|
||||
"adventure_update_error": "Das Abenteuer konnte nicht aktualisiert werden",
|
||||
"adventure_updated": "Abenteuer aktualisiert",
|
||||
"basic_information": "Grundlegende Informationen",
|
||||
"basic_information": "Basisdaten",
|
||||
"category": "Kategorie",
|
||||
"clear_map": "Karte leeren",
|
||||
"copy_link": "Link kopieren",
|
||||
"create_new": "Neu erstellen...",
|
||||
"date_constrain": "Auf Abholtermine beschränken",
|
||||
"date_constrain": "Beschränke auf Sammlungstermine",
|
||||
"description": "Beschreibung",
|
||||
"end_date": "Enddatum",
|
||||
"fetch_image": "Bild abrufen",
|
||||
|
@ -138,7 +138,7 @@
|
|||
"public_adventure": "Öffentliches Abenteuer",
|
||||
"remove": "Entfernen",
|
||||
"save_next": "Speichern & weiter",
|
||||
"search_for_location": "Suchen Sie nach einem Ort",
|
||||
"search_for_location": "Nach einem Ort suchen",
|
||||
"search_results": "Suchergebnisse",
|
||||
"see_adventures": "Siehe Abenteuer",
|
||||
"select_adventure_category": "Wählen Sie die Abenteuerkategorie",
|
||||
|
@ -150,14 +150,14 @@
|
|||
"warning": "Warnung",
|
||||
"wiki_desc": "Ruft einen Auszug aus einem Wikipedia-Artikel ab, der zum Namen des Abenteuers passt.",
|
||||
"wikipedia": "Wikipedia",
|
||||
"adventure_not_found": "Es sind keine Abenteuer zum Anzeigen vorhanden. \nFügen Sie einige über die Plus-Schaltfläche unten rechts hinzu oder versuchen Sie, die Filter zu ändern!",
|
||||
"adventure_not_found": "Keine Abenteuer vorhanden. \nFügen Sie welche über die Plus-Schaltfläche unten rechts hinzu oder versuchen Sie, die Filter zu ändern!",
|
||||
"all": "Alle",
|
||||
"error_updating_regions": "Fehler beim Aktualisieren der Regionen",
|
||||
"mark_region_as_visited": "Region {region}, {country} als besucht markieren?",
|
||||
"mark_visited": "als besucht markieren",
|
||||
"my_adventures": "Meine Abenteuer",
|
||||
"no_adventures_found": "Keine Abenteuer gefunden",
|
||||
"no_collections_found": "Es wurden keine Sammlungen gefunden, zu denen dieses Abenteuer hinzugefügt werden kann.",
|
||||
"no_collections_found": "Es wurden keine Sammlungen gefunden, die zu diesem Abenteuer hinzugefügt werden können.",
|
||||
"no_linkable_adventures": "Es wurden keine Abenteuer gefunden, die mit dieser Sammlung verknüpft werden können.",
|
||||
"not_visited": "Nicht besucht",
|
||||
"regions_updated": "Regionen aktualisiert",
|
||||
|
@ -165,65 +165,65 @@
|
|||
"update_visited_regions_disclaimer": "Dies kann je nach Anzahl der Abenteuer, die Sie besucht haben, eine Weile dauern.",
|
||||
"visited_region_check": "Überprüfung der besuchten Region",
|
||||
"visited_region_check_desc": "Wenn Sie diese Option auswählen, überprüft der Server alle von Ihnen besuchten Abenteuer und markiert die Regionen, in denen sie sich befinden, im Bereich Weltreisen als besucht.",
|
||||
"add_new": "Neu hinzufügen...",
|
||||
"add_new": "Neu...",
|
||||
"checklist": "Checkliste",
|
||||
"checklists": "Checklisten",
|
||||
"collection_completed": "Du hast diese Sammlung vervollständigt!",
|
||||
"collection_completed": "Du hast die Sammlung vervollständigt!",
|
||||
"collection_stats": "Sammlungsstatistiken",
|
||||
"days": "Tage",
|
||||
"itineary_by_date": "Reiseroute nach Datum",
|
||||
"keep_exploring": "Entdecken Sie weiter!",
|
||||
"link_new": "Link Neu...",
|
||||
"keep_exploring": "Weiter erkunden!",
|
||||
"link_new": "Neuer Link...",
|
||||
"linked_adventures": "Verknüpfte Abenteuer",
|
||||
"links": "Links",
|
||||
"no_end_date": "Bitte geben Sie ein Enddatum ein",
|
||||
"no_end_date": "Bitte ein Enddatum eingeben",
|
||||
"note": "Notiz",
|
||||
"notes": "Notizen",
|
||||
"nothing_planned": "Für diesen Tag ist nichts geplant. \nGenieße die Reise!",
|
||||
"nothing_planned": "Für heute ist nichts geplant. \nGenieße die Reise!",
|
||||
"transportation": "Transport",
|
||||
"transportations": "Transporte",
|
||||
"visit_link": "Besuchen Sie den Link",
|
||||
"collection_archived": "Diese Sammlung wurde archiviert.",
|
||||
"visit_link": "Besuche Link",
|
||||
"collection_archived": "Die Sammlung wurde archiviert.",
|
||||
"day": "Tag",
|
||||
"add_a_tag": "Fügen Sie einen Tag hinzu",
|
||||
"add_a_tag": "Fügen Sie ein Schlagwort hinzu",
|
||||
"tags": "Schlagworte",
|
||||
"set_to_pin": "Auf „Anpinnen“ setzen",
|
||||
"category_fetch_error": "Fehler beim Abrufen der Kategorien",
|
||||
"copied_to_clipboard": "In die Zwischenablage kopiert!",
|
||||
"copy_failed": "Das Kopieren ist fehlgeschlagen",
|
||||
"adventure_calendar": "Abenteuerkalender",
|
||||
"emoji_picker": "Emoji-Picker",
|
||||
"emoji_picker": "Emoji-Wähler",
|
||||
"hide": "Verstecken",
|
||||
"show": "Zeigen",
|
||||
"download_calendar": "Kalender herunterladen",
|
||||
"md_instructions": "Schreiben Sie hier Ihren Markdowntext...",
|
||||
"md_instructions": "Hier den Markdowntext schreiben...",
|
||||
"preview": "Vorschau",
|
||||
"checklist_delete_confirm": "Sind Sie sicher, dass Sie diese Checkliste löschen möchten? \nDiese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"checklist_delete_confirm": "Sind Sie sicher, dass Sie diese Checkliste löschen möchten? \nDies kann nicht rückgängig gemacht werden.",
|
||||
"clear_location": "Standort löschen",
|
||||
"date_information": "Datumsinformationen",
|
||||
"delete_checklist": "Checkliste löschen",
|
||||
"delete_note": "Notiz löschen",
|
||||
"delete_transportation": "Transport löschen",
|
||||
"end": "Ende",
|
||||
"ending_airport": "Endflughafen",
|
||||
"ending_airport": "Zielflughafen",
|
||||
"flight_information": "Fluginformationen",
|
||||
"from": "Von",
|
||||
"no_location_found": "Kein Standort gefunden",
|
||||
"note_delete_confirm": "Sind Sie sicher, dass Sie diese Notiz löschen möchten? \nDiese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"out_of_range": "Nicht im Datumsbereich der Reiseroute",
|
||||
"no_location_found": "Keinen Standort gefunden",
|
||||
"note_delete_confirm": "Sind Sie sicher, dass Sie diese Notiz löschen möchten? \nDies kann nicht rückgängig gemacht werden!",
|
||||
"out_of_range": "Außerhalb des geplanten Reisezeitraums",
|
||||
"show_region_labels": "Regionsbeschriftungen anzeigen",
|
||||
"start": "Start",
|
||||
"starting_airport": "Startflughafen",
|
||||
"to": "Nach",
|
||||
"transportation_delete_confirm": "Sind Sie sicher, dass Sie diesen Transport löschen möchten? \nDiese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"transportation_delete_confirm": "Sind Sie sicher, dass Sie diesen Transport löschen möchten? \nDies lässt sich nicht rückgängig machen.",
|
||||
"show_map": "Karte anzeigen",
|
||||
"will_be_marked": "wird als besucht markiert, sobald das Abenteuer gespeichert ist.",
|
||||
"will_be_marked": "wird als besucht markiert, sobald das Abenteuer gespeichert wird.",
|
||||
"cities_updated": "Städte aktualisiert",
|
||||
"create_adventure": "Erstelle Abenteuer",
|
||||
"no_adventures_to_recommendations": "Keine Abenteuer gefunden. \nFügen Sie mindestens ein Abenteuer hinzu, um Empfehlungen zu erhalten.",
|
||||
"finding_recommendations": "Entdecken Sie verborgene Schätze für Ihr nächstes Abenteuer",
|
||||
"attachment": "Anhang",
|
||||
"attachment_delete_success": "Anhang erfolgreich gelöscht!",
|
||||
"attachment_delete_success": "Anhang gelöscht!",
|
||||
"attachment_name": "Anhangsname",
|
||||
"attachment_update_error": "Fehler beim Aktualisieren des Anhangs",
|
||||
"attachment_update_success": "Anhang erfolgreich aktualisiert!",
|
||||
|
@ -242,26 +242,26 @@
|
|||
"lodging": "Unterkunft",
|
||||
"region": "Region",
|
||||
"delete_lodging": "Unterkunft löschen",
|
||||
"lodging_delete_confirm": "Sind Sie sicher, dass Sie diesen Standort löschen möchten? \nDiese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"lodging_information": "Unterkunftsinformationen",
|
||||
"lodging_delete_confirm": "Sind Sie sicher, dass Sie diese Unterkunft löschen möchten? \nDies lässt sich nicht rückgängig machen!",
|
||||
"lodging_information": "Informationen zur Unterkunft",
|
||||
"price": "Preis",
|
||||
"reservation_number": "Reservierungsnummer",
|
||||
"welcome_map_info": "Öffentliche Abenteuer auf diesem Server",
|
||||
"open_in_maps": "In Karten geöffnet"
|
||||
"welcome_map_info": "Frei zugängliche Abenteuer auf diesem Server",
|
||||
"open_in_maps": "In Karten öffnen"
|
||||
},
|
||||
"home": {
|
||||
"desc_1": "Entdecken, planen und erkunden Sie mit Leichtigkeit",
|
||||
"desc_2": "AdventureLog wurde entwickelt, um Ihre Reise zu vereinfachen und Ihnen die Tools und Ressourcen zur Verfügung zu stellen, mit denen Sie Ihr nächstes unvergessliches Abenteuer planen, packen und navigieren können.",
|
||||
"desc_1": "Entdecken, planen und erkunden Sie mühelos",
|
||||
"desc_2": "AdventureLog wurde entwickelt, um Ihre Reise zu vereinfachen und stellt Ihnen alle nötigen Werkzeuge und Ressourcen zur Verfügung, mit denen Sie Ihr nächstes unvergessliches Abenteuer planen, packen und erleben können.",
|
||||
"feature_1": "Reisetagebuch",
|
||||
"feature_1_desc": "Behalten Sie den Überblick über Ihre Abenteuer mit einem personalisierten Reisetagebuch und teilen Sie Ihre Erlebnisse mit Freunden und Familie.",
|
||||
"feature_1_desc": "Dokumentieren Sie Ihre Abenteuer mit einem persönlichen Reisetagebuch und teilen Sie Ihre Erlebnisse mit Freunden und Familie.",
|
||||
"feature_2": "Reiseplanung",
|
||||
"feature_3": "Reisekarte",
|
||||
"feature_3_desc": "Sehen Sie sich Ihre Reisen rund um die Welt mit einer interaktiven Karte an und erkunden Sie neue Reiseziele.",
|
||||
"go_to": "Gehen Sie zu AdventureLog",
|
||||
"feature_3_desc": "Betrachten Sie Ihre Reisen rund um die Welt auf einer interaktiven Karte und entdecken Sie neue Ziele.",
|
||||
"go_to": "AdventureLog öffnen",
|
||||
"hero_1": "Entdecken Sie die aufregendsten Abenteuer der Welt",
|
||||
"hero_2": "Entdecken und planen Sie Ihr nächstes Abenteuer mit AdventureLog. \nEntdecken Sie atemberaubende Reiseziele, erstellen Sie individuelle Reiserouten und bleiben Sie unterwegs in Verbindung.",
|
||||
"hero_2": "Entdecken und planen Sie Ihr nächstes Abenteuer mit AdventureLog. Erkunden Sie atemberaubende Reiseziele, erstellen Sie individuelle Reisepläne und bleiben Sie unterwegs stets verbunden.",
|
||||
"key_features": "Hauptmerkmale",
|
||||
"feature_2_desc": "Erstellen Sie ganz einfach individuelle Reiserouten und erhalten Sie eine tagesaktuelle Aufschlüsselung Ihrer Reise."
|
||||
"feature_2_desc": "Erstellen Sie mühelos individuelle Reisepläne und erhalten Sie eine detaillierte Tagesübersicht Ihrer Reise."
|
||||
},
|
||||
"navbar": {
|
||||
"about": "Über AdventureLog",
|
||||
|
@ -277,7 +277,7 @@
|
|||
"search": "Suchen",
|
||||
"settings": "Einstellungen",
|
||||
"shared_with_me": "Mit mir geteilt",
|
||||
"theme_selection": "Themenauswahl",
|
||||
"theme_selection": "Design",
|
||||
"themes": {
|
||||
"aqua": "Aqua",
|
||||
"dark": "Dunkel",
|
||||
|
@ -285,17 +285,17 @@
|
|||
"light": "Hell",
|
||||
"night": "Nacht",
|
||||
"aestheticDark": "Ästhetisches Dunkel",
|
||||
"aestheticLight": "Ästhetisches Licht",
|
||||
"northernLights": "Nordlicht"
|
||||
"aestheticLight": "Ästhetisches Hell",
|
||||
"northernLights": "Nordlichter"
|
||||
},
|
||||
"users": "Benutzer",
|
||||
"worldtravel": "Weltreisen",
|
||||
"my_tags": "Meine Tags",
|
||||
"tag": "Etikett",
|
||||
"language_selection": "Sprache",
|
||||
"my_tags": "Meine Schlagworte",
|
||||
"tag": "Schlagwort",
|
||||
"language_selection": "Sprachauswahl",
|
||||
"support": "Unterstützung",
|
||||
"calendar": "Kalender",
|
||||
"admin_panel": "Admin -Panel"
|
||||
"admin_panel": "Administration"
|
||||
},
|
||||
"auth": {
|
||||
"confirm_password": "Passwort bestätigen",
|
||||
|
@ -304,7 +304,7 @@
|
|||
"forgot_password": "Passwort vergessen?",
|
||||
"last_name": "Nachname",
|
||||
"login": "Login",
|
||||
"login_error": "Anmeldung mit den angegebenen Anmeldeinformationen nicht möglich.",
|
||||
"login_error": "Die Anmeldung ist mit den angegebenen Anmeldeinformationen nicht möglich.",
|
||||
"password": "Passwort",
|
||||
"registration_disabled": "Die Registrierung ist derzeit deaktiviert.",
|
||||
"signup": "Melden Sie sich an",
|
||||
|
@ -323,7 +323,7 @@
|
|||
"user_collections": "Benutzersammlungen"
|
||||
},
|
||||
"users": {
|
||||
"no_users_found": "Keine Benutzer mit öffentlichen Profilen gefunden."
|
||||
"no_users_found": "Keine Benutzer mit öffentlichem Profil gefunden."
|
||||
},
|
||||
"worldtravel": {
|
||||
"all": "Alle",
|
||||
|
@ -337,34 +337,34 @@
|
|||
"partially_visited": "Teilweise besucht",
|
||||
"all_visited": "Sie haben alle Regionen besucht in",
|
||||
"cities": "Städte",
|
||||
"failed_to_mark_visit": "Der Besuch konnte nicht markiert werden",
|
||||
"failed_to_remove_visit": "Der Besuch von konnte nicht entfernt werden",
|
||||
"failed_to_mark_visit": "Fehler beim Markieren des Besuchs von",
|
||||
"failed_to_remove_visit": "Fehler beim Entfernen des Besuchs",
|
||||
"marked_visited": "als besucht markiert",
|
||||
"no_cities_found": "Keine Städte gefunden",
|
||||
"region_failed_visited": "Die Region konnte nicht als besucht markiert werden",
|
||||
"region_stats": "Regionsstatistiken",
|
||||
"regions_in": "Regionen in",
|
||||
"removed": "ENTFERNT",
|
||||
"removed": "entfernt",
|
||||
"view_cities": "Städte anzeigen",
|
||||
"visit_remove_failed": "Der Besuch konnte nicht entfernt werden",
|
||||
"visit_to": "Besuch bei"
|
||||
"visit_to": "Besuch von"
|
||||
},
|
||||
"settings": {
|
||||
"account_settings": "Benutzerkontoeinstellungen",
|
||||
"current_email": "Aktuelle E-Mail",
|
||||
"account_settings": "Benutzerkonto",
|
||||
"current_email": "Bisherige E-Mail",
|
||||
"email_change": "E-Mail ändern",
|
||||
"new_email": "Neue E-Mail",
|
||||
"new_password": "Neues Passwort",
|
||||
"no_email_set": "Keine E-Mail-Adresse festgelegt",
|
||||
"password_change": "Kennwort ändern",
|
||||
"settings_page": "Einstellungsseite",
|
||||
"settings_page": "Einstellungen",
|
||||
"update": "Aktualisieren",
|
||||
"update_error": "Fehler beim Aktualisieren der Einstellungen",
|
||||
"update_success": "Einstellungen erfolgreich aktualisiert!",
|
||||
"change_password": "Kennwort ändern",
|
||||
"confirm_new_password": "Bestätigen Sie das neue Passwort",
|
||||
"invalid_token": "Token ist ungültig oder abgelaufen",
|
||||
"login_redir": "Anschließend werden Sie zur Anmeldeseite weitergeleitet.",
|
||||
"invalid_token": "Das Token ist ungültig oder abgelaufen",
|
||||
"login_redir": "Anschließend erfolgt eine Weiterleitung zur Anmeldeseite.",
|
||||
"missing_email": "Bitte geben Sie eine E-Mail-Adresse ein",
|
||||
"password_does_not_match": "Passwörter stimmen nicht überein",
|
||||
"password_is_required": "Passwort ist erforderlich",
|
||||
|
@ -375,74 +375,82 @@
|
|||
"about_this_background": "Über diesen Hintergrund",
|
||||
"join_discord": "Treten Sie dem Discord bei",
|
||||
"join_discord_desc": "um Ihre eigenen Fotos zu teilen. \nVeröffentlichen Sie sie im",
|
||||
"photo_by": "Foto von",
|
||||
"change_password_error": "Passwort kann nicht geändert werden. \nUngültiges aktuelles Passwort oder ungültiges neues Passwort.",
|
||||
"photo_by": "Foto aufgenommen von",
|
||||
"change_password_error": "Das Passwort kann nicht geändert werden. \nUngültiges aktuelles oder neues Passwort.",
|
||||
"current_password": "Aktuelles Passwort",
|
||||
"password_change_lopout_warning": "Nach der Passwortänderung werden Sie abgemeldet.",
|
||||
"authenticator_code": "Authentifikatorcode",
|
||||
"authenticator_code": "Authentifizierungscode",
|
||||
"copy": "Kopie",
|
||||
"disable_mfa": "Deaktivieren Sie MFA",
|
||||
"email_added": "E-Mail erfolgreich hinzugefügt!",
|
||||
"email_added": "E-Mail hinzugefügt!",
|
||||
"email_added_error": "Fehler beim Hinzufügen der E-Mail",
|
||||
"email_removed": "E-Mail erfolgreich entfernt!",
|
||||
"email_removed": "E-Mail entfernt!",
|
||||
"email_removed_error": "Fehler beim Entfernen der E-Mail",
|
||||
"email_set_primary": "E-Mail erfolgreich als primäre E-Mail-Adresse festgelegt!",
|
||||
"email_set_primary_error": "Fehler beim Festlegen der E-Mail-Adresse als primär",
|
||||
"email_verified": "E-Mail erfolgreich bestätigt!",
|
||||
"email_set_primary": "E-Mail als primäre E-Mail-Adresse festgelegt!",
|
||||
"email_set_primary_error": "Die E-Mail-Adresse konnte nicht als primäre Adresse festgelegt werden",
|
||||
"email_verified": "E-Mail bestätigt!",
|
||||
"email_verified_erorr_desc": "Ihre E-Mail-Adresse konnte nicht bestätigt werden. \nBitte versuchen Sie es erneut.",
|
||||
"email_verified_error": "Fehler bei der E-Mail-Bestätigung",
|
||||
"email_verified_error": "Fehler bei der Verifizierung der E-Mail-Adresse",
|
||||
"email_verified_success": "Ihre E-Mail-Adresse wurde bestätigt. \nSie können sich jetzt anmelden.",
|
||||
"enable_mfa": "Aktivieren Sie MFA",
|
||||
"error_change_password": "Fehler beim Ändern des Passworts. \nBitte überprüfen Sie Ihr aktuelles Passwort und versuchen Sie es erneut.",
|
||||
"generic_error": "Bei der Bearbeitung Ihrer Anfrage ist ein Fehler aufgetreten.",
|
||||
"invalid_code": "Ungültiger MFA-Code",
|
||||
"invalid_credentials": "Ungültiger Benutzername oder Passwort",
|
||||
"make_primary": "Zum bevorzugten machen",
|
||||
"mfa_disabled": "Multi-Faktor-Authentifizierung erfolgreich deaktiviert!",
|
||||
"mfa_enabled": "Multi-Faktor-Authentifizierung erfolgreich aktiviert!",
|
||||
"mfa_not_enabled": "MFA ist nicht aktiviert",
|
||||
"mfa_page_title": "Multi-Faktor-Authentifizierung",
|
||||
"mfa_required": "Eine Multi-Faktor-Authentifizierung ist erforderlich",
|
||||
"make_primary": "Als primär festlegen",
|
||||
"mfa_disabled": "MFA-Authentifizierung deaktiviert!",
|
||||
"mfa_enabled": "MFA-Authentifizierung aktiviert!",
|
||||
"mfa_not_enabled": "MFA nicht aktiviert",
|
||||
"mfa_page_title": "Multi-Faktor-Authentifizierung (MFA)",
|
||||
"mfa_required": "MFA erforderlich",
|
||||
"no_emai_set": "Keine E-Mail-Adresse festgelegt",
|
||||
"not_verified": "Nicht verifiziert",
|
||||
"primary": "Primär",
|
||||
"recovery_codes": "Wiederherstellungscodes",
|
||||
"recovery_codes_desc": "Dies sind Ihre Wiederherstellungscodes. \nBewahren Sie sie sicher auf. \nSie werden sie nicht mehr sehen können.",
|
||||
"recovery_codes_desc": "Dies sind Ihre Wiederherstellungscodes. \nBewahren Sie sie sicher auf. \nSie werden nicht erneut angezeigt.",
|
||||
"reset_session_error": "Bitte melden Sie sich ab und wieder an, um Ihre Sitzung zu aktualisieren, und versuchen Sie es erneut.",
|
||||
"verified": "Verifiziert",
|
||||
"verify": "Verifizieren",
|
||||
"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!",
|
||||
"add_email_blocked": "Sie können keine E-Mail-Adresse zu einem Konto hinzufügen, das durch die Zwei-Faktor-Authentifizierung geschützt ist.",
|
||||
"verify_email_success": "E-Mail-Bestätigung gesendet!",
|
||||
"add_email_blocked": "Sie können keine E-Mail-Adresse zu einem Konto hinzufügen, das durch die Zwei-Faktor-Authentifizierung (MFA) geschützt ist.",
|
||||
"required": "Dieses Feld ist erforderlich",
|
||||
"csrf_failed": "CSRF-Token konnte nicht abgerufen werden",
|
||||
"csrf_failed": "Fehler beim Abrufen des CSRF-Tokens",
|
||||
"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.",
|
||||
"administration_settings": "Verwaltungseinstellungen",
|
||||
"documentation_link": "Dokumentationslink",
|
||||
"administration_settings": "Administrationseinstellungen",
|
||||
"documentation_link": "Dokumentation",
|
||||
"launch_account_connections": "Kontoverbindungen starten",
|
||||
"launch_administration_panel": "Starten Sie das Administrationspanel",
|
||||
"launch_administration_panel": "Administrationseinstellungen öffnen",
|
||||
"no_verified_email_warning": "Sie müssen über eine verifizierte E-Mail-Adresse verfügen, um die Zwei-Faktor-Authentifizierung zu aktivieren.",
|
||||
"social_auth_desc": "Aktivieren oder deaktivieren Sie soziale und OIDC-Authentifizierungsanbieter für Ihr Konto. \nMit diesen Verbindungen können Sie sich bei selbst gehosteten Authentifizierungsidentitätsanbietern wie Authentik oder Drittanbietern wie GitHub anmelden.",
|
||||
"social_auth_desc_2": "Diese Einstellungen werden auf dem AdventureLog-Server verwaltet und müssen vom Administrator manuell aktiviert werden.",
|
||||
"social_oidc_auth": "Soziale und OIDC-Authentifizierung",
|
||||
"add_email": "E-Mail hinzufügen",
|
||||
"password_too_short": "Das Passwort muss mindestens 6 Zeichen lang sein"
|
||||
"password_too_short": "Das Passwort muss mindestens 6 Zeichen lang sein",
|
||||
"disable_password": "Passwort deaktivieren",
|
||||
"password_disable": "Deaktivieren Sie die Passwortauthentifizierung",
|
||||
"password_disable_desc": "Durch Deaktivieren der Kennwortauthentifizierung werden Sie daran hindern, sich mit einem Kennwort anzumelden. \nSie müssen einen sozialen oder OIDC-Anbieter verwenden, um sich anzumelden. Sollte Ihr sozialer Anbieter nicht verknüpft werden, wird die Kennwortauthentifizierung automatisch wieder aufgenommen, auch wenn diese Einstellung deaktiviert ist.",
|
||||
"password_disable_warning": "Derzeit ist die Kennwortauthentifizierung deaktiviert. \nAnmelden Sie über einen sozialen oder OIDC -Anbieter erforderlich.",
|
||||
"password_disabled": "Kennwortauthentifizierung deaktiviert",
|
||||
"password_disabled_error": "Fehler beim Deaktivieren der Kennwortauthentifizierung. \nStellen Sie sicher, dass ein sozialer oder OIDC -Anbieter mit Ihrem Konto verknüpft ist.",
|
||||
"password_enabled": "Kennwortauthentifizierung aktiviert",
|
||||
"password_enabled_error": "Fehler zur Kennwortauthentifizierung."
|
||||
},
|
||||
"checklist": {
|
||||
"add_item": "Artikel hinzufügen",
|
||||
"add_item": "Eintrag hinzufügen",
|
||||
"checklist_delete_error": "Fehler beim Löschen der Checkliste",
|
||||
"checklist_deleted": "Checkliste erfolgreich gelöscht!",
|
||||
"checklist_deleted": "Checkliste gelöscht!",
|
||||
"checklist_editor": "Checklisten-Editor",
|
||||
"checklist_public": "Diese Checkliste ist öffentlich, da sie sich in einer öffentlichen Sammlung befindet.",
|
||||
"editing_checklist": "Checkliste bearbeiten",
|
||||
"failed_to_save": "Checkliste konnte nicht gespeichert werden",
|
||||
"item": "Artikel",
|
||||
"item_already_exists": "Artikel existiert bereits",
|
||||
"item_cannot_be_empty": "Das Element darf nicht leer sein",
|
||||
"items": "Artikel",
|
||||
"new_item": "Neuer Artikel",
|
||||
"item": "Eintrag",
|
||||
"item_already_exists": "Dieser Eintrag existiert bereits",
|
||||
"item_cannot_be_empty": "Der Eintrag darf nicht leer sein",
|
||||
"items": "Einträge",
|
||||
"new_item": "Neuer Eintrag",
|
||||
"save": "Speichern",
|
||||
"checklist_viewer": "Checklisten-Viewer",
|
||||
"new_checklist": "Neue Checkliste"
|
||||
|
@ -454,7 +462,7 @@
|
|||
"edit_collection": "Sammlung bearbeiten",
|
||||
"error_creating_collection": "Fehler beim Erstellen der Sammlung",
|
||||
"error_editing_collection": "Fehler beim Bearbeiten der Sammlung",
|
||||
"new_collection": "Neue Kollektion",
|
||||
"new_collection": "Neue Sammlung",
|
||||
"public_collection": "Öffentliche Sammlung"
|
||||
},
|
||||
"notes": {
|
||||
|
@ -466,7 +474,7 @@
|
|||
"note_deleted": "Notiz erfolgreich gelöscht!",
|
||||
"note_editor": "Notizeditor",
|
||||
"note_public": "Diese Notiz ist öffentlich, da sie sich in einer öffentlichen Sammlung befindet.",
|
||||
"open": "Offen",
|
||||
"open": "Öffnen",
|
||||
"save": "Speichern",
|
||||
"invalid_url": "Ungültige URL",
|
||||
"note_viewer": "Notizenbetrachter"
|
||||
|
@ -475,9 +483,9 @@
|
|||
"date_and_time": "Datum",
|
||||
"date_time": "Startdatum",
|
||||
"edit": "Bearbeiten",
|
||||
"edit_transportation": "Transport bearbeiten",
|
||||
"edit_transportation": "Verkehrsmittel bearbeiten",
|
||||
"end_date_time": "Enddatum",
|
||||
"error_editing_transportation": "Fehler beim Bearbeiten des Transports",
|
||||
"error_editing_transportation": "Fehler beim Bearbeiten des Verkehrsmittels",
|
||||
"flight_number": "Flugnummer",
|
||||
"from_location": "Vom Standort",
|
||||
"modes": {
|
||||
|
@ -490,19 +498,19 @@
|
|||
"plane": "Flugzeug",
|
||||
"train": "Zug"
|
||||
},
|
||||
"transportation_added": "Transport erfolgreich hinzugefügt!",
|
||||
"transportation_delete_error": "Fehler beim Löschen des Transports",
|
||||
"transportation_deleted": "Transport erfolgreich gelöscht!",
|
||||
"transportation_edit_success": "Transport erfolgreich bearbeitet!",
|
||||
"transportation_added": "Verkehrsmittel erfolgreich hinzugefügt!",
|
||||
"transportation_delete_error": "Fehler beim Löschen des Verkehrsmittels",
|
||||
"transportation_deleted": "Verkehrsmittel erfolgreich gelöscht!",
|
||||
"transportation_edit_success": "Verkehrsmittel erfolgreich bearbeitet!",
|
||||
"type": "Typ",
|
||||
"new_transportation": "Neue Transportmittel",
|
||||
"new_transportation": "Neues Verkehrsmittel",
|
||||
"provide_start_date": "Bitte geben Sie ein Startdatum an",
|
||||
"start": "Start",
|
||||
"to_location": "Zum Standort",
|
||||
"transport_type": "Transporttyp",
|
||||
"ending_airport_desc": "Geben Sie den Ending Airport Code ein (z. B. lax)",
|
||||
"transport_type": "Verkehrsmittel",
|
||||
"ending_airport_desc": "Geben Sie den Flughafencode des Zielflughafens ein (z. B. LAX)",
|
||||
"fetch_location_information": "Standortinformationen abrufen",
|
||||
"starting_airport_desc": "Geben Sie den Start -Flughafencode ein (z. B. JFK)"
|
||||
"starting_airport_desc": "Geben Sie den Flughafencode des Startflughafens ein (z. B. JFK)"
|
||||
},
|
||||
"search": {
|
||||
"adventurelog_results": "AdventureLog-Ergebnisse",
|
||||
|
@ -522,14 +530,14 @@
|
|||
"share": {
|
||||
"no_users_shared": "Keine Benutzer geteilt mit",
|
||||
"not_shared_with": "Nicht geteilt mit",
|
||||
"share_desc": "Teilen Sie diese Sammlung mit anderen Benutzern.",
|
||||
"share_desc": "Sammlung mit anderen Benutzern teilen.",
|
||||
"shared": "Geteilt",
|
||||
"shared_with": "Geteilt mit",
|
||||
"unshared": "Nicht geteilt",
|
||||
"with": "mit",
|
||||
"go_to_settings": "Gehen Sie zu den Einstellungen",
|
||||
"go_to_settings": "Gehe zu Einstellungen",
|
||||
"no_shared_found": "Es wurden keine Sammlungen gefunden, die mit Ihnen geteilt wurden.",
|
||||
"set_public": "Damit Benutzer Inhalte mit Ihnen teilen können, muss Ihr Profil auf „Öffentlich“ eingestellt sein."
|
||||
"set_public": "Damit Benutzer Inhalte mit Ihnen teilen können, muss Ihr Profil auf „Öffentlich“ gesetzt sein."
|
||||
},
|
||||
"profile": {
|
||||
"member_since": "Mitglied seit",
|
||||
|
@ -544,11 +552,11 @@
|
|||
"icon": "Symbol",
|
||||
"manage_categories": "Kategorien verwalten",
|
||||
"no_categories_found": "Keine Kategorien gefunden.",
|
||||
"select_category": "Kategorie auswählen",
|
||||
"select_category": "Kategorie wählen",
|
||||
"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.",
|
||||
"add_some": "Warum nicht gleich Ihr nächstes Abenteuer planen? Sie können ein neues Abenteuer hinzufügen, indem Sie auf den Button unten klicken.",
|
||||
"countries_visited": "Besuchte Länder",
|
||||
"no_recent_adventures": "Keine aktuellen Abenteuer?",
|
||||
"recent_adventures": "Aktuelle Abenteuer",
|
||||
|
@ -565,21 +573,21 @@
|
|||
"imageid_required": "Bild-ID ist erforderlich",
|
||||
"immich": "Immich",
|
||||
"immich_desc": "Integrieren Sie Ihr Immich-Konto mit AdventureLog, damit Sie Ihre Fotobibliothek durchsuchen und Fotos für Ihre Abenteuer importieren können.",
|
||||
"immich_disabled": "Immich-Integration erfolgreich deaktiviert!",
|
||||
"immich_enabled": "Immich-Integration erfolgreich aktiviert!",
|
||||
"immich_error": "Fehler beim Aktualisieren der Immich-Integration",
|
||||
"immich_disabled": "Immich-Integration deaktiviert!",
|
||||
"immich_enabled": "Immich-Integration aktiviert!",
|
||||
"immich_error": "Fehler beim aktualisieren der Immich-Integration",
|
||||
"immich_updated": "Immich-Einstellungen erfolgreich aktualisiert!",
|
||||
"integration_enabled": "Integration aktiviert",
|
||||
"integration_fetch_error": "Fehler beim Abrufen der Daten aus der Immich-Integration",
|
||||
"integration_missing": "Im Backend fehlt die Immich-Integration",
|
||||
"load_more": "Mehr laden",
|
||||
"no_items_found": "Keine Artikel gefunden",
|
||||
"query_required": "Abfrage ist erforderlich",
|
||||
"server_down": "Der Immich-Server ist derzeit ausgefallen oder nicht erreichbar",
|
||||
"query_required": "Bitte geben Sie eine Suchanfrage ein",
|
||||
"server_down": "Der Immich-Server ist derzeit nicht erreichbar",
|
||||
"server_url": "Immich-Server-URL",
|
||||
"update_integration": "Update-Integration",
|
||||
"update_integration": "Integration updaten",
|
||||
"immich_integration": "Immich-Integration",
|
||||
"documentation": "Immich-Integrationsdokumentation",
|
||||
"documentation": "Dokumentation zur Immich-Integration",
|
||||
"localhost_note": "Hinweis: localhost wird höchstwahrscheinlich nicht funktionieren, es sei denn, Sie haben Docker-Netzwerke entsprechend eingerichtet. \nEs wird empfohlen, die IP-Adresse des Servers oder den Domänennamen zu verwenden."
|
||||
},
|
||||
"recomendations": {
|
||||
|
@ -591,29 +599,29 @@
|
|||
},
|
||||
"lodging": {
|
||||
"apartment": "Wohnung",
|
||||
"bnb": "Übernachtung mit Frühstück",
|
||||
"cabin": "Kabine",
|
||||
"bnb": "Bed & Breakfast",
|
||||
"cabin": "Hütte",
|
||||
"campground": "Campingplatz",
|
||||
"check_in": "Einchecken",
|
||||
"check_out": "Kasse",
|
||||
"date_and_time": "Datum",
|
||||
"check_in": "Check-in",
|
||||
"check_out": "Check-out",
|
||||
"date_and_time": "Datum und Uhrzeit",
|
||||
"edit": "Bearbeiten",
|
||||
"edit_lodging": "Unterkunft bearbeiten",
|
||||
"error_editing_lodging": "Fehlerbearbeitung",
|
||||
"hostel": "Herberge",
|
||||
"error_editing_lodging": "Fehler beim Bearbeiten der Unterkunft",
|
||||
"hostel": "Hostel",
|
||||
"hotel": "Hotel",
|
||||
"house": "Haus",
|
||||
"lodging_added": "Unterkunft erfolgreich hinzugefügt!",
|
||||
"lodging_delete_error": "Fehler beim Löschen von Unterkünften",
|
||||
"lodging_deleted": "Unterkunft erfolgreich gelöscht!",
|
||||
"lodging_edit_success": "Unterbringung erfolgreich bearbeitet!",
|
||||
"lodging_delete_error": "Fehler beim Löschen der Unterkunft",
|
||||
"lodging_deleted": "Unterkunft gelöscht!",
|
||||
"lodging_edit_success": "Unterbringung bearbeitet!",
|
||||
"lodging_type": "Unterkunftstyp",
|
||||
"motel": "Motel",
|
||||
"new_lodging": "Neue Unterkunft",
|
||||
"other": "Andere",
|
||||
"other": "Sonstige",
|
||||
"provide_start_date": "Bitte geben Sie einen Startdatum an",
|
||||
"reservation_number": "Reservierungsnummer",
|
||||
"resort": "Resort",
|
||||
"resort": "Ferienanlage",
|
||||
"start": "Start",
|
||||
"type": "Typ",
|
||||
"villa": "Villa",
|
||||
|
|
|
@ -203,7 +203,7 @@
|
|||
"category_fetch_error": "Error fetching categories",
|
||||
"new_adventure": "New Adventure",
|
||||
"basic_information": "Basic Information",
|
||||
"no_adventures_to_recommendations": "No adventures found. Add at leat one adventure to get recommendations.",
|
||||
"no_adventures_to_recommendations": "No adventures found. Add at least one adventure to get recommendations.",
|
||||
"display_name": "Display Name",
|
||||
"adventure_not_found": "There are no adventures to display. Add some using the plus button at the bottom right or try changing filters!",
|
||||
"no_adventures_found": "No adventures found",
|
||||
|
@ -428,7 +428,15 @@
|
|||
"documentation_link": "Documentation Link",
|
||||
"launch_account_connections": "Launch Account Connections",
|
||||
"password_too_short": "Password must be at least 6 characters",
|
||||
"add_email": "Add Email"
|
||||
"add_email": "Add Email",
|
||||
"password_disable": "Disable Password Authentication",
|
||||
"password_disable_desc": "Disabling password authentication will prevent you from logging in with a password. You will need to use a social or OIDC provider to log in. Should your social provider be unlinked, password authentication will be automatically re-enabled even if this setting is disabled.",
|
||||
"disable_password": "Disable Password",
|
||||
"password_enabled": "Password authentication enabled",
|
||||
"password_disabled": "Password authentication disabled",
|
||||
"password_disable_warning": "Currently, password authentication is disabled. Login via a social or OIDC provider is required.",
|
||||
"password_disabled_error": "Error disabling password authentication. Make sure a social or OIDC provider is linked to your account.",
|
||||
"password_enabled_error": "Error enabling password authentication."
|
||||
},
|
||||
"collection": {
|
||||
"collection_created": "Collection created successfully!",
|
||||
|
|
|
@ -428,7 +428,15 @@
|
|||
"social_auth_desc_2": "Estas configuraciones se administran en el servidor AdventureLog y el administrador debe habilitarlas manualmente.",
|
||||
"social_oidc_auth": "Autenticación social y OIDC",
|
||||
"add_email": "Agregar correo electrónico",
|
||||
"password_too_short": "La contraseña debe tener al menos 6 caracteres."
|
||||
"password_too_short": "La contraseña debe tener al menos 6 caracteres.",
|
||||
"disable_password": "Desactivar contraseña",
|
||||
"password_disable": "Desactivar la autenticación de contraseña",
|
||||
"password_disable_desc": "Desactivar la autenticación de contraseña le impedirá iniciar sesión con una contraseña. \nDeberá utilizar un proveedor social o OIDC para iniciar sesión. Si su proveedor social no está vinculado, la autenticación de contraseña se volverá a habilitar automáticamente incluso si esta configuración está deshabilitada.",
|
||||
"password_disable_warning": "Actualmente, la autenticación de contraseña está deshabilitada. \nIniciar sesión a través de un proveedor social o OIDC se requiere.",
|
||||
"password_disabled": "Autenticación de contraseña deshabilitada",
|
||||
"password_disabled_error": "Error a deshabilitar la autenticación de contraseña. \nAsegúrese de que un proveedor social o OIDC esté vinculado a su cuenta.",
|
||||
"password_enabled": "Autenticación de contraseña habilitada",
|
||||
"password_enabled_error": "Error al habilitar la autenticación de contraseña."
|
||||
},
|
||||
"checklist": {
|
||||
"add_item": "Agregar artículo",
|
||||
|
|
|
@ -428,7 +428,15 @@
|
|||
"social_auth_desc_2": "Ces paramètres sont gérés sur le serveur AdventureLog et doivent être activés manuellement par l'administrateur.",
|
||||
"social_oidc_auth": "Authentification sociale et OIDC",
|
||||
"add_email": "Ajouter un e-mail",
|
||||
"password_too_short": "Le mot de passe doit contenir au moins 6 caractères"
|
||||
"password_too_short": "Le mot de passe doit contenir au moins 6 caractères",
|
||||
"disable_password": "Désactiver le mot de passe",
|
||||
"password_disable": "Désactiver l'authentification du mot de passe",
|
||||
"password_disable_desc": "La désactivation de l'authentification du mot de passe vous empêchera de vous connecter avec un mot de passe. \nVous devrez utiliser un fournisseur social ou OIDC pour vous connecter. Si votre fournisseur social est non lié, l'authentification du mot de passe sera automatiquement réactivé même si ce paramètre est désactivé.",
|
||||
"password_disable_warning": "Actuellement, l'authentification du mot de passe est désactivée. \nLa connexion via un fournisseur social ou OIDC est requise.",
|
||||
"password_disabled": "Authentification du mot de passe désactivé",
|
||||
"password_disabled_error": "Erreur de désactivation de l'authentification du mot de passe. \nAssurez-vous qu'un fournisseur social ou OIDC est lié à votre compte.",
|
||||
"password_enabled": "Authentification du mot de passe activé",
|
||||
"password_enabled_error": "Erreur permettant l'authentification du mot de passe."
|
||||
},
|
||||
"checklist": {
|
||||
"add_item": "Ajouter un article",
|
||||
|
|
|
@ -428,7 +428,15 @@
|
|||
"social_auth_desc_2": "Queste impostazioni sono gestite nel server AdventureLog e devono essere abilitate manualmente dall'amministratore.",
|
||||
"social_oidc_auth": "Autenticazione sociale e OIDC",
|
||||
"add_email": "Aggiungi e-mail",
|
||||
"password_too_short": "La password deve contenere almeno 6 caratteri"
|
||||
"password_too_short": "La password deve contenere almeno 6 caratteri",
|
||||
"disable_password": "Disabilita la password",
|
||||
"password_disable": "Disabilita l'autenticazione della password",
|
||||
"password_disable_desc": "La disabilitazione dell'autenticazione della password ti impedirà di accedere con una password. \nDovrai utilizzare un provider di social o OIDC per accedere. Se il tuo fornitore social non fosse collegato, l'autenticazione password verrà riabilitata automaticamente anche se questa impostazione è disabilitata.",
|
||||
"password_disable_warning": "Attualmente, l'autenticazione della password è disabilitata. \nÈ richiesto l'accesso tramite un fornitore sociale o OIDC.",
|
||||
"password_disabled": "Autenticazione password disabilitata",
|
||||
"password_disabled_error": "Errore di disabilitazione dell'autenticazione della password. \nAssicurati che un fornitore sociale o OIDC sia collegato al tuo account.",
|
||||
"password_enabled": "Autenticazione password abilitata",
|
||||
"password_enabled_error": "Errore che abilita l'autenticazione della password."
|
||||
},
|
||||
"checklist": {
|
||||
"add_item": "Aggiungi articolo",
|
||||
|
|
|
@ -514,7 +514,15 @@
|
|||
"documentation_link": "문서화 링크",
|
||||
"email_set_primary": "기본 이메일 세트로 설정했습니다!",
|
||||
"email_set_primary_error": "기본 이메일 설정 오류",
|
||||
"email_taken": "이 이메일 주소는 이미 사용 중입니다."
|
||||
"email_taken": "이 이메일 주소는 이미 사용 중입니다.",
|
||||
"disable_password": "비밀번호를 비활성화합니다",
|
||||
"password_disable": "비밀번호 인증을 비활성화합니다",
|
||||
"password_disable_desc": "비밀번호 인증을 비활성화하면 비밀번호로 로그인하지 못하게됩니다. \n소셜 또는 OIDC 제공 업체를 사용하여 로그인해야합니다. 소셜 제공 업체가 끊어지지 않으면이 설정이 비활성화 된 경우에도 비밀번호 인증이 자동으로 다시 활성화됩니다.",
|
||||
"password_disable_warning": "현재 비밀번호 인증이 비활성화되어 있습니다. \n소셜 또는 OIDC 제공 업체를 통해 로그인해야합니다.",
|
||||
"password_disabled": "비밀번호 인증 비활성화",
|
||||
"password_disabled_error": "비밀번호 인증 오류. \n소셜 또는 OIDC 제공 업체가 귀하의 계정에 연결되어 있는지 확인하십시오.",
|
||||
"password_enabled": "비밀번호 인증 활성화",
|
||||
"password_enabled_error": "비밀번호 인증을 활성화하는 오류."
|
||||
},
|
||||
"share": {
|
||||
"go_to_settings": "설정으로 이동",
|
||||
|
|
|
@ -428,7 +428,15 @@
|
|||
"social_auth_desc_2": "Deze instellingen worden beheerd op de AdventureLog-server en moeten handmatig worden ingeschakeld door de beheerder.",
|
||||
"social_oidc_auth": "Sociale en OIDC-authenticatie",
|
||||
"add_email": "E-mail toevoegen",
|
||||
"password_too_short": "Wachtwoord moet minimaal 6 tekens lang zijn"
|
||||
"password_too_short": "Wachtwoord moet minimaal 6 tekens lang zijn",
|
||||
"disable_password": "Schakel het wachtwoord uit",
|
||||
"password_disable": "Schakel wachtwoordverificatie uit",
|
||||
"password_disable_desc": "Het uitschakelen van wachtwoordverificatie zal voorkomen dat u zich aanmeldt met een wachtwoord. \nU moet een sociale of OIDC-provider gebruiken om in te loggen. Als uw sociale provider niet wordt gekoppeld, wordt wachtwoordverificatie automatisch opnieuw ingeschakeld, zelfs als deze instelling is uitgeschakeld.",
|
||||
"password_disable_warning": "Momenteel is wachtwoordverificatie uitgeschakeld. \nLogin via een sociale of OIDC -provider is vereist.",
|
||||
"password_disabled": "Wachtwoordverificatie uitgeschakeld",
|
||||
"password_disabled_error": "Fout het uitschakelen van wachtwoordverificatie. \nZorg ervoor dat een sociale of OIDC -provider is gekoppeld aan uw account.",
|
||||
"password_enabled": "Wachtwoordverificatie ingeschakeld",
|
||||
"password_enabled_error": "Fout bij het inschakelen van wachtwoordverificatie."
|
||||
},
|
||||
"checklist": {
|
||||
"add_item": "Artikel toevoegen",
|
||||
|
|
|
@ -428,7 +428,15 @@
|
|||
"social_auth_desc_2": "Ustawienia te są zarządzane na serwerze AdventureLog i muszą zostać włączone ręcznie przez administratora.",
|
||||
"social_oidc_auth": "Uwierzytelnianie społecznościowe i OIDC",
|
||||
"add_email": "Dodaj e-mail",
|
||||
"password_too_short": "Hasło musi mieć co najmniej 6 znaków"
|
||||
"password_too_short": "Hasło musi mieć co najmniej 6 znaków",
|
||||
"disable_password": "Wyłącz hasło",
|
||||
"password_disable": "Wyłącz uwierzytelnianie hasła",
|
||||
"password_disable_desc": "Wyłączenie uwierzytelniania hasła uniemożliwia logowanie hasłem. \nAby się zalogować, będziesz musiał użyć dostawcy społeczności lub OIDC. Jeśli dostawca społecznościowy zostanie niezbędny, uwierzytelnianie hasła zostanie automatycznie ponowne odnowione, nawet jeśli to ustawienie zostanie wyłączone.",
|
||||
"password_disable_warning": "Obecnie uwierzytelnianie hasła jest wyłączone. \nWymagane jest zalogowanie się za pośrednictwem dostawcy społeczności lub OIDC.",
|
||||
"password_disabled": "Uwierzytelnianie hasła wyłączone",
|
||||
"password_disabled_error": "Błąd wyłączający uwierzytelnianie hasła. \nUpewnij się, że dostawca społecznościowy lub OIDC jest powiązany z Twoim kontem.",
|
||||
"password_enabled": "Włączone uwierzytelnianie hasła",
|
||||
"password_enabled_error": "Błąd umożliwiający uwierzytelnianie hasła."
|
||||
},
|
||||
"collection": {
|
||||
"collection_created": "Kolekcja została pomyślnie utworzona!",
|
||||
|
|
|
@ -428,7 +428,15 @@
|
|||
"social_auth_desc_2": "Dessa inställningar hanteras i AdventureLog-servern och måste aktiveras manuellt av administratören.",
|
||||
"social_oidc_auth": "Social och OIDC-autentisering",
|
||||
"add_email": "Lägg till e-post",
|
||||
"password_too_short": "Lösenordet måste bestå av minst 6 tecken"
|
||||
"password_too_short": "Lösenordet måste bestå av minst 6 tecken",
|
||||
"disable_password": "Inaktivera lösenord",
|
||||
"password_disable": "Inaktivera lösenordsautentisering",
|
||||
"password_disable_desc": "Inaktivering av lösenordsautentisering förhindrar dig att logga in med ett lösenord. \nDu måste använda en social eller OIDC-leverantör för att logga in. Om din sociala leverantör lossnar kommer lösenordsautentisering automatiskt att aktiveras även om den här inställningen är inaktiverad.",
|
||||
"password_disable_warning": "För närvarande är lösenordsautentisering inaktiverad. \nLogga in via en social eller OIDC -leverantör krävs.",
|
||||
"password_disabled": "Lösenordsautentisering inaktiverad",
|
||||
"password_disabled_error": "Fel Inaktivera lösenordsautentisering. \nSe till att en social eller OIDC -leverantör är länkad till ditt konto.",
|
||||
"password_enabled": "Lösenordsautentisering aktiverad",
|
||||
"password_enabled_error": "Fel som aktiverar lösenordsautentisering."
|
||||
},
|
||||
"checklist": {
|
||||
"add_item": "Lägg till objekt",
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
{
|
||||
"navbar": {
|
||||
"about": "关于冒险日志",
|
||||
"adventures": "冒险",
|
||||
"collections": "合集",
|
||||
"worldtravel": "环游世界",
|
||||
"map": "地图",
|
||||
"users": "用户",
|
||||
"search": "搜索",
|
||||
"profile": "个人资料",
|
||||
"collections": "收藏",
|
||||
"discord": "不和谐",
|
||||
"documentation": "文档",
|
||||
"greeting": "你好",
|
||||
"logout": "退出",
|
||||
"map": "地图",
|
||||
"my_adventures": "我的冒险",
|
||||
"profile": "轮廓",
|
||||
"search": "搜索",
|
||||
"settings": "设置",
|
||||
"shared_with_me": "与我分享",
|
||||
"theme_selection": "主题选择",
|
||||
"themes": {
|
||||
"aqua": "阿夸",
|
||||
"dark": "黑暗的",
|
||||
"forest": "森林",
|
||||
"light": "光",
|
||||
"night": "夜晚",
|
||||
"aestheticDark": "审美黑暗",
|
||||
"aestheticLight": "美学之光",
|
||||
"northernLights": "北极光"
|
||||
},
|
||||
"users": "用户",
|
||||
"worldtravel": "环球旅行",
|
||||
"my_tags": "我的标签",
|
||||
"tag": "标签",
|
||||
"shared_with_me": "与我共享",
|
||||
"settings": "设置",
|
||||
"logout": "登出",
|
||||
"about": "关于AdventureLog",
|
||||
"documentation": "文档",
|
||||
"discord": "Discord",
|
||||
"language_selection": "语言",
|
||||
"support": "支持",
|
||||
"calendar": "日历",
|
||||
"theme_selection": "主题选择",
|
||||
"admin_panel": "管理面板",
|
||||
"themes": {
|
||||
"light": "明亮",
|
||||
"dark": "黑暗",
|
||||
"night": "夜晚",
|
||||
"forest": "森林",
|
||||
"aestheticLight": "美学明亮",
|
||||
"aestheticDark": "美学黑暗",
|
||||
"aqua": "水蓝",
|
||||
"northernLights": "北极光"
|
||||
}
|
||||
"admin_panel": "管理面板"
|
||||
},
|
||||
"about": {
|
||||
"about": "关于",
|
||||
|
@ -45,18 +45,18 @@
|
|||
"close": "关闭"
|
||||
},
|
||||
"home": {
|
||||
"hero_1": "发现世界上最刺激的冒险",
|
||||
"hero_2": "使用 AdventureLog 发现并计划您的下一个冒险。\n探索令人叹为观止的目的地,创建自定义行程,并随时随地保持联系。",
|
||||
"go_to": "前往AdventureLog",
|
||||
"key_features": "主要功能",
|
||||
"desc_1": "轻松发现、规划和探索",
|
||||
"desc_2": "AdventureLog 旨在简化您的旅程,为您提供计划、打包和导航下一个难忘冒险的工具和资源。",
|
||||
"desc_2": "AdventureLog 旨在简化您的旅程,为您提供工具和资源来计划、打包和导航您的下一次难忘的冒险。",
|
||||
"feature_1": "旅行日志",
|
||||
"feature_1_desc": "通过个性化的旅行日志记录你的冒险,并与朋友和家人分享你的经历。",
|
||||
"feature_2": "行程规划",
|
||||
"feature_2_desc": "轻松创建自定义行程,并获取每日行程明细。",
|
||||
"feature_3": "旅行地图",
|
||||
"feature_3_desc": "通过交互式地图查看你在世界各地的旅行,并探索新的目的地。"
|
||||
"feature_1_desc": "通过个性化的旅行日志记录您的冒险经历,并与朋友和家人分享您的经历。",
|
||||
"feature_2": "旅行计划",
|
||||
"feature_2_desc": "轻松创建自定义行程并获取行程的每日详细信息。",
|
||||
"feature_3": "旅游地图",
|
||||
"feature_3_desc": "使用交互式地图查看您在世界各地的旅行并探索新的目的地。",
|
||||
"go_to": "前往冒险日志",
|
||||
"hero_1": "探索世界上最惊险的冒险",
|
||||
"hero_2": "使用 AdventureLog 发现并计划您的下一次冒险。\n探索令人惊叹的目的地、创建定制行程并随时随地保持联系。",
|
||||
"key_features": "主要特点"
|
||||
},
|
||||
"adventures": {
|
||||
"collection_remove_success": "成功从合集中移除冒险!",
|
||||
|
@ -266,7 +266,7 @@
|
|||
"attachment_update_success": "附件更新成功!",
|
||||
"attachment_name": "附件名称",
|
||||
"gpx_tip": "上传 GPX 文件到附件以便在地图上查看它们!",
|
||||
"welcome_map_info": "此服务器上的公开冒险",
|
||||
"welcome_map_info": "该服务器上的公共冒险",
|
||||
"attachment_update_error": "更新附件时出错",
|
||||
"activities": {
|
||||
"general": "通用 🌍",
|
||||
|
@ -294,108 +294,9 @@
|
|||
},
|
||||
"lodging_information": "住宿信息",
|
||||
"price": "价格",
|
||||
"region": "地区",
|
||||
"reservation_number": "预订号",
|
||||
"welcome_map_info": "该服务器上的公共冒险",
|
||||
"open_in_maps": "在地图上打开"
|
||||
},
|
||||
"home": {
|
||||
"desc_1": "轻松发现、规划和探索",
|
||||
"desc_2": "AdventureLog 旨在简化您的旅程,为您提供工具和资源来计划、打包和导航您的下一次难忘的冒险。",
|
||||
"feature_1": "旅行日志",
|
||||
"feature_1_desc": "通过个性化的旅行日志记录您的冒险经历,并与朋友和家人分享您的经历。",
|
||||
"feature_2": "旅行计划",
|
||||
"feature_2_desc": "轻松创建自定义行程并获取行程的每日详细信息。",
|
||||
"feature_3": "旅游地图",
|
||||
"feature_3_desc": "使用交互式地图查看您在世界各地的旅行并探索新的目的地。",
|
||||
"go_to": "前往冒险日志",
|
||||
"hero_1": "探索世界上最惊险的冒险",
|
||||
"hero_2": "使用 AdventureLog 发现并计划您的下一次冒险。\n探索令人惊叹的目的地、创建定制行程并随时随地保持联系。",
|
||||
"key_features": "主要特点"
|
||||
},
|
||||
"navbar": {
|
||||
"about": "关于冒险日志",
|
||||
"adventures": "冒险",
|
||||
"collections": "收藏",
|
||||
"discord": "不和谐",
|
||||
"documentation": "文档",
|
||||
"greeting": "你好",
|
||||
"logout": "退出",
|
||||
"map": "地图",
|
||||
"my_adventures": "我的冒险",
|
||||
"profile": "轮廓",
|
||||
"search": "搜索",
|
||||
"settings": "设置",
|
||||
"shared_with_me": "与我分享",
|
||||
"theme_selection": "主题选择",
|
||||
"themes": {
|
||||
"aqua": "阿夸",
|
||||
"dark": "黑暗的",
|
||||
"forest": "森林",
|
||||
"light": "光",
|
||||
"night": "夜晚",
|
||||
"aestheticDark": "审美黑暗",
|
||||
"aestheticLight": "美学之光",
|
||||
"northernLights": "北极光"
|
||||
},
|
||||
"users": "用户",
|
||||
"worldtravel": "环球旅行",
|
||||
"my_tags": "我的标签",
|
||||
"tag": "标签",
|
||||
"language_selection": "语言",
|
||||
"support": "支持",
|
||||
"calendar": "日历",
|
||||
"admin_panel": "管理面板"
|
||||
},
|
||||
"auth": {
|
||||
"forgot_password": "忘记密码?",
|
||||
"login": "登录",
|
||||
"login_error": "无法使用提供的凭据登录。",
|
||||
"password": "密码",
|
||||
"signup": "报名",
|
||||
"username": "用户名",
|
||||
"confirm_password": "确认密码",
|
||||
"email": "电子邮件",
|
||||
"first_name": "名",
|
||||
"last_name": "姓",
|
||||
"registration_disabled": "目前已禁用注册。",
|
||||
"profile_picture": "个人资料图片",
|
||||
"public_profile": "公开资料",
|
||||
"public_tooltip": "通过公开个人资料,用户可以与您共享收藏并在用户页面上查看您的个人资料。",
|
||||
"email_required": "电子邮件为必填项",
|
||||
"both_passwords_required": "两个密码都需要",
|
||||
"new_password": "新密码",
|
||||
"reset_failed": "重置密码失败",
|
||||
"or_3rd_party": "或者使用第三方服务登录",
|
||||
"no_public_adventures": "找不到公共冒险",
|
||||
"no_public_collections": "找不到公共收藏",
|
||||
"user_adventures": "用户冒险",
|
||||
"user_collections": "用户收集"
|
||||
},
|
||||
"worldtravel": {
|
||||
"all": "全部",
|
||||
"all_subregions": "所有次区域",
|
||||
"clear_search": "清除搜索",
|
||||
"completely_visited": "已完全访问",
|
||||
"country_list": "国家列表",
|
||||
"no_countries_found": "没有找到国家",
|
||||
"not_visited": "未访问过",
|
||||
"num_countries": "找到的国家",
|
||||
"partially_visited": "部分访问",
|
||||
"all_visited": "您已访问过所有地区",
|
||||
"cities": "城市",
|
||||
"failed_to_mark_visit": "无法标记访问",
|
||||
"failed_to_remove_visit": "无法删除对的访问",
|
||||
"marked_visited": "标记为已访问",
|
||||
"no_cities_found": "没有找到城市",
|
||||
"region_failed_visited": "无法将区域标记为已访问",
|
||||
"region_stats": "地区统计",
|
||||
"regions_in": "地区位于",
|
||||
"removed": "已删除",
|
||||
"view_cities": "查看城市",
|
||||
"visit_remove_failed": "删除访问失败",
|
||||
"visit_to": "参观"
|
||||
},
|
||||
"auth": {
|
||||
"forgot_password": "忘记密码?",
|
||||
"login": "登录",
|
||||
|
@ -421,6 +322,30 @@
|
|||
"user_adventures": "用户冒险",
|
||||
"user_collections": "用户合集"
|
||||
},
|
||||
"worldtravel": {
|
||||
"all": "全部",
|
||||
"all_subregions": "所有次区域",
|
||||
"clear_search": "清除搜索",
|
||||
"completely_visited": "已完全访问",
|
||||
"country_list": "国家列表",
|
||||
"no_countries_found": "没有找到国家",
|
||||
"not_visited": "未访问过",
|
||||
"num_countries": "找到的国家",
|
||||
"partially_visited": "部分访问",
|
||||
"all_visited": "您已访问过所有地区",
|
||||
"cities": "城市",
|
||||
"failed_to_mark_visit": "无法标记访问",
|
||||
"failed_to_remove_visit": "无法删除对的访问",
|
||||
"marked_visited": "标记为已访问",
|
||||
"no_cities_found": "没有找到城市",
|
||||
"region_failed_visited": "无法将区域标记为已访问",
|
||||
"region_stats": "地区统计",
|
||||
"regions_in": "地区位于",
|
||||
"removed": "已删除",
|
||||
"view_cities": "查看城市",
|
||||
"visit_remove_failed": "删除访问失败",
|
||||
"visit_to": "参观"
|
||||
},
|
||||
"users": {
|
||||
"no_users_found": "未找到已公开个人资料的用户。"
|
||||
},
|
||||
|
@ -503,7 +428,15 @@
|
|||
"social_auth_desc_2": "这些设置在 AdventureLog 服务器中进行管理,并且必须由管理员手动启用。",
|
||||
"social_oidc_auth": "社交与 OIDC 认证",
|
||||
"add_email": "添加邮箱",
|
||||
"password_too_short": "密码必须至少为 6 个字符"
|
||||
"password_too_short": "密码必须至少为 6 个字符",
|
||||
"disable_password": "禁用密码",
|
||||
"password_disable": "禁用密码身份验证",
|
||||
"password_disable_desc": "禁用密码身份验证将阻止您使用密码登录。\n您将需要使用社交或OIDC提供商登录。如果您的社交提供商未链接,即使禁用了此设置,密码身份验证也将自动重新启用。",
|
||||
"password_disable_warning": "当前,密码身份验证已禁用。\n需要通过社交或OIDC提供商登录。",
|
||||
"password_disabled": "密码身份验证禁用",
|
||||
"password_disabled_error": "错误禁用密码身份验证。\n确保将社交或OIDC提供商链接到您的帐户。",
|
||||
"password_enabled": "启用密码身份验证",
|
||||
"password_enabled_error": "启用密码身份验证的错误。"
|
||||
},
|
||||
"checklist": {
|
||||
"add_item": "添加项目",
|
||||
|
@ -694,4 +627,4 @@
|
|||
"resort": "度假村",
|
||||
"current_timezone": "当前时区"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { DefaultMarker, MapLibre, Popup, GeoJSON, LineLayer } from 'svelte-maplibre';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { marked } from 'marked'; // Import the markdown parser
|
||||
|
||||
import DOMPurify from 'dompurify';
|
||||
// @ts-ignore
|
||||
import toGeoJSON from '@mapbox/togeojson';
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
let geojson: any;
|
||||
|
||||
const renderMarkdown = (markdown: string) => {
|
||||
return marked(markdown);
|
||||
return marked(markdown) as string;
|
||||
};
|
||||
|
||||
async function getGpxFiles() {
|
||||
|
@ -369,7 +369,7 @@
|
|||
<article
|
||||
class="prose overflow-auto h-full max-w-full p-4 border border-base-300 rounded-lg"
|
||||
>
|
||||
{@html renderMarkdown(adventure.description)}
|
||||
{@html DOMPurify.sanitize(renderMarkdown(adventure.description))}
|
||||
</article>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@ import { json } from '@sveltejs/kit';
|
|||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function GET(event) {
|
||||
const { url, params, request, fetch, cookies } = event;
|
||||
const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
|
||||
const searchParam = url.search ? `${url.search}` : '';
|
||||
return handleRequest(url, params, request, fetch, cookies, searchParam);
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,13 @@ export async function POST({ url, params, request, fetch, cookies }) {
|
|||
}
|
||||
|
||||
export async function PATCH({ url, params, request, fetch, cookies }) {
|
||||
const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
|
||||
return handleRequest(url, params, request, fetch, cookies, searchParam, true);
|
||||
const searchParam = url.search ? `${url.search}` : '';
|
||||
return handleRequest(url, params, request, fetch, cookies, searchParam, false);
|
||||
}
|
||||
|
||||
export async function PUT({ url, params, request, fetch, cookies }) {
|
||||
const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
|
||||
return handleRequest(url, params, request, fetch, cookies, searchParam, true);
|
||||
const searchParam = url.search ? `${url.search}` : '';
|
||||
return handleRequest(url, params, request, fetch, cookies, searchParam, false);
|
||||
}
|
||||
|
||||
export async function DELETE({ url, params, request, fetch, cookies }) {
|
||||
|
@ -43,13 +43,15 @@ async function handleRequest(
|
|||
const path = params.path;
|
||||
let targetUrl = `${endpoint}/auth/${path}`;
|
||||
|
||||
const add_trailing_slash_list = ['disable-password'];
|
||||
|
||||
// Ensure the path ends with a trailing slash
|
||||
if (requreTrailingSlash && !targetUrl.endsWith('/')) {
|
||||
if ((requreTrailingSlash && !targetUrl.endsWith('/')) || add_trailing_slash_list.includes(path)) {
|
||||
targetUrl += '/';
|
||||
}
|
||||
|
||||
// Append query parameters to the path correctly
|
||||
targetUrl += searchParam; // This will add ?format=json or &format=json to the URL
|
||||
targetUrl += searchParam; // This will add or to the URL
|
||||
|
||||
const headers = new Headers(request.headers);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
import AdventureCard from '$lib/components/AdventureCard.svelte';
|
||||
import AdventureLink from '$lib/components/AdventureLink.svelte';
|
||||
import NotFound from '$lib/components/NotFound.svelte';
|
||||
import { DefaultMarker, MapLibre, Marker, Popup } from 'svelte-maplibre';
|
||||
import { DefaultMarker, MapLibre, Marker, Popup, LineLayer, GeoJSON } from 'svelte-maplibre';
|
||||
import TransportationCard from '$lib/components/TransportationCard.svelte';
|
||||
import NoteCard from '$lib/components/NoteCard.svelte';
|
||||
import NoteModal from '$lib/components/NoteModal.svelte';
|
||||
|
@ -28,7 +28,8 @@
|
|||
groupTransportationsByDate,
|
||||
groupChecklistsByDate,
|
||||
osmTagToEmoji,
|
||||
groupLodgingByDate
|
||||
groupLodgingByDate,
|
||||
LODGING_TYPES_ICONS
|
||||
} from '$lib';
|
||||
import ChecklistCard from '$lib/components/ChecklistCard.svelte';
|
||||
import ChecklistModal from '$lib/components/ChecklistModal.svelte';
|
||||
|
@ -46,6 +47,14 @@
|
|||
return marked(markdown);
|
||||
};
|
||||
|
||||
function getLodgingIcon(type: string) {
|
||||
if (type in LODGING_TYPES_ICONS) {
|
||||
return LODGING_TYPES_ICONS[type as keyof typeof LODGING_TYPES_ICONS];
|
||||
} else {
|
||||
return '🏨';
|
||||
}
|
||||
}
|
||||
|
||||
let collection: Collection;
|
||||
|
||||
// add christmas and new years
|
||||
|
@ -604,10 +613,6 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
{#if collection && !collection.start_date && adventures.length == 0 && transportations.length == 0 && notes.length == 0 && checklists.length == 0 && lodging.length == 0}
|
||||
<NotFound error={undefined} />
|
||||
{/if}
|
||||
|
||||
{#if collection.description}
|
||||
<div class="flex justify-center mt-4 max-w-screen-lg mx-auto">
|
||||
<article
|
||||
|
@ -990,14 +995,15 @@
|
|||
{/if}
|
||||
{/each}
|
||||
{#each transportations as transportation}
|
||||
{#if transportation.destination_latitude && transportation.destination_longitude}
|
||||
{#if transportation.origin_latitude && transportation.origin_longitude && transportation.destination_latitude && transportation.destination_longitude}
|
||||
<!-- Origin Marker -->
|
||||
<Marker
|
||||
lngLat={{
|
||||
lng: transportation.destination_longitude,
|
||||
lat: transportation.destination_latitude
|
||||
lng: transportation.origin_longitude,
|
||||
lat: transportation.origin_latitude
|
||||
}}
|
||||
class="grid h-8 w-8 place-items-center rounded-full border border-gray-200
|
||||
bg-red-300 text-black focus:outline-6 focus:outline-black"
|
||||
bg-green-300 text-black focus:outline-6 focus:outline-black"
|
||||
>
|
||||
<span class="text-xl">
|
||||
{getTransportationEmoji(transportation.type)}
|
||||
|
@ -1009,15 +1015,15 @@
|
|||
</p>
|
||||
</Popup>
|
||||
</Marker>
|
||||
{/if}
|
||||
{#if transportation.origin_latitude && transportation.origin_longitude}
|
||||
|
||||
<!-- Destination Marker -->
|
||||
<Marker
|
||||
lngLat={{
|
||||
lng: transportation.origin_longitude,
|
||||
lat: transportation.origin_latitude
|
||||
lng: transportation.destination_longitude,
|
||||
lat: transportation.destination_latitude
|
||||
}}
|
||||
class="grid h-8 w-8 place-items-center rounded-full border border-gray-200
|
||||
bg-green-300 text-black focus:outline-6 focus:outline-black"
|
||||
bg-red-300 text-black focus:outline-6 focus:outline-black"
|
||||
>
|
||||
<span class="text-xl">
|
||||
{getTransportationEmoji(transportation.type)}
|
||||
|
@ -1029,6 +1035,57 @@
|
|||
</p>
|
||||
</Popup>
|
||||
</Marker>
|
||||
|
||||
<!-- Line connecting origin and destination -->
|
||||
<GeoJSON
|
||||
data={{
|
||||
type: 'Feature',
|
||||
properties: {
|
||||
name: transportation.name,
|
||||
type: transportation.type
|
||||
},
|
||||
geometry: {
|
||||
type: 'LineString',
|
||||
coordinates: [
|
||||
[transportation.origin_longitude, transportation.origin_latitude],
|
||||
[transportation.destination_longitude, transportation.destination_latitude]
|
||||
]
|
||||
}
|
||||
}}
|
||||
>
|
||||
<LineLayer
|
||||
layout={{ 'line-cap': 'round', 'line-join': 'round' }}
|
||||
paint={{
|
||||
'line-width': 3,
|
||||
'line-color': '#898989', // customize your line color here
|
||||
'line-opacity': 0.8
|
||||
// 'line-dasharray': [5, 2]
|
||||
}}
|
||||
/>
|
||||
</GeoJSON>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
{#each lodging as hotel}
|
||||
{#if hotel.longitude && hotel.latitude}
|
||||
<Marker
|
||||
lngLat={{
|
||||
lng: hotel.longitude,
|
||||
lat: hotel.latitude
|
||||
}}
|
||||
class="grid h-8 w-8 place-items-center rounded-full border border-gray-200
|
||||
bg-yellow-300 text-black focus:outline-6 focus:outline-black"
|
||||
>
|
||||
<span class="text-xl">
|
||||
{getLodgingIcon(hotel.type)}
|
||||
</span>
|
||||
<Popup openOn="click" offset={[0, -10]}>
|
||||
<div class="text-lg text-black font-bold">{hotel.name}</div>
|
||||
<p class="font-semibold text-black text-md">
|
||||
{hotel.type}
|
||||
</p>
|
||||
</Popup>
|
||||
</Marker>
|
||||
{/if}
|
||||
{/each}
|
||||
</MapLibre>
|
||||
|
@ -1080,7 +1137,7 @@
|
|||
</div>
|
||||
<div class="join flex items-center justify-center mt-4">
|
||||
<input
|
||||
class="join-item btn"
|
||||
class="join-item btn btn-neutral"
|
||||
type="radio"
|
||||
name="options"
|
||||
aria-label="Tourism"
|
||||
|
@ -1088,7 +1145,7 @@
|
|||
on:click={() => (recomendationType = 'tourism')}
|
||||
/>
|
||||
<input
|
||||
class="join-item btn"
|
||||
class="join-item btn btn-neutral"
|
||||
type="radio"
|
||||
name="options"
|
||||
aria-label="Food"
|
||||
|
@ -1096,7 +1153,7 @@
|
|||
on:click={() => (recomendationType = 'food')}
|
||||
/>
|
||||
<input
|
||||
class="join-item btn"
|
||||
class="join-item btn btn-neutral"
|
||||
type="radio"
|
||||
name="options"
|
||||
aria-label="Lodging"
|
||||
|
|
|
@ -63,6 +63,13 @@ export const load: PageServerLoad = async (event) => {
|
|||
immichIntegration = await immichIntegrationsFetch.json();
|
||||
}
|
||||
|
||||
let socialProvidersFetch = await fetch(`${endpoint}/auth/social-providers`, {
|
||||
headers: {
|
||||
Cookie: `sessionid=${sessionId}`
|
||||
}
|
||||
});
|
||||
let socialProviders = await socialProvidersFetch.json();
|
||||
|
||||
let publicUrlFetch = await fetch(`${endpoint}/public-url/`);
|
||||
let publicUrl = '';
|
||||
if (!publicUrlFetch.ok) {
|
||||
|
@ -78,7 +85,8 @@ export const load: PageServerLoad = async (event) => {
|
|||
emails,
|
||||
authenticators,
|
||||
immichIntegration,
|
||||
publicUrl
|
||||
publicUrl,
|
||||
socialProviders
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
import TotpModal from '$lib/components/TOTPModal.svelte';
|
||||
import { appTitle, appVersion } from '$lib/config.js';
|
||||
import ImmichLogo from '$lib/assets/immich.svg';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export let data;
|
||||
console.log(data);
|
||||
|
@ -20,6 +19,8 @@
|
|||
emails = data.props.emails;
|
||||
}
|
||||
|
||||
let new_password_disable_setting: boolean = false;
|
||||
|
||||
let new_email: string = '';
|
||||
let public_url: string = data.props.publicUrl;
|
||||
let immichIntegration = data.props.immichIntegration;
|
||||
|
@ -87,8 +88,38 @@
|
|||
}
|
||||
}
|
||||
|
||||
async function disablePassword() {
|
||||
if (user.disable_password) {
|
||||
let res = await fetch('/auth/disable-password/', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
if (res.ok) {
|
||||
addToast('success', $t('settings.password_disabled'));
|
||||
} else {
|
||||
addToast('error', $t('settings.password_disabled_error'));
|
||||
user.disable_password = false;
|
||||
}
|
||||
} else {
|
||||
let res = await fetch('/auth/disable-password/', {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
if (res.ok) {
|
||||
addToast('success', $t('settings.password_enabled'));
|
||||
} else {
|
||||
addToast('error', $t('settings.password_enabled_error'));
|
||||
user.disable_password = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function verifyEmail(email: { email: any; verified?: boolean; primary?: boolean }) {
|
||||
let res = await fetch('/auth/browser/v1/account/email/', {
|
||||
let res = await fetch('/auth/browser/v1/account/email', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -103,7 +134,7 @@
|
|||
}
|
||||
|
||||
async function addEmail() {
|
||||
let res = await fetch('/auth/browser/v1/account/email/', {
|
||||
let res = await fetch('/auth/browser/v1/account/email', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -122,7 +153,7 @@
|
|||
}
|
||||
|
||||
async function primaryEmail(email: { email: any; verified?: boolean; primary?: boolean }) {
|
||||
let res = await fetch('/auth/browser/v1/account/email/', {
|
||||
let res = await fetch('/auth/browser/v1/account/email', {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -490,6 +521,41 @@
|
|||
href={`${public_url}/accounts/social/connections/`}
|
||||
target="_blank">{$t('settings.launch_account_connections')}</a
|
||||
>
|
||||
|
||||
{#if data.props.socialProviders && data.props.socialProviders.length > 0}
|
||||
<div class="mt-8">
|
||||
<h2 class="text-2xl font-semibold text-center">{$t('settings.password_disable')}</h2>
|
||||
<p>{$t('settings.password_disable_desc')}</p>
|
||||
|
||||
<div class="flex flex-col items-center mt-4">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="disable_password"
|
||||
name="disable_password"
|
||||
bind:checked={user.disable_password}
|
||||
class="toggle toggle-primary"
|
||||
on:change={disablePassword}
|
||||
/>
|
||||
<label for="disable_password" class="ml-2 text-sm text-neutral-content"
|
||||
>{$t('settings.disable_password')}</label
|
||||
>
|
||||
<!-- <button class="btn btn-primary mt-4" on:click={disablePassword}
|
||||
>{$t('settings.update')}</button
|
||||
> -->
|
||||
{#if user.disable_password}
|
||||
<div class="badge badge-error mt-2">{$t('settings.password_disabled')}</div>
|
||||
{/if}
|
||||
{#if !user.disable_password}
|
||||
<div class="badge badge-success mt-2">{$t('settings.password_enabled')}</div>
|
||||
{/if}
|
||||
{#if user.disable_password}
|
||||
<div class="alert alert-warning mt-4">
|
||||
{$t('settings.password_disable_warning')}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
|
@ -10,6 +10,21 @@
|
|||
let regions: Region[] = data.props?.regions || [];
|
||||
let visitedRegions: VisitedRegion[] = data.props?.visitedRegions || [];
|
||||
|
||||
let filteredRegions: Region[] = [];
|
||||
|
||||
let searchQuery: string = '';
|
||||
|
||||
$: {
|
||||
if (searchQuery === '') {
|
||||
filteredRegions = regions;
|
||||
} else {
|
||||
// always filter from the original regions list
|
||||
filteredRegions = regions.filter((region) =>
|
||||
region.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const country = data.props?.country || null;
|
||||
console.log(data);
|
||||
|
||||
|
@ -88,8 +103,25 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-center mb-4">
|
||||
<input
|
||||
type="text"
|
||||
placeholder={$t('navbar.search')}
|
||||
class="input input-bordered w-full max-w-xs"
|
||||
bind:value={searchQuery}
|
||||
/>
|
||||
{#if searchQuery.length > 0}
|
||||
<!-- clear button -->
|
||||
<div class="flex items-center justify-center ml-4">
|
||||
<button class="btn btn-neutral" on:click={() => (searchQuery = '')}>
|
||||
{$t('worldtravel.clear_search')}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-4 mr-4 ml-4 justify-center content-center">
|
||||
{#each regions as region}
|
||||
{#each filteredRegions as region}
|
||||
<RegionCard
|
||||
{region}
|
||||
visited={visitedRegions.some((visitedRegion) => visitedRegion.region === region.id)}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
filteredCities = allCities;
|
||||
} else {
|
||||
// otherwise, filter countries by name
|
||||
filteredCities = filteredCities.filter((country) =>
|
||||
filteredCities = allCities.filter((country) =>
|
||||
country.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
@ -97,74 +97,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="flex items-center justify-center mb-4">
|
||||
<div class="join">
|
||||
<input
|
||||
class="join-item btn"
|
||||
type="radio"
|
||||
name="filter"
|
||||
aria-label={$t('worldtravel.all')}
|
||||
checked
|
||||
on:click={() => (filterOption = 'all')}
|
||||
/>
|
||||
<input
|
||||
class="join-item btn"
|
||||
type="radio"
|
||||
name="filter"
|
||||
aria-label={$t('worldtravel.partially_visited')}
|
||||
on:click={() => (filterOption = 'partial')}
|
||||
/>
|
||||
<input
|
||||
class="join-item btn"
|
||||
type="radio"
|
||||
name="filter"
|
||||
aria-label={$t('worldtravel.completely_visited')}
|
||||
on:click={() => (filterOption = 'complete')}
|
||||
/>
|
||||
<input
|
||||
class="join-item btn"
|
||||
type="radio"
|
||||
name="filter"
|
||||
aria-label={$t('worldtravel.not_visited')}
|
||||
on:click={() => (filterOption = 'not')}
|
||||
/>
|
||||
</div>
|
||||
<select class="select select-bordered w-full max-w-xs ml-4" bind:value={subRegionOption}>
|
||||
<option value="">{$t('worldtravel.all_subregions')}</option>
|
||||
{#each worldSubregions as subregion}
|
||||
<option value={subregion}>{subregion}</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<div class="flex items-center justify-center ml-4">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checkbox-bordered"
|
||||
bind:checked={showMap}
|
||||
aria-label={$t('adventures.show_map')}
|
||||
/>
|
||||
<span class="ml-2">{$t('adventures.show_map')}</span>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
{#if allCities.length > 0}
|
||||
<div class="flex items-center justify-center mb-4">
|
||||
<input
|
||||
type="text"
|
||||
placeholder={$t('navbar.search')}
|
||||
class="input input-bordered w-full max-w-xs"
|
||||
bind:value={searchQuery}
|
||||
/>
|
||||
{#if searchQuery.length > 0}
|
||||
<!-- clear button -->
|
||||
<div class="flex items-center justify-center ml-4">
|
||||
<button class="btn btn-neutral" on:click={() => (searchQuery = '')}>
|
||||
{$t('worldtravel.clear_search')}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="mt-4 mb-4 flex justify-center">
|
||||
<!-- checkbox to toggle marker -->
|
||||
|
||||
|
@ -198,6 +131,23 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex items-center justify-center mb-4">
|
||||
<input
|
||||
type="text"
|
||||
placeholder={$t('navbar.search')}
|
||||
class="input input-bordered w-full max-w-xs"
|
||||
bind:value={searchQuery}
|
||||
/>
|
||||
{#if searchQuery.length > 0}
|
||||
<!-- clear button -->
|
||||
<div class="flex items-center justify-center ml-4">
|
||||
<button class="btn btn-neutral" on:click={() => (searchQuery = '')}>
|
||||
{$t('worldtravel.clear_search')}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-4 mr-4 ml-4 justify-center content-center">
|
||||
{#each filteredCities as city}
|
||||
<CityCard
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue