Adds a pull-based legal-update flow instead of fanning out through the petId-scoped Notification model (ToS/Datenschutz acceptance is an Owner-level concern, not a per-pet one): - Prisma: LegalDocType enum, LegalDocumentVersion model, Owner.legalAcknowledgedAt. - trpc/routers/legal.ts: admin publish/listVersions, owner-facing getPendingUpdate/acknowledge. assertAdmin exported from admin.ts instead of duplicated. - Admin panel /legal: publish form (doc type + change summary) + history. Publishing IS sending — every owner sees it on next load until acknowledged; republishing re-surfaces it for everyone. - LegalUpdateBanner mounted in (app)/layout.tsx: non-dismissable sheet with the stored change summary, "Verstanden" (acknowledge) and "Konto löschen" (routes into DeleteAccountDialog via new ?deleteAccount=1 auto-open support) actions. Closes the last DEBUG-List.md item. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
301 lines
10 KiB
JSON
301 lines
10 KiB
JSON
{
|
|
"Nav": {
|
|
"home": "Home",
|
|
"myPets": "My Pets",
|
|
"explore": "Explore",
|
|
"search": "Search",
|
|
"notifications": "Notifications",
|
|
"messages": "Messages",
|
|
"invite": "Invite Friends",
|
|
"newPost": "New Post",
|
|
"addPet": "Add Pet",
|
|
"account": "Account",
|
|
"profile": "Profile"
|
|
},
|
|
"PostType": {
|
|
"title": "Create",
|
|
"photo": "Photo Post",
|
|
"story": "Story",
|
|
"video": "Video Post",
|
|
"milestone": "Milestone",
|
|
"newPost": "New Post",
|
|
"newStory": "New Story",
|
|
"newMilestone": "New Milestone",
|
|
"newVideo": "New Video"
|
|
},
|
|
"Feed": {
|
|
"emptyTitle": "Your feed is empty",
|
|
"emptyBody": "Follow some pets to see their posts here.",
|
|
"findPets": "Find Pets"
|
|
},
|
|
"Welcome": {
|
|
"title": "Welcome to PawFeed!",
|
|
"subtitle": "Here's what your pet can do:",
|
|
"close": "Close",
|
|
"understood": "Got it",
|
|
"ctaHint": "Press + in the nav to create your first post.",
|
|
"photosTitle": "Photos & Videos",
|
|
"photosDesc": "Share moments from your pet's life — single images, carousels, or short videos.",
|
|
"storiesTitle": "Stories",
|
|
"storiesDesc": "24 h stories disappear automatically. See who viewed your story.",
|
|
"milestonesTitle": "Milestones",
|
|
"milestonesDesc": "Celebrate birthdays, adoption anniversaries, first outings and more.",
|
|
"dmsTitle": "DMs",
|
|
"dmsDesc": "Message other pets directly — perfect for playdates or questions.",
|
|
"healthTitle": "Health Tracking",
|
|
"healthDesc": "Track weight, vaccinations and vet visits. Share the Health Card with your vet."
|
|
},
|
|
"Explore": {
|
|
"title": "Explore",
|
|
"trending": "Trending",
|
|
"all": "All",
|
|
"allBreeds": "All breeds",
|
|
"loadMore": "Load more",
|
|
"noPetsYet": "No {species} pets yet",
|
|
"noTrending": "No trending content yet — check back soon",
|
|
"trendingHashtags": "Trending hashtags",
|
|
"hotPosts": "Hot posts · last 48 h"
|
|
},
|
|
"PetForm": {
|
|
"name": "Pet name",
|
|
"namePlaceholder": "Enter pet name",
|
|
"nameRequired": "This field is required.",
|
|
"nameMaxLength": "Pet name must be 30 characters or fewer.",
|
|
"species": "Species",
|
|
"selectSpecies": "Select species",
|
|
"speciesRequired": "Please select a species.",
|
|
"breed": "Breed",
|
|
"selectBreed": "Select breed (optional)",
|
|
"selectSpeciesFirst": "Select a species first",
|
|
"noBreedsFound": "No breeds found.",
|
|
"bio": "Bio",
|
|
"adoptionStory": "Adoption story",
|
|
"birthday": "Birthday",
|
|
"birthdayHint": "For birthday reminders",
|
|
"adoptedAt": "Adoption date",
|
|
"adoptedAtHint": "For anniversary reminders",
|
|
"addPet": "Add Pet",
|
|
"saveChanges": "Save changes",
|
|
"petCreated": "Pet profile created",
|
|
"changesSaved": "Changes saved",
|
|
"error": "Something went wrong. Please try again."
|
|
},
|
|
"DateWheelPicker": {
|
|
"selectDate": "Select date",
|
|
"apply": "Apply"
|
|
},
|
|
"LegalUpdateBanner": {
|
|
"title": "Our Terms of Service or Privacy Policy have changed",
|
|
"readFull": "Read the full text",
|
|
"acknowledge": "Got it",
|
|
"disagree": "Disagree — delete my account"
|
|
},
|
|
"AvatarUpload": {
|
|
"uploadPhoto": "Upload photo",
|
|
"changePhoto": "Change photo",
|
|
"savePetFirst": "Save your pet first to upload a photo.",
|
|
"uploadFailed": "Upload failed — please try again",
|
|
"photoUpdated": "Profile photo updated",
|
|
"fileTooLarge": "Photo must be under 10 MB.",
|
|
"invalidType": "Upload a JPG, PNG, or WebP image.",
|
|
"uploading": "Uploading…"
|
|
},
|
|
"Onboarding": {
|
|
"addFirstPet": "Add your first pet",
|
|
"addFirstPetDesc": "Your pet will be their own star on PawFeed.",
|
|
"addPhoto": "Add a profile photo",
|
|
"addPhotoDesc": "Give your pet a face on PawFeed. You can always change this later.",
|
|
"done": "Done",
|
|
"skipForNow": "Skip for now"
|
|
},
|
|
"Language": {
|
|
"switch": "Language",
|
|
"en": "English",
|
|
"de": "Deutsch"
|
|
},
|
|
"PostCard": {
|
|
"justNow": "just now",
|
|
"minutesAgo": "{count}m ago",
|
|
"hoursAgo": "{count}h ago",
|
|
"daysAgo": "{count}d ago",
|
|
"editCaption": "Edit caption",
|
|
"deletePost": "Delete post",
|
|
"reportPost": "Report post",
|
|
"blockPet": "Block {name}",
|
|
"captionPlaceholder": "Write a caption…",
|
|
"charsRemaining": "{count} characters remaining",
|
|
"saveCaption": "Save caption",
|
|
"cancel": "Cancel",
|
|
"more": "more",
|
|
"less": "less",
|
|
"deleteTitle": "Delete this post?",
|
|
"deleteDesc": "This will permanently delete the post and all its photos. This can't be undone.",
|
|
"keepPost": "Keep post",
|
|
"yesDelete": "Yes, delete",
|
|
"captionUpdated": "Caption updated",
|
|
"captionUpdateError": "Couldn't update caption. Please try again.",
|
|
"postDeleted": "Post deleted",
|
|
"deleteError": "Couldn't delete post. Please try again."
|
|
},
|
|
"Comments": {
|
|
"title": "Comments",
|
|
"justNow": "now",
|
|
"empty": "No comments yet — be the first!",
|
|
"placeholder": "Add a comment…",
|
|
"post": "Post",
|
|
"sending": "Sending…",
|
|
"postError": "Couldn't post comment. Please try again.",
|
|
"deleteError": "Couldn't delete comment. Please try again.",
|
|
"countSingular": "1 comment",
|
|
"countPlural": "{count} comments"
|
|
},
|
|
"RelativeTime": {
|
|
"justNow": "now",
|
|
"minutes": "{count}m",
|
|
"hours": "{count}h",
|
|
"days": "{count}d"
|
|
},
|
|
"Follow": {
|
|
"follow": "Follow",
|
|
"following": "Following",
|
|
"unfollow": "Unfollow",
|
|
"unfollowTitle": "Unfollow {name}?",
|
|
"unfollowDesc": "You'll stop seeing {name}'s posts in your feed.",
|
|
"keepFollowing": "Keep following",
|
|
"followError": "Something went wrong. Try again.",
|
|
"nowFollowing": "You're now following {name}",
|
|
"unfollowed": "Unfollowed {name}"
|
|
},
|
|
"Search": {
|
|
"title": "Search",
|
|
"placeholder": "Search pets, people or hashtags…",
|
|
"tabPets": "Pets",
|
|
"tabPeople": "People",
|
|
"tabTags": "Tags",
|
|
"typeMore": "Type at least 2 characters to search",
|
|
"typeHashtag": "Type a hashtag to search",
|
|
"noPets": "No pets found for \"{query}\"",
|
|
"noPeople": "No people found for \"{query}\"",
|
|
"noTags": "No posts tagged #{tag}",
|
|
"followerCount": "{count} followers"
|
|
},
|
|
"Messages": {
|
|
"pageTitle": "Messages",
|
|
"noMessages": "No messages yet",
|
|
"noMessagesHint": "Visit a pet's profile and tap Message to start a conversation.",
|
|
"you": "You",
|
|
"startConversation": "Start the conversation",
|
|
"timeNow": "now",
|
|
"relativeMinutes": "{count}m",
|
|
"relativeHours": "{count}h",
|
|
"relativeDays": "{count}d",
|
|
"today": "Today",
|
|
"yesterday": "Yesterday",
|
|
"empty": "Say hello 👋",
|
|
"placeholder": "Message…",
|
|
"charsLeft": "{count} characters left",
|
|
"sendError": "Failed to send message. Try again."
|
|
},
|
|
"FeedList": {
|
|
"forYou": "For you",
|
|
"recent": "Recent",
|
|
"allCaughtUp": "You're all caught up. Follow more pets to see more posts."
|
|
},
|
|
"ProfileTabs": {
|
|
"posts": "Posts",
|
|
"milestones": "Milestones",
|
|
"noPosts": "No posts yet",
|
|
"noMilestones": "No milestones yet"
|
|
},
|
|
"ExploreCard": {
|
|
"followerSingular": "1 follower",
|
|
"followerPlural": "{count} followers",
|
|
"yourPet": "Your pet"
|
|
},
|
|
"Health": {
|
|
"pageTitle": "Health — {petName}",
|
|
"shareCard": "Share Card",
|
|
"tabWeight": "Weight",
|
|
"tabVet": "Vet Visits",
|
|
"tabVaccines": "Vaccines",
|
|
"cancel": "Cancel",
|
|
"save": "Save",
|
|
"weight": {
|
|
"add": "Add Weight",
|
|
"noEntries": "No weight entries yet",
|
|
"singular": "1 entry",
|
|
"plural": "{count} entries",
|
|
"labelDate": "Date",
|
|
"labelWeight": "Weight (kg)",
|
|
"placeholderWeight": "e.g. 4.2",
|
|
"labelNotes": "Notes (optional)",
|
|
"placeholderNotes": "e.g. after morning walk",
|
|
"toastAdded": "Weight entry added",
|
|
"toastDeleted": "Entry deleted",
|
|
"toastError": "Failed to save weight entry",
|
|
"toastDeleteError": "Failed to delete entry",
|
|
"toastValidation": "Please fill in date and a valid weight"
|
|
},
|
|
"vet": {
|
|
"add": "Add Visit",
|
|
"noEntries": "No vet visits yet",
|
|
"singular": "1 visit",
|
|
"plural": "{count} visits",
|
|
"labelDate": "Date",
|
|
"labelVet": "Vet / Clinic (optional)",
|
|
"placeholderVet": "e.g. Dr. Müller",
|
|
"labelReason": "Reason *",
|
|
"placeholderReason": "e.g. Annual checkup",
|
|
"labelNotes": "Notes (optional)",
|
|
"placeholderNotes": "Diagnosis, treatment, medications…",
|
|
"toastAdded": "Vet visit added",
|
|
"toastDeleted": "Entry deleted",
|
|
"toastError": "Failed to save vet visit",
|
|
"toastDeleteError": "Failed to delete entry",
|
|
"toastValidation": "Please fill in date and reason"
|
|
},
|
|
"vaccines": {
|
|
"add": "Add Vaccine",
|
|
"noEntries": "No vaccines recorded yet",
|
|
"singular": "1 vaccine",
|
|
"plural": "{count} vaccines",
|
|
"labelName": "Vaccine Name *",
|
|
"placeholderName": "e.g. Rabies, DHPP",
|
|
"labelDateGiven": "Date Given *",
|
|
"labelNextDue": "Next Due (optional)",
|
|
"labelNotes": "Notes (optional)",
|
|
"placeholderNotes": "Batch number, clinic…",
|
|
"badgeOverdue": "Overdue",
|
|
"badgeDue": "Due {date}",
|
|
"textGiven": "Given {date}",
|
|
"toastAdded": "Vaccine added",
|
|
"toastDeleted": "Entry deleted",
|
|
"toastError": "Failed to save vaccine",
|
|
"toastDeleteError": "Failed to delete entry",
|
|
"toastValidation": "Please fill in vaccine name and date given"
|
|
},
|
|
"feeding": {
|
|
"sectionTitle": "Feeding",
|
|
"edit": "Edit",
|
|
"add": "Add Feeding Info",
|
|
"labelFoodType": "Food type",
|
|
"labelFeedingTimes": "Feedings per day",
|
|
"labelDailyAmount": "Daily amount (g)",
|
|
"labelBrand": "Brand (optional)",
|
|
"labelSpecialDiet": "Special diet / allergies (optional)",
|
|
"placeholderFoodType": "e.g. Dry food, Wet food, BARF",
|
|
"placeholderFeedingTimes": "e.g. 2",
|
|
"placeholderDailyAmount": "e.g. 200",
|
|
"placeholderBrand": "e.g. Royal Canin",
|
|
"placeholderSpecialDiet": "e.g. Grain-free, chicken allergy…",
|
|
"noInfo": "No feeding info saved yet.",
|
|
"timesPerDay": "{count}x per day",
|
|
"gramsPerDay": "{amount} g / day",
|
|
"toastSaved": "Feeding info saved",
|
|
"toastDeleted": "Feeding info removed",
|
|
"toastError": "Could not save feeding info",
|
|
"toastDeleteError": "Could not remove feeding info"
|
|
}
|
|
}
|
|
}
|