export type Locale = 'en' | 'fi';

const allMessages = {
  en: {
    brand: 'lomavuokraus.fi',
    navProfile: 'Profile',
    navMyListings: 'My listings',
    navNewListing: 'New listing',
    navApprovals: 'Approvals',
    navUsers: 'Users',
    navLogout: 'Logout',
    navLogin: 'Login',
    navSignup: 'Sign up',
    navBrowse: 'Browse listings',
    navLanguage: 'Language',
    approvalsBadge: '{count}',
    heroEyebrow: 'lomavuokraus.fi',
    heroTitle: 'Find your next Finnish getaway',
    heroBody: 'A fast, modern marketplace for holiday rentals. Built with the Next.js App Router and ready for Kubernetes from day one.',
    ctaViewSample: 'View a sample listing',
    ctaHealth: 'Check health endpoint',
    ctaBrowse: 'Browse listings',
    highlightQualityTitle: 'Quality stays',
    highlightQualityBody: 'Curated cabins and villas with clear availability and simple booking.',
    highlightLocalTitle: 'Local-first',
    highlightLocalBody: 'Built for Finnish seasons with fast content delivery in the Nordics.',
    highlightApiTitle: 'API-friendly',
    highlightApiBody: 'Structured data so you can surface listings wherever you need them.',
    runtimeConfigTitle: 'Runtime configuration',
    runtimeConfigLead: 'Build-time and runtime values used by the service.',
    runtimeAppEnv: 'APP_ENV',
    runtimeSiteUrl: 'NEXT_PUBLIC_SITE_URL',
    runtimeApiBase: 'NEXT_PUBLIC_API_BASE',
    aboutTitle: 'About lomavuokraus.fi',
    aboutLead: 'A focused marketplace for Finnish holiday rentals with fast browsing, clear moderation, and a simple host experience.',
    pricingTitle: 'Pricing',
    pricingLead: 'Straightforward pricing for hosts with no surprises.',
    pricingMonthly: 'Monthly',
    pricingAnnual: 'Annual',
    pricingPerMonth: 'per month',
    pricingPerYear: 'per year (save 20%)',
    pricingMonthlyBody: 'Start with a monthly plan at 10€ per listing.',
    pricingAnnualBody: 'Pay annually for 100€ per listing and keep your costs predictable.',
    pricingPerListing: 'Pricing is per active listing. Cancel anytime.',
    pricingNotesTitle: 'Notes',
    pricingNotesBody: 'We keep pricing simple while we build out hosting tools, messaging, and integrations. All current features are included.',
    footerAbout: 'About',
    footerPricing: 'Pricing',
    footerPrivacy: 'Privacy & cookies',
    loginTitle: 'Login',
    emailLabel: 'Email',
    passwordLabel: 'Password',
    loginButton: 'Login',
    loggingIn: 'Logging in…',
    loginSuccess: 'Login successful.',
    registerTitle: 'Create an account',
    registerLead: 'Verify email is required, and an admin will approve your account.',
    nameOptional: 'Name (optional)',
    passwordHint: 'Password (min 8 chars)',
    registerButton: 'Register',
    registering: 'Submitting…',
    registerSuccess: 'Registration successful. Check your email for a verification link.',
    forgotTitle: 'Forgot your password?',
    forgotLead: 'Enter your email and we will send a reset link.',
    forgotSubmit: 'Send reset link',
    forgotSuccess: 'If that email exists, a reset link has been sent.',
    forgotError: 'Could not send reset link right now.',
    resetTitle: 'Reset password',
    resetLead: 'Set a new password for your account.',
    resetSubmit: 'Set new password',
    resetSuccess: 'Password updated. You can log in now.',
    resetError: 'Failed to reset password. The link may be invalid or expired.',
    resetMissingToken: 'Reset token missing. Please use the link from your email.',
    forgotCta: 'Forgot password?',
    pendingAdminTitle: 'Admin: pending items',
    pendingUsersTitle: 'Pending users',
    pendingListingsTitle: 'Pending listings',
    noPendingUsers: 'No pending users.',
    noPendingListings: 'No pending listings.',
    statusLabel: 'status',
    slugsLabel: 'Slugs',
    verifiedLabel: 'verified',
    approve: 'Approve',
    approveAdmin: 'Approve + make admin',
    reject: 'Reject',
    remove: 'Remove',
    publish: 'Publish',
    approvalsMessage: 'Listing updated',
    userUpdated: 'User updated',
    adminRequired: 'Admin access required',
    adminUsersTitle: 'Admin: users',
    adminUsersLead: 'Manage user roles and approvals.',
    tableEmail: 'Email',
    tableRole: 'Role',
    tableStatus: 'Status',
    tableVerified: 'Verified',
    tableApproved: 'Approved',
    myListingsTitle: 'My listings',
    createNewListing: 'Create new listing',
    noListings: 'No listings yet.',
    createOne: 'Create one',
    loading: 'Loading…',
    view: 'View',
    removing: 'Removing…',
    removed: 'Listing removed',
    removeConfirm: 'Remove this listing? It will be hidden from others.',
    myProfileTitle: 'My profile',
    notLoggedIn: 'Not logged in',
    profileEmail: 'Email',
    profileName: 'Name',
    profilePhone: 'Phone',
    profileRole: 'Role',
    profileStatus: 'Status',
    profileEmailVerified: 'Email verified',
    profileApproved: 'Approved',
    profileUpdated: 'Profile updated',
    emailLocked: 'Email cannot be changed',
    save: 'Save',
    saving: 'Saving…',
    yes: 'yes',
    no: 'no',
    verifyTitle: 'Email verification',
    verifyOk: 'Your email is verified. An admin will approve your account shortly.',
    verifyFail: 'Verification failed or token invalid.',
    listingLocation: 'Location',
    listingAddress: 'Address',
    listingCapacity: 'Capacity',
    listingAmenities: 'Amenities',
    listingNoAmenities: 'No amenities listed yet.',
    listingContact: 'Contact',
    listingMoreInfo: 'More info',
    availabilityTitle: 'Availability calendar',
    availabilityLegendBooked: 'Booked',
    availabilityMissing: 'Calendar not connected yet.',
    localeLabel: 'Locale',
    homeCrumb: 'Home',
    createListingTitle: 'Create listing',
    loginToCreate: 'Please log in first to create a listing.',
    slugLabel: 'Slug',
    localeInput: 'Locale',
    titleLabel: 'Title',
    descriptionLabel: 'Description',
    teaserLabel: 'Teaser',
    countryLabel: 'Country',
    regionLabel: 'Region',
    cityLabel: 'City',
    contactNameLabel: 'Contact name',
    contactEmailLabel: 'Contact email',
    streetAddressLabel: 'Street address',
    addressNoteLabel: 'Address note (optional)',
    addressNotePlaceholder: 'Directions, parking, or arrival details',
    latitudeLabel: 'Latitude (optional)',
    longitudeLabel: 'Longitude (optional)',
    maxGuestsLabel: 'Max guests',
    bedroomsLabel: 'Bedrooms',
    bedsLabel: 'Beds',
    bathroomsLabel: 'Bathrooms',
    priceHintLabel: 'Price ballpark (€ / night)',
    priceHintHelp: 'Rough nightly price in euros (not a binding offer).',
    calendarUrlsLabel: 'Availability calendars (iCal URLs, one per line)',
    calendarUrlsHelp: 'Paste iCal links from other platforms. We will merge them to show availability.',
    imagesLabel: 'Images',
    imagesHelp: 'Upload up to {count} images (max {sizeMb}MB each).',
    imagesTooMany: 'Too many images (max {count}).',
    imagesTooLarge: 'Image is too large (max {sizeMb}MB).',
    imagesReadFailed: 'Could not read selected images.',
    imagesRequired: 'Please upload at least one image.',
    coverImageLabel: 'Cover image order',
    coverImageHelp: '1-based index of the uploaded images (defaults to 1)',
    coverChoice: 'Cover position {index}',
    submitListing: 'Create listing',
    submittingListing: 'Submitting…',
    createListingSuccess: 'Listing created with id {id} (status: {status})',
    approvalsCountLabel: 'Approvals',
    approvalsPending: '{count} pending',
    amenitySauna: 'Sauna',
    amenityFireplace: 'Fireplace',
    amenityWifi: 'Wi-Fi',
    amenityPets: 'Pets allowed',
    amenityLake: 'By the lake',
    amenityAirConditioning: 'Air conditioning',
    amenityKitchen: 'Kitchen',
    amenityDishwasher: 'Dishwasher',
    amenityWashingMachine: 'Washing machine',
    amenityBarbecue: 'Barbecue grill',
    amenityEvFree: 'EV charging (free)',
    amenityEvPaid: 'EV charging (paid)',
    evChargingLabel: 'EV charging',
    evChargingNone: 'Not available',
    evChargingFree: 'Free for guests',
    evChargingPaid: 'Paid on-site',
    capacityGuests: '{count} guests',
    capacityBedrooms: '{count} bedrooms',
    capacityBeds: '{count} beds',
    capacityBathrooms: '{count} bathrooms',
    browseListingsTitle: 'Browse listings',
    browseListingsLead: 'Search public listings, filter by location, and explore them on the map.',
    sampleBadge: 'Sample',
    privacyTitle: 'Privacy & cookies',
    privacyUpdated: 'Updated: {date}',
    privacyCollectTitle: 'What data we collect',
    privacyCollectAccounts: 'Account data: email, password hash, name, phone (optional), role/status.',
    privacyCollectListings: 'Listing data: location, contact details, amenities, photos, translations.',
    privacyCollectLogs: 'Operational logs: minimal request metadata for diagnostics.',
    privacyUseTitle: 'How we use your data',
    privacyUseAuth: 'To authenticate users and manage sessions.',
    privacyUseListings: 'To publish and moderate listings.',
    privacyUseMail: 'To send transactional email (verification, password reset).',
    privacyUseLegal: 'To comply with legal requests or protect the service.',
    privacyStoreTitle: 'Storage & retention',
    privacyStoreDb: 'Data is stored in our Postgres database hosted in the EU.',
    privacyStoreBackups: 'Backups are retained for disaster recovery; removed accounts/listings may persist in backups for a limited time.',
    privacyCookiesTitle: 'Cookies',
    privacyCookiesSession: 'We use essential cookies only: a session cookie for login/authentication.',
    privacyCookiesNoTracking: 'No analytics, marketing, or tracking cookies are used.',
    privacySharingTitle: 'Sharing',
    privacySharingAds: 'We do not sell or share personal data with advertisers.',
    privacySharingOps: 'Data may be shared with service providers strictly for running the service (email delivery, hosting).',
    privacyRightsTitle: 'Your rights',
    privacyRightsAccess: 'Request access, correction, or deletion of your data.',
    privacyRightsConsent: 'Withdraw consent for non-essential processing (we currently process only essentials).',
    privacyRightsContact: 'Contact support for any privacy questions.',
    searchLabel: 'Search',
    searchPlaceholder: 'Search by name, description, or city',
    cityFilter: 'City',
    regionFilter: 'Region',
    searchButton: 'Search',
    searchAmenities: 'Amenities',
    searchAvailability: 'Availability',
    startDate: 'Start date',
    endDate: 'End date',
    availabilityOnlyWithCalendar: 'Only listings with a connected calendar are shown when filtering by dates.',
    availableForDates: 'Available for selected dates',
    notAvailableForDates: 'Unavailable for selected dates',
    calendarConnected: 'Calendar connected',
    clearFilters: 'Clear filters',
    addressSearchLabel: 'Find listings near an address',
    addressSearchPlaceholder: 'Street, city, or place',
    locateAddress: 'Locate on map',
    addressRadiusLabel: 'Within {km} km',
    listingsFound: '{count} listings',
    openListing: 'Open listing',
    mapNoResults: 'No listings match your filters.',
    evChargingAny: 'Any',
    addressNotFound: 'Address not found',
    addressLookupFailed: 'Failed to locate address',
    loadingMap: 'Loading map…',
    latestListingsTitle: 'Latest listings',
    latestListingsLead: 'Fresh rentals as they are published. Tap to browse.',
  },
  fi: {
    brand: 'lomavuokraus.fi',
    navProfile: 'Profiili',
    navMyListings: 'Omat kohteet',
    navNewListing: 'Luo kohde',
    navApprovals: 'Tarkastettavat',
    navUsers: 'Käyttäjät',
    navLogout: 'Kirjaudu ulos',
    navLogin: 'Kirjaudu',
    navSignup: 'Rekisteröidy',
    navBrowse: 'Selaa kohteita',
    navLanguage: 'Kieli',
    approvalsBadge: '{count}',
    heroEyebrow: 'lomavuokraus.fi',
    heroTitle: 'Löydä seuraava mökkilomasi',
    heroBody: 'Nopea, moderni vuokramökkipalvelu. Rakennettu Next.js App Routerilla ja valmiina Kubernetes-ympäristöön.',
    ctaViewSample: 'Katso esimerkkikohde',
    ctaHealth: 'Tarkista health-päätepiste',
    ctaBrowse: 'Selaa kohteita',
    highlightQualityTitle: 'Laadukkaat kohteet',
    highlightQualityBody: 'Kuratoidut mökit ja huvilat, selkeät saatavuudet ja helppo varaus.',
    highlightLocalTitle: 'Suomi edellä',
    highlightLocalBody: 'Tehty Suomen olosuhteisiin, nopea sisällönjakelu Pohjoismaissa.',
    highlightApiTitle: 'API-ystävällinen',
    highlightApiBody: 'Strukturoitu data, jotta löydät kohteet kaikissa kanavissa.',
    runtimeConfigTitle: 'Ajoaikainen konfiguraatio',
    runtimeConfigLead: 'Ajo- ja rakennusaikaiset arvot, joita palvelu käyttää.',
    runtimeAppEnv: 'APP_ENV',
    runtimeSiteUrl: 'NEXT_PUBLIC_SITE_URL',
    runtimeApiBase: 'NEXT_PUBLIC_API_BASE',
    aboutTitle: 'Tietoja lomavuokraus.fi:stä',
    aboutLead: 'Keskittynyt suomalainen loma-asuntopalvelu: nopea selaus, selkeä moderointi ja mutkaton kokemus vuokraajalle.',
    pricingTitle: 'Hinnasto',
    pricingLead: 'Selkeä hinnoittelu vuokraajille ilman yllätyksiä.',
    pricingMonthly: 'Kuukausi',
    pricingAnnual: 'Vuosimaksu',
    pricingPerMonth: 'kuukaudessa',
    pricingPerYear: 'vuodessa (20 % säästö)',
    pricingMonthlyBody: 'Aloita kuukausihinnalla 10 € per kohde.',
    pricingAnnualBody: 'Maksa vuodessa 100 € per kohde ja pidä kulut ennustettavina.',
    pricingPerListing: 'Hinta on per aktiivinen kohde. Voit perua milloin vain.',
    pricingNotesTitle: 'Huomiot',
    pricingNotesBody: 'Pidämme hinnoittelun yksinkertaisena samalla kun rakennamme uusia isäntätyökaluja, viestejä ja integraatioita. Kaikki nykyiset ominaisuudet sisältyvät.',
    footerAbout: 'Tietoa',
    footerPricing: 'Hinnasto',
    footerPrivacy: 'Tietosuoja ja evästeet',
    loginTitle: 'Kirjaudu sisään',
    emailLabel: 'Sähköposti',
    passwordLabel: 'Salasana',
    loginButton: 'Kirjaudu',
    loggingIn: 'Kirjaudutaan…',
    loginSuccess: 'Kirjautuminen onnistui.',
    registerTitle: 'Luo tili',
    registerLead: 'Sähköpostin varmistus vaaditaan, ja ylläpitäjä hyväksyy tilin.',
    nameOptional: 'Nimi (valinnainen)',
    passwordHint: 'Salasana (väh. 8 merkkiä)',
    registerButton: 'Rekisteröidy',
    registering: 'Lähetetään…',
    registerSuccess: 'Rekisteröinti onnistui. Tarkista sähköpostisi vahvistuslinkin vuoksi.',
    forgotTitle: 'Unohditko salasanasi?',
    forgotLead: 'Syötä sähköpostisi niin lähetämme palautuslinkin.',
    forgotSubmit: 'Lähetä palautuslinkki',
    forgotSuccess: 'Jos sähköposti löytyy, palautuslinkki on lähetetty.',
    forgotError: 'Linkin lähetys epäonnistui.',
    resetTitle: 'Vaihda salasana',
    resetLead: 'Aseta uusi salasana tilillesi.',
    resetSubmit: 'Aseta uusi salasana',
    resetSuccess: 'Salasana vaihdettu. Voit nyt kirjautua sisään.',
    resetError: 'Salasanan vaihto epäonnistui. Linkki voi olla vanhentunut.',
    resetMissingToken: 'Palautustunniste puuttuu. Käytä sähköpostista saatua linkkiä.',
    forgotCta: 'Unohdit salasanan?',
    pendingAdminTitle: 'Ylläpito: tarkastettavat',
    pendingUsersTitle: 'Odottavat käyttäjät',
    pendingListingsTitle: 'Odottavat kohteet',
    noPendingUsers: 'Ei odottavia käyttäjiä.',
    noPendingListings: 'Ei odottavia kohteita.',
    statusLabel: 'tila',
    slugsLabel: 'Osoitepolut',
    verifiedLabel: 'vahvistettu',
    approve: 'Hyväksy',
    approveAdmin: 'Hyväksy + admin',
    reject: 'Hylkää',
    remove: 'Poista käytöstä',
    publish: 'Julkaise',
    approvalsMessage: 'Kohde päivitetty',
    userUpdated: 'Käyttäjä päivitetty',
    adminRequired: 'Ylläpitäjän oikeudet vaaditaan',
    adminUsersTitle: 'Ylläpito: käyttäjät',
    adminUsersLead: 'Hallinnoi rooleja ja hyväksyntöjä.',
    tableEmail: 'Sähköposti',
    tableRole: 'Rooli',
    tableStatus: 'Tila',
    tableVerified: 'Vahvistettu',
    tableApproved: 'Hyväksytty',
    myListingsTitle: 'Omat kohteet',
    createNewListing: 'Luo uusi kohde',
    noListings: 'Ei kohteita vielä.',
    createOne: 'Luo kohde',
    loading: 'Ladataan…',
    view: 'Näytä',
    removing: 'Poistetaan…',
    removed: 'Kohde poistettu näkyvistä',
    removeConfirm: 'Poista kohde? Se piilotetaan muilta.',
    myProfileTitle: 'Oma profiili',
    notLoggedIn: 'Et ole kirjautunut',
    profileEmail: 'Sähköposti',
    profileName: 'Nimi',
    profilePhone: 'Puhelin',
    profileRole: 'Rooli',
    profileStatus: 'Tila',
    profileEmailVerified: 'Sähköposti vahvistettu',
    profileApproved: 'Hyväksytty',
    profileUpdated: 'Profiili päivitetty',
    emailLocked: 'Sähköpostia ei voi vaihtaa',
    save: 'Tallenna',
    saving: 'Tallennetaan…',
    yes: 'kyllä',
    no: 'ei',
    verifyTitle: 'Sähköpostin vahvistus',
    verifyOk: 'Sähköposti vahvistettu. Ylläpitäjä hyväksyy tilin pian.',
    verifyFail: 'Vahvistus epäonnistui tai token on virheellinen.',
    listingLocation: 'Sijainti',
    listingAddress: 'Osoite',
    listingCapacity: 'Tilat',
    listingAmenities: 'Varustelu',
    listingNoAmenities: 'Varustelua ei ole listattu.',
    listingContact: 'Yhteystiedot',
    listingMoreInfo: 'Lisätietoja',
    availabilityTitle: 'Saatavuuskalenteri',
    availabilityLegendBooked: 'Varattu',
    availabilityMissing: 'Kalenteria ei ole vielä yhdistetty.',
    localeLabel: 'Kieli',
    homeCrumb: 'Etusivu',
    createListingTitle: 'Luo kohde',
    loginToCreate: 'Kirjaudu ensin luodaksesi kohteen.',
    slugLabel: 'Osoitepolku',
    localeInput: 'Kieli',
    titleLabel: 'Otsikko',
    descriptionLabel: 'Kuvaus',
    teaserLabel: 'Tiivistelmä',
    countryLabel: 'Maa',
    regionLabel: 'Maakunta/alue',
    cityLabel: 'Kunta/kaupunki',
    contactNameLabel: 'Yhteyshenkilö',
    contactEmailLabel: 'Yhteyssähköposti',
    streetAddressLabel: 'Katuosoite',
    addressNoteLabel: 'Saapumisohje (valinnainen)',
    addressNotePlaceholder: 'Reittiohje, pysäköinti tai muut saapumisohjeet',
    latitudeLabel: 'Leveysaste (valinnainen)',
    longitudeLabel: 'Pituusaste (valinnainen)',
    maxGuestsLabel: 'Vieraita enintään',
    bedroomsLabel: 'Makuuhuoneita',
    bedsLabel: 'Vuoteita',
    bathroomsLabel: 'Kylpyhuoneita',
    priceHintLabel: 'Hinta-arvio (€ / yö)',
    priceHintHelp: 'Suuntaa-antava hinta euroina per yö (ei sitova).',
    calendarUrlsLabel: 'Saatavuuskalenterit (iCal-osoitteet, yksi per rivi)',
    calendarUrlsHelp: 'Liitä iCal-linkit muilta alustoilta. Yhdistämme ne saatavuuden näyttämiseen.',
    imagesLabel: 'Kuvat',
    imagesHelp: 'Lataa enintään {count} kuvaa (max {sizeMb} Mt / kuva).',
    imagesTooMany: 'Liikaa kuvia (enintään {count}).',
    imagesTooLarge: 'Kuva on liian suuri (max {sizeMb} Mt).',
    imagesReadFailed: 'Kuvien luku epäonnistui.',
    imagesRequired: 'Lataa vähintään yksi kuva.',
    coverImageLabel: 'Kansikuvan järjestys',
    coverImageHelp: 'Monettako ladatuista kuvista käytetään kansikuvana (oletus 1)',
    coverChoice: 'Kansipaikka {index}',
    submitListing: 'Luo kohde',
    submittingListing: 'Lähetetään…',
    createListingSuccess: 'Kohde luotu id:llä {id} (tila: {status})',
    approvalsCountLabel: 'Tarkastettavat',
    approvalsPending: '{count} odottaa',
    amenitySauna: 'Sauna',
    amenityFireplace: 'Takka',
    amenityWifi: 'Wi-Fi',
    amenityPets: 'Lemmikit sallittu',
    amenityLake: 'Järven rannalla',
    amenityAirConditioning: 'Ilmastointi',
    amenityKitchen: 'Keittiö',
    amenityDishwasher: 'Astianpesukone',
    amenityWashingMachine: 'Pyykinpesukone',
    amenityBarbecue: 'Grilli',
    amenityEvFree: 'Sähköauton lataus (ilmainen)',
    amenityEvPaid: 'Sähköauton lataus (maksullinen)',
    evChargingLabel: 'Sähköauton lataus',
    evChargingNone: 'Ei saatavilla',
    evChargingFree: 'Ilmainen asiakkaille',
    evChargingPaid: 'Maksullinen',
    capacityGuests: '{count} vierasta',
    capacityBedrooms: '{count} makuuhuonetta',
    capacityBeds: '{count} vuodetta',
    capacityBathrooms: '{count} kylpyhuonetta',
    browseListingsTitle: 'Selaa kohteita',
    browseListingsLead: 'Hae julkaistuja kohteita, rajaa sijainnilla ja tutki kartalla.',
    sampleBadge: 'Mallikohde',
    privacyTitle: 'Tietosuoja ja evästeet',
    privacyUpdated: 'Päivitetty: {date}',
    privacyCollectTitle: 'Mitä tietoja keräämme',
    privacyCollectAccounts: 'Käyttäjätiedot: sähköposti, salasanatiiviste, nimi, puhelin (valinnainen), rooli/tila.',
    privacyCollectListings: 'Kohdetiedot: sijainti, yhteystiedot, varustelu, kuvat, kieliversiot.',
    privacyCollectLogs: 'Lokit: rajattu pyyntömeta diagnostiikkaan.',
    privacyUseTitle: 'Miten käytämme tietoja',
    privacyUseAuth: 'Kirjautumiseen ja sessioiden hallintaan.',
    privacyUseListings: 'Kohteiden julkaisuun ja moderointiin.',
    privacyUseMail: 'Transaktio­sähköposteihin (vahvistus, salasanan palautus).',
    privacyUseLegal: 'Lakivelvoitteiden täyttämiseen ja palvelun suojaamiseen.',
    privacyStoreTitle: 'Säilytys',
    privacyStoreDb: 'Tiedot tallennetaan EU:ssa olevaan Postgres-tietokantaan.',
    privacyStoreBackups: 'Varmuuskopioita säilytetään palautusta varten; poistetut tiedot voivat esiintyä varmuuskopioissa rajatun ajan.',
    privacyCookiesTitle: 'Evästeet',
    privacyCookiesSession: 'Käytämme vain välttämättömiä evästeitä: kirjautumissessio.',
    privacyCookiesNoTracking: 'Ei analytiikka-, mainos- tai seurantateknologioita.',
    privacySharingTitle: 'Tietojen jakaminen',
    privacySharingAds: 'Emme myy tai jaa henkilötietoja mainostajille.',
    privacySharingOps: 'Palveluntarjoajille vain palvelun pyörittämiseen (sähköposti, hosting).',
    privacyRightsTitle: 'Oikeutesi',
    privacyRightsAccess: 'Voit pyytää tietojen nähtävyyttä, oikaisua tai poistoa.',
    privacyRightsConsent: 'Voit perua suostumuksen ei-välttämättömästä käsittelystä (tällä hetkellä vain välttämättömät).',
    privacyRightsContact: 'Ota yhteyttä, jos sinulla on kysyttävää tietosuojasta.',
    searchLabel: 'Haku',
    searchPlaceholder: 'Hae nimellä, kuvauksella tai paikkakunnalla',
    cityFilter: 'Kaupunki/kunta',
    regionFilter: 'Maakunta/alue',
    searchButton: 'Hae',
    searchAmenities: 'Varustelu',
    searchAvailability: 'Saatavuus',
    startDate: 'Alkupäivä',
    endDate: 'Loppupäivä',
    availabilityOnlyWithCalendar: 'Päiväsuodatus näyttää vain kohteet, joissa on kalenteri yhdistettynä.',
    availableForDates: 'Vapaa valituille päiville',
    notAvailableForDates: 'Ei vapaana valituille päiville',
    calendarConnected: 'Kalenteri yhdistetty',
    clearFilters: 'Tyhjennä suodattimet',
    addressSearchLabel: 'Etsi kohteita osoitteen läheltä',
    addressSearchPlaceholder: 'Katu, kaupunki tai paikka',
    locateAddress: 'Paikanna kartalle',
    addressRadiusLabel: '{km} km säteellä',
    listingsFound: '{count} kohdetta',
    openListing: 'Avaa kohde',
    mapNoResults: 'Suodattimilla ei löytynyt kohteita.',
    evChargingAny: 'Kaikki',
    addressNotFound: 'Osoitetta ei löydy',
    addressLookupFailed: 'Paikannus epäonnistui',
    loadingMap: 'Ladataan karttaa…',
    latestListingsTitle: 'Viimeisimmät kohteet',
    latestListingsLead: 'Tuoreimmat kohteet heti julkaisun jälkeen.',
  },
} as const;

export const messages = allMessages;
export type MessageKey = keyof typeof allMessages.en;

function normalizeLocale(input?: string | null): Locale | null {
  if (!input) return null;
  const lower = input.toLowerCase();
  if (lower.startsWith('fi')) return 'fi';
  if (lower.startsWith('en')) return 'en';
  return null;
}

export function resolveLocale(opts: { cookieLocale?: string | null; acceptLanguage?: string | null }): Locale {
  const fromCookie = normalizeLocale(opts.cookieLocale);
  if (fromCookie) return fromCookie;
  const fromHeader = normalizeLocale(opts.acceptLanguage);
  if (fromHeader) return fromHeader;
  return 'en';
}

export function t(locale: Locale, key: MessageKey, vars?: Record<string, string | number>) {
  const table = messages[locale] ?? messages.en;
  const template = String(table[key] ?? messages.en[key]);
  if (!vars) return template;
  return Object.entries(vars).reduce<string>((acc, [k, v]) => acc.replace(`{${k}}`, String(v)), template);
}
