ADD - add garage fallback translations

This commit is contained in:
Leon.Schmidt
2026-08-08 18:53:33 +02:00
parent 140cf961a1
commit 3fac15fe36
+470 -95
View File
@@ -1,4 +1,3 @@
import { defineStore } from 'pinia'
import type { AppLaunchOrigin, LaunchablePhoneAppId } from '@/types/apps'
@@ -30,24 +29,122 @@ const namespaceQueues = new Map<string, Promise<void>>()
const defaultLocales: LocaleTree = {
Apps: {
darkchat: {
name: 'DarkChat', newMessage: 'New DarkChat message from {sender}', privateNotification: 'New DarkChat message',
signInBody: 'DarkChat identities are linked to your private iFruit account.', signInHint: 'Sign in through Settings to continue.',
security: 'Security', privateNetwork: 'Private invitation-only network', noResults: 'No Results', noResultsBody: 'Try another alias or Dark-ID.',
noChats: 'No Private Chats', noChatsBody: 'Connect with a Dark-ID or invitation code. There is no public search.', newChat: 'New Chat',
connectPrivately: 'Connect privately', newChatBody: 'Enter an exact Dark-ID or invitation code. Unknown identities require confirmation.', darkIdOrInvite: 'Dark-ID or invitation code', continue: 'Continue', contacts: 'DarkChat Contacts', shareIdentity: 'Tap to share your private identity',
message: 'Dark message', activeNow: 'Activity shared', encryptedSession: 'Private session', serverPrivate: 'Private server-stored conversation',
emoji: 'Emoji', gif: 'GIF', gifs: 'GIFs', photo: 'Photo', video: 'Video', attachPhoto: 'Attach Photo', takePhoto: 'Take Photo', attachGif: 'Attach GIF', attachVideo: 'Attach Video', searchGifs: 'Search GIFs', loadMore: 'Load More',
voiceMessage: 'Voice message', sending: 'Sending', failed: 'Not delivered', delivered: 'Delivered', read: 'Read', replying: 'Replying to',
messageDeleted: 'Message deleted', securityUpdate: 'Security settings updated', timerChanged: 'Disappearing messages: {timer}',
timerOff: 'Off', timerAfterRead: 'After reading', timerMinute: '1 minute', timerFiveMinutes: '5 minutes', timerHour: '1 hour', timerDay: '24 hours', timerWeek: '7 days',
copied: 'Copied', reply: 'Reply', copy: 'Copy', deleteForMe: 'Delete for me', deleteForBoth: 'Delete for both', report: 'Report',
contactSecurity: 'Contact & Security', chatSince: 'Private chat since {date}', notifications: 'Notifications', readReceipts: 'Read receipts', disappearing: 'Disappearing messages', contactAlias: 'Contact alias', saveContact: 'Save Contact', addContact: 'Add Contact', contactSaved: 'Contact saved', removeContact: 'Remove Contact', block: 'Block User', unblock: 'Unblock User', clearChat: 'Clear Chat', chatCleared: 'Chat cleared',
myIdentity: 'My Dark Identity', alias: 'Alias', notificationPrivacy: 'Notification privacy', notificationFull: 'Full · alias and message', notificationPrivate: 'Private · generic message', notificationHidden: 'Invisible · badge only', shareActivity: 'Share activity status', inviteCode: 'Private invitation code', copyInvite: 'Copy Invite', privacyDisclaimer: 'DarkChat stores messages on the server and does not claim end-to-end encryption.',
unknownIdentity: 'Unknown Identity', unknownIdentityBody: 'Only continue if you expected this identity. The account is not discoverable through public search.', openSecureChat: 'Open Private Chat',
reportUser: 'Report User', reportSpam: 'Spam', reportHarassment: 'Harassment', reportThreats: 'Threats', reportIllegal: 'Illegal content', reportOther: 'Other', reportDetails: 'Optional details', submitReport: 'Submit Report', reported: 'Report submitted',
microphoneUnavailable: 'The microphone is unavailable.', recordingTooLarge: 'The voice message is too large.',
name: 'DarkChat',
newMessage: 'New DarkChat message from {sender}',
privateNotification: 'New DarkChat message',
signInBody:
'DarkChat identities are linked to your private iFruit account.',
signInHint: 'Sign in through Settings to continue.',
security: 'Security',
privateNetwork: 'Private invitation-only network',
noResults: 'No Results',
noResultsBody: 'Try another alias or Dark-ID.',
noChats: 'No Private Chats',
noChatsBody:
'Connect with a Dark-ID or invitation code. There is no public search.',
newChat: 'New Chat',
connectPrivately: 'Connect privately',
newChatBody:
'Enter an exact Dark-ID or invitation code. Unknown identities require confirmation.',
darkIdOrInvite: 'Dark-ID or invitation code',
continue: 'Continue',
contacts: 'DarkChat Contacts',
shareIdentity: 'Tap to share your private identity',
message: 'Dark message',
activeNow: 'Activity shared',
encryptedSession: 'Private session',
serverPrivate: 'Private server-stored conversation',
emoji: 'Emoji',
gif: 'GIF',
gifs: 'GIFs',
photo: 'Photo',
video: 'Video',
attachPhoto: 'Attach Photo',
takePhoto: 'Take Photo',
attachGif: 'Attach GIF',
attachVideo: 'Attach Video',
searchGifs: 'Search GIFs',
loadMore: 'Load More',
voiceMessage: 'Voice message',
sending: 'Sending',
failed: 'Not delivered',
delivered: 'Delivered',
read: 'Read',
replying: 'Replying to',
messageDeleted: 'Message deleted',
securityUpdate: 'Security settings updated',
timerChanged: 'Disappearing messages: {timer}',
timerOff: 'Off',
timerAfterRead: 'After reading',
timerMinute: '1 minute',
timerFiveMinutes: '5 minutes',
timerHour: '1 hour',
timerDay: '24 hours',
timerWeek: '7 days',
copied: 'Copied',
reply: 'Reply',
copy: 'Copy',
deleteForMe: 'Delete for me',
deleteForBoth: 'Delete for both',
report: 'Report',
contactSecurity: 'Contact & Security',
chatSince: 'Private chat since {date}',
notifications: 'Notifications',
readReceipts: 'Read receipts',
disappearing: 'Disappearing messages',
contactAlias: 'Contact alias',
saveContact: 'Save Contact',
addContact: 'Add Contact',
contactSaved: 'Contact saved',
removeContact: 'Remove Contact',
block: 'Block User',
unblock: 'Unblock User',
clearChat: 'Clear Chat',
chatCleared: 'Chat cleared',
myIdentity: 'My Dark Identity',
alias: 'Alias',
notificationPrivacy: 'Notification privacy',
notificationFull: 'Full · alias and message',
notificationPrivate: 'Private · generic message',
notificationHidden: 'Invisible · badge only',
shareActivity: 'Share activity status',
inviteCode: 'Private invitation code',
copyInvite: 'Copy Invite',
privacyDisclaimer:
'DarkChat stores messages on the server and does not claim end-to-end encryption.',
unknownIdentity: 'Unknown Identity',
unknownIdentityBody:
'Only continue if you expected this identity. The account is not discoverable through public search.',
openSecureChat: 'Open Private Chat',
reportUser: 'Report User',
reportSpam: 'Spam',
reportHarassment: 'Harassment',
reportThreats: 'Threats',
reportIllegal: 'Illegal content',
reportOther: 'Other',
reportDetails: 'Optional details',
submitReport: 'Submit Report',
reported: 'Report submitted',
microphoneUnavailable: 'The microphone is unavailable.',
recordingTooLarge: 'The voice message is too large.',
errors: {
not_authenticated: 'Sign in to your iFruit account first.', invalid_dark_id: 'Enter a valid Dark-ID or invitation code.', profile_not_found: 'This private identity was not found.', self_chat: 'You cannot message your own identity.', conversation_not_found: 'This conversation is unavailable.', blocked: 'Messages are blocked in this conversation.', invalid_message: 'Enter a valid message.', invalid_gif: 'This GIF is invalid.', invalid_voice: 'This voice message is invalid.', invalid_attachment: 'This photo or video is unavailable.', invalid_profile: 'Check your alias and privacy settings.', rate_limited: 'Too many requests. Try again shortly.', gif_provider_unconfigured: 'GIF search is not configured.', gif_provider_unauthorized: 'The GIF provider key is invalid.', gif_provider_rate_limited: 'GIF search is busy. Try again shortly.', gif_provider_failed: 'GIFs are temporarily unavailable.', default: 'DarkChat could not complete the request.',
not_authenticated: 'Sign in to your iFruit account first.',
invalid_dark_id: 'Enter a valid Dark-ID or invitation code.',
profile_not_found: 'This private identity was not found.',
self_chat: 'You cannot message your own identity.',
conversation_not_found: 'This conversation is unavailable.',
blocked: 'Messages are blocked in this conversation.',
invalid_message: 'Enter a valid message.',
invalid_gif: 'This GIF is invalid.',
invalid_voice: 'This voice message is invalid.',
invalid_attachment: 'This photo or video is unavailable.',
invalid_profile: 'Check your alias and privacy settings.',
rate_limited: 'Too many requests. Try again shortly.',
gif_provider_unconfigured: 'GIF search is not configured.',
gif_provider_unauthorized: 'The GIF provider key is invalid.',
gif_provider_rate_limited: 'GIF search is busy. Try again shortly.',
gif_provider_failed: 'GIFs are temporarily unavailable.',
default: 'DarkChat could not complete the request.',
},
},
messages: {
@@ -117,7 +214,8 @@ const defaultLocales: LocaleTree = {
media_provider_unconfigured: 'Photo uploads are not configured.',
capture_provider_unavailable: 'The screenshot resource is unavailable.',
capture_failed: 'The photo could not be captured.',
video_provider_unavailable: 'Video capture requires the screencapture resource.',
video_provider_unavailable:
'Video capture requires the screencapture resource.',
video_capture_failed: 'The video could not be recorded.',
recording_in_progress: 'A video is already being recorded.',
recording_not_found: 'No active video recording was found.',
@@ -261,6 +359,105 @@ const defaultLocales: LocaleTree = {
default: 'The banking request failed.',
},
},
garage: {
name: 'Garage',
subtitle: 'Your vehicle collection',
myVehicles: 'My Vehicles',
searchPlaceholder: 'Search name, plate or garage',
tryAgain: 'Try Again',
unavailable: 'Garage unavailable',
noVehicles: 'No Vehicles',
noVehiclesBody: 'Vehicles owned by this character will appear here.',
noResults: 'No Results',
noResultsBody: 'Try another vehicle, plate or location.',
unknownVehicle: 'Unknown Vehicle',
unknownLocation: 'Location unavailable',
location: 'Current location',
fuel: 'Fuel',
engine: 'Engine',
body: 'Body',
vin: 'Vehicle Identification Number',
notAvailable: '—',
provider: 'Vehicle data · {system}',
valet: {
title: 'Sky Valet',
eyebrow: 'Premium delivery',
body: 'A professional driver brings this vehicle directly to your current location.',
deliver: 'Deliver Vehicle',
liveEyebrow: 'Live delivery',
tracked: 'Live tracked',
onDemand: 'On demand',
cancel: 'Cancel',
confirmTitle: 'Request Valet?',
confirmBody: '{vehicle} will be delivered to you for {price}.',
confirm: 'Request Valet',
ordering: 'Requesting…',
account: 'The fee is charged to your {account} account.',
connecting: 'Locating driver',
arriving: 'Arriving now',
eta: 'About {seconds}s away',
distance: '{distance} m away',
unavailableStatus: 'Only parked vehicles can be delivered.',
unsupported: 'Valet delivery is disabled for this vehicle type.',
activeOrder: 'A valet driver is already delivering another vehicle.',
status: {
ordering: 'Confirming order',
preparing: 'Preparing vehicle',
en_route: 'Driver en route',
arriving: 'Arriving now',
delivered: 'Vehicle delivered',
cancelled: 'Delivery cancelled',
failed: 'Delivery failed',
},
},
filters: {
all: 'All',
garaged: 'Parked',
out: 'Outside',
impounded: 'Impound',
},
status: {
garaged: 'Parked',
out: 'Outside',
impounded: 'Impounded',
},
kinds: {
car: 'Vehicle',
bike: 'Motorcycle',
boat: 'Boat',
plane: 'Aircraft',
helicopter: 'Helicopter',
},
errors: {
garage_unavailable: 'Vehicle data is unavailable for this character.',
valet_disabled: 'Valet service is currently unavailable.',
valet_active: 'A valet delivery is already active.',
valet_cooldown: 'Please wait before requesting another vehicle.',
invalid_vehicle: 'Select a valid vehicle.',
vehicle_not_owned: 'This vehicle does not belong to this character.',
vehicle_not_garaged: 'This vehicle is not parked in a garage.',
valet_vehicle_type: 'Valet supports cars and motorcycles only.',
insufficient_funds: 'You do not have enough money for this delivery.',
valet_status_unsupported:
'This garage system cannot release the vehicle.',
valet_not_found: 'The valet order is no longer active.',
valet_not_cancellable: 'The delivery can no longer be cancelled.',
invalid_vehicle_model: 'The vehicle model could not be loaded.',
vehicle_already_out: 'This vehicle is already nearby.',
valet_spawn_failed: 'The driver could not prepare your vehicle.',
valet_no_road: 'No suitable road was found near you.',
valet_interrupted: 'The valet delivery was interrupted.',
valet_timeout:
'The driver could not reach you in time. Your fee was refunded.',
valet_completion_failed: 'The handover could not be confirmed.',
valet_vehicle_unverified:
'The delivered vehicle could not be verified.',
rate_limited: 'Please wait before refreshing again.',
device_not_open: 'Open the phone again to view your vehicles.',
request_failed: 'The garage request failed.',
default: 'The garage request failed.',
},
},
calculator: { name: 'Calculator' },
snake: {
name: 'Snake',
@@ -315,7 +512,8 @@ const defaultLocales: LocaleTree = {
best: 'Best',
board: '2048 game board',
cancel: 'Keep Current Game',
confirmBody: 'Your current board will be replaced. This cannot be undone.',
confirmBody:
'Your current board will be replaced. This cannot be undone.',
confirmNew: 'Start New Game',
confirmTitle: 'Replace current game?',
continueGame: 'Continue Game',
@@ -330,9 +528,11 @@ const defaultLocales: LocaleTree = {
gameOverBody: 'No empty spaces or matching neighbours remain.',
gameOverTitle: 'No more moves',
highest: 'Highest Tile',
howToBody: 'Swipe to combine matching tiles. Each pair becomes one larger tile.',
howToBody:
'Swipe to combine matching tiles. Each pair becomes one larger tile.',
howToExample: '2 + 2 = 4 · 4 + 4 = 8 · … · 1024 + 1024 = 2048',
howToGoal: 'Goal: create the 2048 tile before the board has no moves left.',
howToGoal:
'Goal: create the 2048 tile before the board has no moves left.',
howToTitle: 'How to play',
keepPlaying: 'Keep Playing',
mainMenu: 'Main Menu',
@@ -343,7 +543,8 @@ const defaultLocales: LocaleTree = {
score: 'Score',
swipeHint: 'Swipe the board, use the buttons, or press arrow keys / WASD',
unmute: 'Turn on game sounds',
wonBody: 'You reached the legendary tile. Continue climbing or begin again.',
wonBody:
'You reached the legendary tile. Continue climbing or begin again.',
wonTitle: 'You made 2048!',
},
minesweeper: {
@@ -474,13 +675,36 @@ const defaultLocales: LocaleTree = {
citymarkt: {
name: 'CityMarkt',
eyebrow: 'Los Santos marketplace',
tabs: { discover: 'Discover', search: 'Search', sell: 'Sell', inbox: 'Inbox', profile: 'Me' },
tabs: {
discover: 'Discover',
search: 'Search',
sell: 'Sell',
inbox: 'Inbox',
profile: 'Me',
},
categories: {
vehicles: 'Vehicles', property: 'Property', electronics: 'Electronics', clothing: 'Clothing',
tools: 'Tools', leisure: 'Leisure', services: 'Services', jobs: 'Jobs', wanted: 'Wanted', other: 'Other',
vehicles: 'Vehicles',
property: 'Property',
electronics: 'Electronics',
clothing: 'Clothing',
tools: 'Tools',
leisure: 'Leisure',
services: 'Services',
jobs: 'Jobs',
wanted: 'Wanted',
other: 'Other',
},
conditions: {
new: 'New',
very_good: 'Very good',
used: 'Used',
defective: 'Defective',
},
priceTypes: {
fixed: 'Fixed price',
negotiable: 'Negotiable',
free: 'Free',
},
conditions: { new: 'New', very_good: 'Very good', used: 'Used', defective: 'Defective' },
priceTypes: { fixed: 'Fixed price', negotiable: 'Negotiable', free: 'Free' },
offerStatus: {
pending: 'Open',
accepted: 'Accepted',
@@ -488,82 +712,230 @@ const defaultLocales: LocaleTree = {
countered: 'Negotiated',
},
districts: {
los_santos: 'Los Santos', vinewood: 'Vinewood', vespucci: 'Vespucci',
south_los_santos: 'South Los Santos', sandy_shores: 'Sandy Shores',
paleto_bay: 'Paleto Bay', blaine_county: 'Blaine County',
los_santos: 'Los Santos',
vinewood: 'Vinewood',
vespucci: 'Vespucci',
south_los_santos: 'South Los Santos',
sandy_shores: 'Sandy Shores',
paleto_bay: 'Paleto Bay',
blaine_county: 'Blaine County',
},
status: { active: 'Active', reserved: 'Reserved', sold: 'Sold', expired: 'Expired', removed: 'Removed' },
reportReasons: { prohibited: 'Prohibited item', fraud: 'Suspected fraud', spam: 'Spam', offensive: 'Offensive content', other: 'Other' },
searchPlaceholder: 'What are you looking for?', allCategories: 'All categories', allDistricts: 'All districts',
sortNewest: 'Newest first', sortPriceAsc: 'Lowest price', sortPriceDesc: 'Highest price',
freshOffers: 'Fresh offers', offers: 'offers', noListings: 'No offers found',
noListingsBody: 'Try another search or category.', noDistrict: 'No district',
free: 'Free', negotiablePrice: '${price} negotiable', money: '${price}',
hoursAgo: '{count}h ago', daysAgo: '{count}d ago', photos: 'photos', activeListings: 'active listings',
signInTitle: 'Sign in to iFruit', signInBody: 'Use Settings to sign in before selling, saving or messaging.',
noMessages: 'No conversations', noMessagesBody: 'Messages about offers will appear here.',
myListings: 'My listings', favorites: 'Favorites', noProfileListings: 'Nothing here yet',
phone: 'Phone', contactSeller: 'Contact seller', messagePlaceholder: 'Hi, is this still available?',
status: {
active: 'Active',
reserved: 'Reserved',
sold: 'Sold',
expired: 'Expired',
removed: 'Removed',
},
reportReasons: {
prohibited: 'Prohibited item',
fraud: 'Suspected fraud',
spam: 'Spam',
offensive: 'Offensive content',
other: 'Other',
},
searchPlaceholder: 'What are you looking for?',
allCategories: 'All categories',
allDistricts: 'All districts',
sortNewest: 'Newest first',
sortPriceAsc: 'Lowest price',
sortPriceDesc: 'Highest price',
freshOffers: 'Fresh offers',
offers: 'offers',
noListings: 'No offers found',
noListingsBody: 'Try another search or category.',
noDistrict: 'No district',
free: 'Free',
negotiablePrice: '${price} negotiable',
money: '${price}',
hoursAgo: '{count}h ago',
daysAgo: '{count}d ago',
photos: 'photos',
activeListings: 'active listings',
signInTitle: 'Sign in to iFruit',
signInBody:
'Use Settings to sign in before selling, saving or messaging.',
noMessages: 'No conversations',
noMessagesBody: 'Messages about offers will appear here.',
myListings: 'My listings',
favorites: 'Favorites',
noProfileListings: 'Nothing here yet',
phone: 'Phone',
contactSeller: 'Contact seller',
messagePlaceholder: 'Hi, is this still available?',
signInToMessage: 'Sign in to your iFruit account to send a message.',
edit: 'Edit', makeActive: 'Make active', markSold: 'Mark sold', remove: 'Remove',
createListing: 'Create listing', editListing: 'Edit listing', save: 'Save', step: 'Step {current} of {total}', next: 'Next', previous: 'Back', publish: 'Publish',
addPhotos: 'Add photos', addPhotosBody: 'Choose up to six photos from your gallery or take new ones. Photos are optional and the first becomes the cover.',
chooseGallery: 'Choose from gallery', chooseGalleryBody: 'Use photos saved on this phone.',
takePhotos: 'Take photos', takePhotosBody: 'Take several new photos for this listing.',
selectedPhotos: 'Selected photos', gallery: 'Gallery', camera: 'Camera', takePhoto: 'Take photo',
cameraHint: 'Take as many photos as you need. Each shot is added to the listing automatically.',
noPhoto: 'No photo available', noPhotoBody: 'The seller did not add a photo to this listing.',
noPhotoOptional: 'You can publish without a photo or add one from the gallery or camera.',
previousPhoto: 'Previous photo', nextPhoto: 'Next photo', photo: 'Photo',
removePhoto: 'Remove photo {number}', photoLimit: 'You can add up to six photos.',
describeOffer: 'Describe your offer', title: 'Title', description: 'Description', category: 'Category', condition: 'Condition',
characterCount: '{current} / {maximum} characters', minimumCharacters: 'min. {minimum}',
priceAndPlace: 'Price and location', priceType: 'Price type', price: 'Price', district: 'District',
showPhone: 'Show my current phone number', preview: 'Preview', published: 'Your listing is live.',
writeMessage: 'Write a message', reserveForBuyer: 'Reserve for this buyer', statusChanged: 'Listing updated.',
offer: 'Offer', counterOffer: 'Counteroffer', makeOffer: 'Make an offer',
offeredByYou: 'You sent this offer.', offeredToYou: 'You received this offer.',
acceptOffer: 'Accept', declineOffer: 'Decline', negotiateOffer: 'Counter',
offerFor: 'Your offer for', offerAmount: 'Offer amount', sendOffer: 'Send offer',
offerSent: 'Your offer was sent.', offerAccepted: 'Offer accepted.', offerDeclined: 'Offer declined.',
reportListing: 'Report listing', reportWhy: 'Why are you reporting this?', reportDetails: 'Add details (optional)',
sendReport: 'Send report', blockSeller: 'Block seller', reported: 'Report sent.', blocked: 'Seller blocked.',
edit: 'Edit',
makeActive: 'Make active',
markSold: 'Mark sold',
remove: 'Remove',
createListing: 'Create listing',
editListing: 'Edit listing',
save: 'Save',
step: 'Step {current} of {total}',
next: 'Next',
previous: 'Back',
publish: 'Publish',
addPhotos: 'Add photos',
addPhotosBody:
'Choose up to six photos from your gallery or take new ones. Photos are optional and the first becomes the cover.',
chooseGallery: 'Choose from gallery',
chooseGalleryBody: 'Use photos saved on this phone.',
takePhotos: 'Take photos',
takePhotosBody: 'Take several new photos for this listing.',
selectedPhotos: 'Selected photos',
gallery: 'Gallery',
camera: 'Camera',
takePhoto: 'Take photo',
cameraHint:
'Take as many photos as you need. Each shot is added to the listing automatically.',
noPhoto: 'No photo available',
noPhotoBody: 'The seller did not add a photo to this listing.',
noPhotoOptional:
'You can publish without a photo or add one from the gallery or camera.',
previousPhoto: 'Previous photo',
nextPhoto: 'Next photo',
photo: 'Photo',
removePhoto: 'Remove photo {number}',
photoLimit: 'You can add up to six photos.',
describeOffer: 'Describe your offer',
title: 'Title',
description: 'Description',
category: 'Category',
condition: 'Condition',
characterCount: '{current} / {maximum} characters',
minimumCharacters: 'min. {minimum}',
priceAndPlace: 'Price and location',
priceType: 'Price type',
price: 'Price',
district: 'District',
showPhone: 'Show my current phone number',
preview: 'Preview',
published: 'Your listing is live.',
writeMessage: 'Write a message',
reserveForBuyer: 'Reserve for this buyer',
statusChanged: 'Listing updated.',
offer: 'Offer',
counterOffer: 'Counteroffer',
makeOffer: 'Make an offer',
offeredByYou: 'You sent this offer.',
offeredToYou: 'You received this offer.',
acceptOffer: 'Accept',
declineOffer: 'Decline',
negotiateOffer: 'Counter',
offerFor: 'Your offer for',
offerAmount: 'Offer amount',
sendOffer: 'Send offer',
offerSent: 'Your offer was sent.',
offerAccepted: 'Offer accepted.',
offerDeclined: 'Offer declined.',
reportListing: 'Report listing',
reportWhy: 'Why are you reporting this?',
reportDetails: 'Add details (optional)',
sendReport: 'Send report',
blockSeller: 'Block seller',
reported: 'Report sent.',
blocked: 'Seller blocked.',
newMessage: 'New CityMarkt message from {sender}',
newOffer: '{sender} offered ${price}.',
offerAcceptedNotification: '{sender} accepted your ${price} offer.',
offerRejectedNotification: '{sender} declined your ${price} offer.',
errors: {
invalid_listing: 'Check the listing details.', invalid_price: 'Enter a valid price.',
invalid_images: 'Choose valid photos from this phone.', phone_unavailable: 'Insert a SIM or hide your number.',
listing_limit: 'You have reached the active listing limit.', listing_not_found: 'This listing is no longer available.',
invalid_message: 'Enter a valid message.', inquiry_not_found: 'This conversation is no longer available.',
invalid_offer: 'Enter a valid whole-number offer.', invalid_offer_response: 'This offer action is invalid.',
offer_listing_unavailable: 'This listing is no longer available for offers.',
offer_closed: 'This negotiation is already complete.', offer_waiting: 'Wait for the other person to respond.',
offer_not_allowed: 'You cannot make an offer right now.', offer_not_actionable: 'This offer can no longer be changed.',
invalid_listing: 'Check the listing details.',
invalid_price: 'Enter a valid price.',
invalid_images: 'Choose valid photos from this phone.',
phone_unavailable: 'Insert a SIM or hide your number.',
listing_limit: 'You have reached the active listing limit.',
listing_not_found: 'This listing is no longer available.',
invalid_message: 'Enter a valid message.',
inquiry_not_found: 'This conversation is no longer available.',
invalid_offer: 'Enter a valid whole-number offer.',
invalid_offer_response: 'This offer action is invalid.',
offer_listing_unavailable:
'This listing is no longer available for offers.',
offer_closed: 'This negotiation is already complete.',
offer_waiting: 'Wait for the other person to respond.',
offer_not_allowed: 'You cannot make an offer right now.',
offer_not_actionable: 'This offer can no longer be changed.',
offer_conflict: 'The offer changed. Please try again.',
blocked: 'Messages are blocked between these accounts.', already_reported: 'You already reported this listing.',
rate_limited: 'Too many requests. Try again shortly.', not_authenticated: 'Sign in to your iFruit account first.',
conflict: 'The listing changed. Open it again.', request_failed: 'CityMarkt is temporarily unavailable.',
blocked: 'Messages are blocked between these accounts.',
already_reported: 'You already reported this listing.',
rate_limited: 'Too many requests. Try again shortly.',
not_authenticated: 'Sign in to your iFruit account first.',
conflict: 'The listing changed. Open it again.',
request_failed: 'CityMarkt is temporarily unavailable.',
default: 'The CityMarkt request failed.',
},
},
localPages: {
name: 'Local Pages', eyebrow: 'Your city. Your stories.', cityPulse: 'Live from Los Santos',
heroTitle: 'What is happening nearby?', heroBody: 'Discover places, people and local tips.',
searchPlaceholder: 'Search posts and places', search: 'Search', allCategories: 'All categories',
allLosSantos: 'Los Santos', hoursAgo: '{count}h ago', daysAgo: '{count}d ago',
categories: { recommendation: 'Recommended', wanted: 'Wanted', service: 'Service', event: 'Event', place: 'Place', community: 'Community', citymarkt: 'CityMarkt' },
discover: 'Discover', create: 'Post', profile: 'Profile', post: 'Post', posts: 'posts',
noPosts: 'Nothing here yet', noPostsBody: 'Be the first to share something with the city.', noPhoto: 'No photo attached',
signInTitle: 'Your Local Pages profile', signInBody: 'Sign in to iFruit in Settings to publish and save posts.',
localCreator: 'Local creator', myPosts: 'My posts', saved: 'Saved', save: 'Save', likes: 'likes',
location: 'Location', sharedFrom: 'Shared from CityMarkt', openCityMarkt: 'Open CityMarkt listing',
newPost: 'New local post', shareWithCity: 'Share with the city', publish: 'Publish', published: 'Your post is live.', deleted: 'Post deleted.',
title: 'Title', body: 'Your story', category: 'Category', titlePlaceholder: 'What should people know?', bodyPlaceholder: 'Add details, a recommendation or directions...',
photos: 'Photos', optional: 'optional', camera: 'Camera', gallery: 'Gallery', photoLimit: 'You can add up to six photos.',
cityMarktShare: 'Share to Local Pages', cityMarktShared: 'Shared to Local Pages.', cityMarktShareHint: 'One CityMarkt share per day',
errors: { invalid_post: 'Add a title and a little more detail.', invalid_images: 'Choose valid photos from this phone.', invalid_request: 'This action is not valid.', post_not_found: 'This post is no longer available.', citymarkt_not_found: 'This CityMarkt listing is unavailable.', citymarkt_daily_limit: 'You already shared a CityMarkt listing today.', citymarkt_already_shared: 'This listing was already shared.', not_authenticated: 'Sign in to iFruit first.', rate_limited: 'Too many requests. Try again shortly.', request_failed: 'The post could not be saved.', default: 'Local Pages is temporarily unavailable.' },
name: 'Local Pages',
eyebrow: 'Your city. Your stories.',
cityPulse: 'Live from Los Santos',
heroTitle: 'What is happening nearby?',
heroBody: 'Discover places, people and local tips.',
searchPlaceholder: 'Search posts and places',
search: 'Search',
allCategories: 'All categories',
allLosSantos: 'Los Santos',
hoursAgo: '{count}h ago',
daysAgo: '{count}d ago',
categories: {
recommendation: 'Recommended',
wanted: 'Wanted',
service: 'Service',
event: 'Event',
place: 'Place',
community: 'Community',
citymarkt: 'CityMarkt',
},
discover: 'Discover',
create: 'Post',
profile: 'Profile',
post: 'Post',
posts: 'posts',
noPosts: 'Nothing here yet',
noPostsBody: 'Be the first to share something with the city.',
noPhoto: 'No photo attached',
signInTitle: 'Your Local Pages profile',
signInBody: 'Sign in to iFruit in Settings to publish and save posts.',
localCreator: 'Local creator',
myPosts: 'My posts',
saved: 'Saved',
save: 'Save',
likes: 'likes',
location: 'Location',
sharedFrom: 'Shared from CityMarkt',
openCityMarkt: 'Open CityMarkt listing',
newPost: 'New local post',
shareWithCity: 'Share with the city',
publish: 'Publish',
published: 'Your post is live.',
deleted: 'Post deleted.',
title: 'Title',
body: 'Your story',
category: 'Category',
titlePlaceholder: 'What should people know?',
bodyPlaceholder: 'Add details, a recommendation or directions...',
photos: 'Photos',
optional: 'optional',
camera: 'Camera',
gallery: 'Gallery',
photoLimit: 'You can add up to six photos.',
cityMarktShare: 'Share to Local Pages',
cityMarktShared: 'Shared to Local Pages.',
cityMarktShareHint: 'One CityMarkt share per day',
errors: {
invalid_post: 'Add a title and a little more detail.',
invalid_images: 'Choose valid photos from this phone.',
invalid_request: 'This action is not valid.',
post_not_found: 'This post is no longer available.',
citymarkt_not_found: 'This CityMarkt listing is unavailable.',
citymarkt_daily_limit: 'You already shared a CityMarkt listing today.',
citymarkt_already_shared: 'This listing was already shared.',
not_authenticated: 'Sign in to iFruit first.',
rate_limited: 'Too many requests. Try again shortly.',
request_failed: 'The post could not be saved.',
default: 'Local Pages is temporarily unavailable.',
},
},
map: {
name: 'Map',
@@ -682,9 +1054,11 @@ const defaultLocales: LocaleTree = {
note: 'Note',
notePlaceholder: 'Add details, an address or anything to remember...',
noEvents: 'Nothing planned',
noEventsBody: 'This day is still free. Add an event whenever you are ready.',
noEventsBody:
'This day is still free. Add an event whenever you are ready.',
signInTitle: 'Your iFruit calendar',
signInBody: 'Sign in to iFruit in Settings to sync appointments and receive reminders.',
signInBody:
'Sign in to iFruit in Settings to sync appointments and receive reminders.',
reminderNotification: 'Upcoming: {title}',
views: {
compact: 'Compact',
@@ -701,7 +1075,8 @@ const defaultLocales: LocaleTree = {
oneDay: '1 day before',
},
errors: {
invalid_event: 'Enter a title and make sure the end is after the start.',
invalid_event:
'Enter a title and make sure the end is after the start.',
invalid_range: 'This calendar period is invalid.',
conflict: 'This event changed on another phone. Open it again.',
rate_limited: 'Too many changes. Try again shortly.',