diff --git a/frontend/messages/en.json b/frontend/messages/en.json new file mode 100644 index 0000000..a57eba2 --- /dev/null +++ b/frontend/messages/en.json @@ -0,0 +1,437 @@ +{ + "nav_dashboard": "Dashboard", + "nav_products": "Products", + "nav_routines": "Routines", + "nav_grooming": "Grooming", + "nav_medications": "Medications", + "nav_labResults": "Lab Results", + "nav_skin": "Skin", + "nav_appName": "innercontext", + "nav_appSubtitle": "personal health & skincare", + + "common_save": "Save", + "common_cancel": "Cancel", + "common_add": "Add", + "common_edit": "Edit", + "common_delete": "Delete", + "common_saved": "Saved.", + "common_select": "Select", + "common_unknown": "Unknown", + "common_yes": "Yes", + "common_no": "No", + "common_unknown_value": "Unknown", + "common_optional_notes": "optional", + "common_steps": "steps", + + "dashboard_title": "Dashboard", + "dashboard_subtitle": "Your recent health & skincare overview", + "dashboard_latestSnapshot": "Latest Skin Snapshot", + "dashboard_recentRoutines": "Recent Routines", + "dashboard_noSnapshots": "No skin snapshots yet.", + "dashboard_noRoutines": "No routines in the past 2 weeks.", + + "products_title": "Products", + "products_count": "{count} products", + "products_addNew": "+ Add product", + "products_noProducts": "No products found.", + "products_filterAll": "All", + "products_filterOwned": "Owned", + "products_filterUnowned": "Not owned", + "products_colName": "Name", + "products_colBrand": "Brand", + "products_colTargets": "Targets", + "products_colTime": "Time", + "products_newTitle": "New Product", + "products_backToList": "← Products", + "products_createProduct": "Create product", + "products_saveChanges": "Save changes", + "products_deleteProduct": "Delete product", + "products_confirmDelete": "Delete this product?", + "products_noInventory": "No inventory packages.", + + "inventory_title": "Inventory packages ({count})", + "inventory_addPackage": "+ Add package", + "inventory_packageAdded": "Package added.", + "inventory_packageUpdated": "Package updated.", + "inventory_packageDeleted": "Package deleted.", + "inventory_alreadyOpened": "Already opened", + "inventory_openedDate": "Opened date", + "inventory_finishedDate": "Finished date", + "inventory_expiryDate": "Expiry date", + "inventory_currentWeight": "Current weight (g)", + "inventory_lastWeighed": "Last weighed", + "inventory_notes": "Notes", + "inventory_badgeOpen": "Open", + "inventory_badgeSealed": "Sealed", + "inventory_badgeFinished": "Finished", + "inventory_exp": "Exp:", + "inventory_opened": "Opened:", + "inventory_finished": "Finished:", + "inventory_remaining": "g remaining", + "inventory_weighed": "Weighed:", + "inventory_confirmDelete": "Delete this package?", + + "routines_title": "Routines", + "routines_count": "{count} routines (last 30 days)", + "routines_suggestAI": "Suggest AI routine", + "routines_addNew": "+ New routine", + "routines_noRoutines": "No routines found.", + "routines_newTitle": "New Routine", + "routines_backToList": "← Routines", + "routines_detailsTitle": "Routine details", + "routines_date": "Date *", + "routines_amOrPm": "AM or PM *", + "routines_notes": "Notes", + "routines_notesPlaceholder": "Optional notes", + "routines_createRoutine": "Create routine", + "routines_deleteRoutine": "Delete routine", + "routines_confirmDelete": "Delete this routine?", + "routines_steps": "Steps ({count})", + "routines_addStep": "+ Add step", + "routines_addStepTitle": "Add step", + "routines_product": "Product", + "routines_selectProduct": "Select product", + "routines_dose": "Dose", + "routines_dosePlaceholder": "e.g. 2 pumps", + "routines_region": "Region", + "routines_regionPlaceholder": "e.g. face", + "routines_addStepBtn": "Add step", + "routines_unknownStep": "Unknown step", + "routines_noSteps": "No steps yet.", + + "grooming_title": "Grooming Schedule", + "grooming_backToRoutines": "← Routines", + "grooming_addEntry": "+ Add entry", + "grooming_entryAdded": "Entry added.", + "grooming_entryUpdated": "Entry updated.", + "grooming_entryDeleted": "Entry deleted.", + "grooming_dayOfWeek": "Day of week", + "grooming_action": "Action", + "grooming_notesOptional": "Notes (optional)", + "grooming_notesPlaceholder": "e.g. every 2 weeks", + "grooming_noEntries": "No entries yet. Click \"+ Add entry\" to get started.", + "grooming_confirmDelete": "Delete this entry?", + "grooming_actionShavingRazor": "Razor shaving", + "grooming_actionShavingOneblade": "OneBlade shaving", + "grooming_actionDermarolling": "Dermarolling", + "grooming_dayMonday": "Monday", + "grooming_dayTuesday": "Tuesday", + "grooming_dayWednesday": "Wednesday", + "grooming_dayThursday": "Thursday", + "grooming_dayFriday": "Friday", + "grooming_daySaturday": "Saturday", + "grooming_daySunday": "Sunday", + + "suggest_title": "AI Routine Suggestion", + "suggest_backToRoutines": "← Routines", + "suggest_singleTab": "Single routine", + "suggest_batchTab": "Batch / Vacation", + "suggest_singleParams": "Parameters", + "suggest_date": "Date", + "suggest_timeOfDay": "Time of day", + "suggest_contextLabel": "Additional context for AI", + "suggest_contextOptional": "(optional)", + "suggest_contextPlaceholder": "e.g. party night, focusing on hydration...", + "suggest_generateBtn": "Generate suggestion", + "suggest_generating": "Generating…", + "suggest_proposalTitle": "Suggestion", + "suggest_saveRoutine": "Save routine", + "suggest_saving": "Saving…", + "suggest_regenerate": "Regenerate", + "suggest_batchRange": "Date range", + "suggest_fromDate": "From", + "suggest_toDate": "To (max 14 days)", + "suggest_batchContextLabel": "Context / trip purpose", + "suggest_batchContextPlaceholder": "e.g. sunny trip to Italy, active mountain vacation...", + "suggest_generatePlan": "Generate plan", + "suggest_generatingPlan": "Generating plan…", + "suggest_planTitle": "Plan ({count} days)", + "suggest_saveAllRoutines": "Save all routines", + "suggest_amSteps": "steps", + "suggest_pmSteps": "steps", + "suggest_noAmSteps": "No AM steps.", + "suggest_noPmSteps": "No PM steps.", + "suggest_errorDefault": "Error generating suggestion.", + "suggest_errorBatch": "Error generating plan.", + "suggest_errorSave": "Error saving.", + "suggest_amMorning": "AM (morning)", + "suggest_pmEvening": "PM (evening)", + + "medications_title": "Medications", + "medications_count": "{count} entries", + "medications_addNew": "+ Add medication", + "medications_newTitle": "New medication", + "medications_kind": "Kind", + "medications_productName": "Product name *", + "medications_productNamePlaceholder": "e.g. Vitamin D3", + "medications_activeSubstance": "Active substance", + "medications_activeSubstancePlaceholder": "e.g. cholecalciferol", + "medications_notes": "Notes", + "medications_added": "Medication added.", + "medications_usages": "{count} usages", + "medications_noMedications": "No medications recorded.", + "medications_kindPrescription": "Prescription", + "medications_kindOtc": "OTC", + "medications_kindSupplement": "Supplement", + "medications_kindHerbal": "Herbal", + "medications_kindOther": "Other", + + "labResults_title": "Lab Results", + "labResults_count": "{count} results", + "labResults_addNew": "+ Add result", + "labResults_newTitle": "New lab result", + "labResults_flagFilter": "Flag:", + "labResults_flagAll": "All", + "labResults_flagNone": "None", + "labResults_date": "Date *", + "labResults_loincCode": "LOINC code *", + "labResults_testName": "Test name", + "labResults_testNamePlaceholder": "e.g. Hemoglobin", + "labResults_lab": "Lab", + "labResults_labPlaceholder": "e.g. LabCorp", + "labResults_value": "Value", + "labResults_unit": "Unit", + "labResults_unitPlaceholder": "e.g. g/dL", + "labResults_flag": "Flag", + "labResults_added": "Result added.", + "labResults_colDate": "Date", + "labResults_colTest": "Test", + "labResults_colLoinc": "LOINC", + "labResults_colValue": "Value", + "labResults_colFlag": "Flag", + "labResults_colLab": "Lab", + "labResults_noResults": "No lab results found.", + + "skin_title": "Skin Snapshots", + "skin_count": "{count} snapshots", + "skin_addNew": "+ Add snapshot", + "skin_aiAnalysisTitle": "AI analysis from photos", + "skin_aiUploadText": "Upload 1–3 photos of your skin. AI will pre-fill the form fields below.", + "skin_analyzePhotos": "Analyze photos", + "skin_analyzing": "Analyzing…", + "skin_newSnapshotTitle": "New skin snapshot", + "skin_date": "Date *", + "skin_overallState": "Overall state", + "skin_texture": "Texture", + "skin_skinType": "Skin type", + "skin_barrierState": "Barrier state", + "skin_hydration": "Hydration (1–5)", + "skin_sensitivity": "Sensitivity (1–5)", + "skin_sebumTzone": "Sebum T-zone (1–5)", + "skin_sebumCheeks": "Sebum cheeks (1–5)", + "skin_activeConcerns": "Active concerns (comma-separated)", + "skin_activeConcernsPlaceholder": "acne, redness, dehydration", + "skin_notes": "Notes", + "skin_addSnapshot": "Add snapshot", + "skin_snapshotAdded": "Snapshot added.", + "skin_snapshotUpdated": "Snapshot updated.", + "skin_snapshotDeleted": "Snapshot deleted.", + "skin_noSnapshots": "No skin snapshots yet.", + "skin_hydrationLabel": "Hydration", + "skin_sensitivityLabel": "Sensitivity", + "skin_barrierLabel": "Barrier", + "skin_stateExcellent": "excellent", + "skin_stateGood": "good", + "skin_stateFair": "fair", + "skin_statePoor": "poor", + "skin_textureSmooth": "smooth", + "skin_textureRough": "rough", + "skin_textureFlaky": "flaky", + "skin_textureBumpy": "bumpy", + "skin_barrierIntact": "intact", + "skin_barrierMildly": "mildly compromised", + "skin_barrierCompromised": "compromised", + "skin_typeDry": "dry", + "skin_typeOily": "oily", + "skin_typeCombination": "combination", + "skin_typeSensitive": "sensitive", + "skin_typeNormal": "normal", + "skin_typeAcneProne": "acne prone", + + "productForm_aiPrefill": "AI pre-fill", + "productForm_aiPrefillText": "Paste product description from a website, ingredient list, or other text. AI will fill in available fields — you can review and correct before saving.", + "productForm_pasteText": "Paste product description, INCI ingredients here...", + "productForm_parseWithAI": "Fill fields (AI)", + "productForm_parsing": "Processing…", + "productForm_basicInfo": "Basic info", + "productForm_name": "Name *", + "productForm_namePlaceholder": "e.g. Hydro Boost Water Gel", + "productForm_brand": "Brand *", + "productForm_brandPlaceholder": "e.g. Neutrogena", + "productForm_lineName": "Line / series", + "productForm_lineNamePlaceholder": "e.g. Hydro Boost", + "productForm_url": "URL", + "productForm_sku": "SKU", + "productForm_skuPlaceholder": "e.g. NTR-HB-50", + "productForm_barcode": "Barcode / EAN", + "productForm_barcodePlaceholder": "e.g. 3614273258975", + "productForm_classification": "Classification", + "productForm_category": "Category *", + "productForm_selectCategory": "Select category", + "productForm_time": "Time *", + "productForm_timeOptions": "AM / PM / Both", + "productForm_timeBoth": "Both", + "productForm_leaveOn": "Leave-on *", + "productForm_leaveOnYes": "Yes (leave-on)", + "productForm_leaveOnNo": "No (rinse-off)", + "productForm_texture": "Texture", + "productForm_selectTexture": "Select texture", + "productForm_absorptionSpeed": "Absorption speed", + "productForm_selectSpeed": "Select speed", + "productForm_skinProfile": "Skin profile", + "productForm_recommendedFor": "Recommended for skin types", + "productForm_targetConcerns": "Target concerns", + "productForm_contraindications": "Contraindications (one per line)", + "productForm_contraindicationsPlaceholder": "e.g. active rosacea flares", + "productForm_ingredients": "Ingredients", + "productForm_inciList": "INCI list (one ingredient per line)", + "productForm_activeIngredients": "Active ingredients", + "productForm_addActive": "+ Add active", + "productForm_noActives": "No actives added yet.", + "productForm_activeName": "Name", + "productForm_activePercent": "%", + "productForm_activeStrength": "Strength", + "productForm_activeIrritation": "Irritation", + "productForm_activeFunctions": "Functions", + "productForm_effectProfile": "Effect profile (0–5)", + "productForm_interactions": "Interactions", + "productForm_synergizesWith": "Synergizes with (one per line)", + "productForm_incompatibleWith": "Incompatible with", + "productForm_addIncompatibility": "+ Add incompatibility", + "productForm_noIncompatibilities": "No incompatibilities added.", + "productForm_incompTarget": "Target ingredient", + "productForm_incompScope": "Scope", + "productForm_incompReason": "Reason (optional)", + "productForm_incompReasonPlaceholder": "e.g. reduces efficacy", + "productForm_incompScopeSelect": "Select…", + "productForm_contextRules": "Context rules", + "productForm_ctxAfterShaving": "Safe after shaving", + "productForm_ctxAfterAcids": "Safe after acids", + "productForm_ctxAfterRetinoids": "Safe after retinoids", + "productForm_ctxCompromisedBarrier": "Safe with compromised barrier", + "productForm_ctxLowUvOnly": "Low UV only (evening/covered)", + "productForm_productDetails": "Product details", + "productForm_priceTier": "Price tier", + "productForm_selectTier": "Select tier", + "productForm_sizeMl": "Size (ml)", + "productForm_fullWeightG": "Full weight (g)", + "productForm_emptyWeightG": "Empty weight (g)", + "productForm_paoMonths": "PAO (months)", + "productForm_phMin": "pH min", + "productForm_phMax": "pH max", + "productForm_usageNotes": "Usage notes", + "productForm_usageNotesPlaceholder": "e.g. Apply to damp skin, avoid eye area", + "productForm_safetyFlags": "Safety flags", + "productForm_fragranceFree": "Fragrance-free", + "productForm_essentialOilsFree": "Essential oils-free", + "productForm_alcoholDenatFree": "Alcohol denat-free", + "productForm_pregnancySafe": "Pregnancy safe", + "productForm_usageConstraints": "Usage constraints", + "productForm_minIntervalHours": "Min interval (hours)", + "productForm_maxFrequencyPerWeek": "Max uses per week", + "productForm_isMedication": "Is medication", + "productForm_isTool": "Is tool (e.g. dermaroller)", + "productForm_needleLengthMm": "Needle length (mm, tools only)", + "productForm_personalNotes": "Personal notes", + "productForm_repurchaseIntent": "Repurchase intent", + "productForm_toleranceNotes": "Tolerance notes", + "productForm_toleranceNotesPlaceholder": "e.g. Causes mild stinging, fine after 2 weeks", + + "productForm_categoryCleanser": "Cleanser", + "productForm_categoryToner": "Toner", + "productForm_categoryEssence": "Essence", + "productForm_categorySerum": "Serum", + "productForm_categoryMoisturizer": "Moisturizer", + "productForm_categorySpf": "SPF", + "productForm_categoryMask": "Mask", + "productForm_categoryExfoliant": "Exfoliant", + "productForm_categoryHairTreatment": "Hair treatment", + "productForm_categoryTool": "Tool", + "productForm_categorySpotTreatment": "Spot treatment", + "productForm_categoryOil": "Oil", + + "productForm_textureWatery": "Watery", + "productForm_textureGel": "Gel", + "productForm_textureEmulsion": "Emulsion", + "productForm_textureCream": "Cream", + "productForm_textureOil": "Oil", + "productForm_textureBalm": "Balm", + "productForm_textureFoam": "Foam", + "productForm_textureFluid": "Fluid", + + "productForm_absorptionVeryFast": "Very fast", + "productForm_absorptionFast": "Fast", + "productForm_absorptionModerate": "Moderate", + "productForm_absorptionSlow": "Slow", + "productForm_absorptionVerySlow": "Very slow", + + "productForm_priceBudget": "Budget", + "productForm_priceMid": "Mid", + "productForm_pricePremium": "Premium", + "productForm_priceLuxury": "Luxury", + + "productForm_skinTypeDry": "dry", + "productForm_skinTypeOily": "oily", + "productForm_skinTypeCombination": "combination", + "productForm_skinTypeSensitive": "sensitive", + "productForm_skinTypeNormal": "normal", + "productForm_skinTypeAcneProne": "acne prone", + + "productForm_concernAcne": "acne", + "productForm_concernRosacea": "rosacea", + "productForm_concernHyperpigmentation": "hyperpigmentation", + "productForm_concernAging": "aging", + "productForm_concernDehydration": "dehydration", + "productForm_concernRedness": "redness", + "productForm_concernDamagedBarrier": "damaged barrier", + "productForm_concernPoreVisibility": "pore visibility", + "productForm_concernUnevenTexture": "uneven texture", + "productForm_concernHairGrowth": "hair growth", + "productForm_concernSebumExcess": "sebum excess", + + "productForm_fnHumectant": "humectant", + "productForm_fnEmollient": "emollient", + "productForm_fnOcclusive": "occlusive", + "productForm_fnExfoliantAha": "AHA exfoliant", + "productForm_fnExfoliantBha": "BHA exfoliant", + "productForm_fnExfoliantPha": "PHA exfoliant", + "productForm_fnRetinoid": "retinoid", + "productForm_fnAntioxidant": "antioxidant", + "productForm_fnSoothing": "soothing", + "productForm_fnBarrierSupport": "barrier support", + "productForm_fnBrightening": "brightening", + "productForm_fnAntiAcne": "anti-acne", + "productForm_fnCeramide": "ceramide", + "productForm_fnNiacinamide": "niacinamide", + "productForm_fnSunscreen": "sunscreen", + "productForm_fnPeptide": "peptide", + "productForm_fnHairGrowth": "hair growth stimulant", + "productForm_fnPrebiotic": "prebiotic", + "productForm_fnVitaminC": "vitamin C", + "productForm_fnAntiAging": "anti-aging", + + "productForm_scopeSameStep": "same step", + "productForm_scopeSameDay": "same day", + "productForm_scopeSamePeriod": "same period", + + "productForm_strengthLow": "1 Low", + "productForm_strengthMedium": "2 Medium", + "productForm_strengthHigh": "3 High", + + "productForm_effectHydrationImmediate": "Hydration (immediate)", + "productForm_effectHydrationLongTerm": "Hydration (long term)", + "productForm_effectBarrierRepair": "Barrier repair", + "productForm_effectSoothing": "Soothing", + "productForm_effectExfoliation": "Exfoliation", + "productForm_effectRetinoid": "Retinoid activity", + "productForm_effectIrritation": "Irritation risk", + "productForm_effectComedogenic": "Comedogenic risk", + "productForm_effectBarrierDisruption": "Barrier disruption risk", + "productForm_effectDryness": "Dryness risk", + "productForm_effectBrightening": "Brightening", + "productForm_effectAntiAcne": "Anti-acne", + "productForm_effectAntiAging": "Anti-aging", + + "lang_pl": "PL", + "lang_en": "EN" +} diff --git a/frontend/messages/pl.json b/frontend/messages/pl.json new file mode 100644 index 0000000..ba11dfb --- /dev/null +++ b/frontend/messages/pl.json @@ -0,0 +1,437 @@ +{ + "nav_dashboard": "Dashboard", + "nav_products": "Produkty", + "nav_routines": "Rutyny", + "nav_grooming": "Pielęgnacja", + "nav_medications": "Leki", + "nav_labResults": "Wyniki badań", + "nav_skin": "Skóra", + "nav_appName": "innercontext", + "nav_appSubtitle": "zdrowie & pielęgnacja", + + "common_save": "Zapisz", + "common_cancel": "Anuluj", + "common_add": "Dodaj", + "common_edit": "Edytuj", + "common_delete": "Usuń", + "common_saved": "Zapisano.", + "common_select": "Wybierz", + "common_unknown": "Nieznane", + "common_yes": "Tak", + "common_no": "Nie", + "common_unknown_value": "Nieznane", + "common_optional_notes": "opcjonalnie", + "common_steps": "kroków", + + "dashboard_title": "Dashboard", + "dashboard_subtitle": "Przegląd zdrowia i pielęgnacji", + "dashboard_latestSnapshot": "Ostatni stan skóry", + "dashboard_recentRoutines": "Ostatnie rutyny", + "dashboard_noSnapshots": "Brak wpisów o stanie skóry.", + "dashboard_noRoutines": "Brak rutyno w ciągu ostatnich 2 tygodni.", + + "products_title": "Produkty", + "products_count": "{count} produktów", + "products_addNew": "+ Dodaj produkt", + "products_noProducts": "Nie znaleziono produktów.", + "products_filterAll": "Wszystkie", + "products_filterOwned": "Posiadane", + "products_filterUnowned": "Nieposiadane", + "products_colName": "Nazwa", + "products_colBrand": "Marka", + "products_colTargets": "Cele", + "products_colTime": "Pora", + "products_newTitle": "Nowy produkt", + "products_backToList": "← Produkty", + "products_createProduct": "Utwórz produkt", + "products_saveChanges": "Zapisz zmiany", + "products_deleteProduct": "Usuń produkt", + "products_confirmDelete": "Usunąć ten produkt?", + "products_noInventory": "Brak opakowań w magazynie.", + + "inventory_title": "Opakowania ({count})", + "inventory_addPackage": "+ Dodaj opakowanie", + "inventory_packageAdded": "Opakowanie dodane.", + "inventory_packageUpdated": "Opakowanie zaktualizowane.", + "inventory_packageDeleted": "Opakowanie usunięte.", + "inventory_alreadyOpened": "Już otwarte", + "inventory_openedDate": "Data otwarcia", + "inventory_finishedDate": "Data skończenia", + "inventory_expiryDate": "Data ważności", + "inventory_currentWeight": "Aktualna waga (g)", + "inventory_lastWeighed": "Ostatnie ważenie", + "inventory_notes": "Notatki", + "inventory_badgeOpen": "Otwarte", + "inventory_badgeSealed": "Zamknięte", + "inventory_badgeFinished": "Skończone", + "inventory_exp": "Wazność:", + "inventory_opened": "Otwarto:", + "inventory_finished": "Skończono:", + "inventory_remaining": "g pozostało", + "inventory_weighed": "Ważono:", + "inventory_confirmDelete": "Usunąć to opakowanie?", + + "routines_title": "Rutyny", + "routines_count": "{count} rutyno (ostatnie 30 dni)", + "routines_suggestAI": "Zaproponuj rutynę AI", + "routines_addNew": "+ Nowa rutyna", + "routines_noRoutines": "Nie znaleziono rutyno.", + "routines_newTitle": "Nowa rutyna", + "routines_backToList": "← Rutyny", + "routines_detailsTitle": "Szczegóły rutyny", + "routines_date": "Data *", + "routines_amOrPm": "AM lub PM *", + "routines_notes": "Notatki", + "routines_notesPlaceholder": "Opcjonalne notatki", + "routines_createRoutine": "Utwórz rutynę", + "routines_deleteRoutine": "Usuń rutynę", + "routines_confirmDelete": "Usunąć tę rutynę?", + "routines_steps": "Kroki ({count})", + "routines_addStep": "+ Dodaj krok", + "routines_addStepTitle": "Dodaj krok", + "routines_product": "Produkt", + "routines_selectProduct": "Wybierz produkt", + "routines_dose": "Dawka", + "routines_dosePlaceholder": "np. 2 pompki", + "routines_region": "Okolica", + "routines_regionPlaceholder": "np. twarz", + "routines_addStepBtn": "Dodaj krok", + "routines_unknownStep": "Nieznany krok", + "routines_noSteps": "Brak kroków.", + + "grooming_title": "Harmonogram pielęgnacji", + "grooming_backToRoutines": "← Rutyny", + "grooming_addEntry": "+ Dodaj wpis", + "grooming_entryAdded": "Wpis dodany.", + "grooming_entryUpdated": "Wpis zaktualizowany.", + "grooming_entryDeleted": "Wpis usunięty.", + "grooming_dayOfWeek": "Dzień tygodnia", + "grooming_action": "Czynność", + "grooming_notesOptional": "Notatki (opcjonalnie)", + "grooming_notesPlaceholder": "np. co 2 tygodnie", + "grooming_noEntries": "Brak wpisów. Kliknij \"+ Dodaj wpis\", aby zacząć.", + "grooming_confirmDelete": "Usunąć ten wpis?", + "grooming_actionShavingRazor": "Golenie maszynką", + "grooming_actionShavingOneblade": "Golenie OneBlade", + "grooming_actionDermarolling": "Dermarolling", + "grooming_dayMonday": "Poniedziałek", + "grooming_dayTuesday": "Wtorek", + "grooming_dayWednesday": "Środa", + "grooming_dayThursday": "Czwartek", + "grooming_dayFriday": "Piątek", + "grooming_daySaturday": "Sobota", + "grooming_daySunday": "Niedziela", + + "suggest_title": "Propozycja rutyny AI", + "suggest_backToRoutines": "← Rutyny", + "suggest_singleTab": "Jedna rutyna", + "suggest_batchTab": "Batch / Urlop", + "suggest_singleParams": "Parametry", + "suggest_date": "Data", + "suggest_timeOfDay": "Pora dnia", + "suggest_contextLabel": "Dodatkowy kontekst dla AI", + "suggest_contextOptional": "(opcjonalny)", + "suggest_contextPlaceholder": "np. wieczór imprezowy, skupiam się na nawilżeniu...", + "suggest_generateBtn": "Generuj propozycję", + "suggest_generating": "Generuję…", + "suggest_proposalTitle": "Propozycja", + "suggest_saveRoutine": "Zapisz rutynę", + "suggest_saving": "Zapisuję…", + "suggest_regenerate": "Wygeneruj ponownie", + "suggest_batchRange": "Zakres dat", + "suggest_fromDate": "Od", + "suggest_toDate": "Do (max 14 dni)", + "suggest_batchContextLabel": "Kontekst / cel wyjazdu", + "suggest_batchContextPlaceholder": "np. słoneczna podróż do Włoch, aktywny urlop górski...", + "suggest_generatePlan": "Generuj plan", + "suggest_generatingPlan": "Generuję plan…", + "suggest_planTitle": "Plan ({count} dni)", + "suggest_saveAllRoutines": "Zapisz wszystkie rutyny", + "suggest_amSteps": "kroków", + "suggest_pmSteps": "kroków", + "suggest_noAmSteps": "Brak kroków AM.", + "suggest_noPmSteps": "Brak kroków PM.", + "suggest_errorDefault": "Błąd podczas generowania.", + "suggest_errorBatch": "Błąd podczas generowania planu.", + "suggest_errorSave": "Błąd podczas zapisywania.", + "suggest_amMorning": "AM (rano)", + "suggest_pmEvening": "PM (wieczór)", + + "medications_title": "Leki", + "medications_count": "{count} wpisów", + "medications_addNew": "+ Dodaj lek", + "medications_newTitle": "Nowy lek", + "medications_kind": "Rodzaj", + "medications_productName": "Nazwa produktu *", + "medications_productNamePlaceholder": "np. Witamina D3", + "medications_activeSubstance": "Substancja czynna", + "medications_activeSubstancePlaceholder": "np. cholekalcyferol", + "medications_notes": "Notatki", + "medications_added": "Lek dodany.", + "medications_usages": "{count} użyć", + "medications_noMedications": "Brak leków.", + "medications_kindPrescription": "Na receptę", + "medications_kindOtc": "OTC (bez recepty)", + "medications_kindSupplement": "Suplement", + "medications_kindHerbal": "Zioła", + "medications_kindOther": "Inne", + + "labResults_title": "Wyniki badań", + "labResults_count": "{count} wyników", + "labResults_addNew": "+ Dodaj wynik", + "labResults_newTitle": "Nowy wynik badania", + "labResults_flagFilter": "Flaga:", + "labResults_flagAll": "Wszystkie", + "labResults_flagNone": "Brak", + "labResults_date": "Data *", + "labResults_loincCode": "Kod LOINC *", + "labResults_testName": "Nazwa badania", + "labResults_testNamePlaceholder": "np. Hemoglobina", + "labResults_lab": "Laboratorium", + "labResults_labPlaceholder": "np. LabCorp", + "labResults_value": "Wartość", + "labResults_unit": "Jednostka", + "labResults_unitPlaceholder": "np. g/dL", + "labResults_flag": "Flaga", + "labResults_added": "Wynik dodany.", + "labResults_colDate": "Data", + "labResults_colTest": "Badanie", + "labResults_colLoinc": "LOINC", + "labResults_colValue": "Wartość", + "labResults_colFlag": "Flaga", + "labResults_colLab": "Lab", + "labResults_noResults": "Nie znaleziono wyników badań.", + + "skin_title": "Stan skóry", + "skin_count": "{count} wpisów", + "skin_addNew": "+ Dodaj wpis", + "skin_aiAnalysisTitle": "Analiza AI ze zdjęć", + "skin_aiUploadText": "Prześlij 1–3 zdjęcia skóry. AI wypełni pola formularza poniżej.", + "skin_analyzePhotos": "Analizuj zdjęcia", + "skin_analyzing": "Analizuję…", + "skin_newSnapshotTitle": "Nowy wpis", + "skin_date": "Data *", + "skin_overallState": "Ogólny stan", + "skin_texture": "Tekstura", + "skin_skinType": "Typ skóry", + "skin_barrierState": "Stan bariery", + "skin_hydration": "Nawilżenie (1–5)", + "skin_sensitivity": "Wrażliwość (1–5)", + "skin_sebumTzone": "Sebum T-zone (1–5)", + "skin_sebumCheeks": "Sebum policzki (1–5)", + "skin_activeConcerns": "Aktywne problemy (przecinek)", + "skin_activeConcernsPlaceholder": "trądzik, zaczerwienienie, odwodnienie", + "skin_notes": "Notatki", + "skin_addSnapshot": "Dodaj wpis", + "skin_snapshotAdded": "Wpis dodany.", + "skin_snapshotUpdated": "Wpis zaktualizowany.", + "skin_snapshotDeleted": "Wpis usunięty.", + "skin_noSnapshots": "Brak wpisów o stanie skóry.", + "skin_hydrationLabel": "Nawilżenie", + "skin_sensitivityLabel": "Wrażliwość", + "skin_barrierLabel": "Bariera", + "skin_stateExcellent": "doskonały", + "skin_stateGood": "dobry", + "skin_stateFair": "przeciętny", + "skin_statePoor": "zły", + "skin_textureSmooth": "gładka", + "skin_textureRough": "szorstka", + "skin_textureFlaky": "łuszcząca się", + "skin_textureBumpy": "nierówna", + "skin_barrierIntact": "nienaruszona", + "skin_barrierMildly": "lekko naruszona", + "skin_barrierCompromised": "naruszona", + "skin_typeDry": "sucha", + "skin_typeOily": "tłusta", + "skin_typeCombination": "mieszana", + "skin_typeSensitive": "wrażliwa", + "skin_typeNormal": "normalna", + "skin_typeAcneProne": "trądzikowa", + + "productForm_aiPrefill": "Uzupełnienie AI", + "productForm_aiPrefillText": "Wklej opis produktu ze strony, listę składników lub inny tekst. AI uzupełni dostępne pola — możesz je przejrzeć i poprawić przed zapisem.", + "productForm_pasteText": "Wklej tutaj opis produktu, składniki INCI...", + "productForm_parseWithAI": "Uzupełnij pola (AI)", + "productForm_parsing": "Przetwarzam…", + "productForm_basicInfo": "Informacje podstawowe", + "productForm_name": "Nazwa *", + "productForm_namePlaceholder": "np. Hydro Boost Water Gel", + "productForm_brand": "Marka *", + "productForm_brandPlaceholder": "np. Neutrogena", + "productForm_lineName": "Linia / seria", + "productForm_lineNamePlaceholder": "np. Hydro Boost", + "productForm_url": "URL", + "productForm_sku": "SKU", + "productForm_skuPlaceholder": "np. NTR-HB-50", + "productForm_barcode": "Kod kreskowy / EAN", + "productForm_barcodePlaceholder": "np. 3614273258975", + "productForm_classification": "Klasyfikacja", + "productForm_category": "Kategoria *", + "productForm_selectCategory": "Wybierz kategorię", + "productForm_time": "Pora *", + "productForm_timeOptions": "AM / PM / Oba", + "productForm_timeBoth": "Oba", + "productForm_leaveOn": "Leave-on *", + "productForm_leaveOnYes": "Tak (leave-on)", + "productForm_leaveOnNo": "Nie (rinse-off)", + "productForm_texture": "Tekstura", + "productForm_selectTexture": "Wybierz teksturę", + "productForm_absorptionSpeed": "Szybkość wchłaniania", + "productForm_selectSpeed": "Wybierz szybkość", + "productForm_skinProfile": "Profil skóry", + "productForm_recommendedFor": "Polecane dla typów skóry", + "productForm_targetConcerns": "Problemy docelowe", + "productForm_contraindications": "Przeciwwskazania (jedno na linię)", + "productForm_contraindicationsPlaceholder": "np. aktywna rosacea", + "productForm_ingredients": "Składniki", + "productForm_inciList": "Lista INCI (jeden składnik na linię)", + "productForm_activeIngredients": "Składniki aktywne", + "productForm_addActive": "+ Dodaj aktywny", + "productForm_noActives": "Brak składników aktywnych.", + "productForm_activeName": "Nazwa", + "productForm_activePercent": "%", + "productForm_activeStrength": "Siła", + "productForm_activeIrritation": "Podrażnienie", + "productForm_activeFunctions": "Funkcje", + "productForm_effectProfile": "Profil działania (0–5)", + "productForm_interactions": "Interakcje", + "productForm_synergizesWith": "Synergizuje z (jedno na linię)", + "productForm_incompatibleWith": "Niekompatybilny z", + "productForm_addIncompatibility": "+ Dodaj niekompatybilność", + "productForm_noIncompatibilities": "Brak niekompatybilności.", + "productForm_incompTarget": "Składnik docelowy", + "productForm_incompScope": "Zakres", + "productForm_incompReason": "Powód (opcjonalny)", + "productForm_incompReasonPlaceholder": "np. zmniejsza skuteczność", + "productForm_incompScopeSelect": "Wybierz…", + "productForm_contextRules": "Reguły kontekstu", + "productForm_ctxAfterShaving": "Bezpieczny po goleniu", + "productForm_ctxAfterAcids": "Bezpieczny po kwasach", + "productForm_ctxAfterRetinoids": "Bezpieczny po retinoidach", + "productForm_ctxCompromisedBarrier": "Bezpieczny przy naruszonej barierze", + "productForm_ctxLowUvOnly": "Tylko przy niskim UV (wieczór/zakrycie)", + "productForm_productDetails": "Szczegóły produktu", + "productForm_priceTier": "Przedział cenowy", + "productForm_selectTier": "Wybierz przedział", + "productForm_sizeMl": "Rozmiar (ml)", + "productForm_fullWeightG": "Waga pełna (g)", + "productForm_emptyWeightG": "Waga pustego (g)", + "productForm_paoMonths": "PAO (miesiące)", + "productForm_phMin": "pH min", + "productForm_phMax": "pH max", + "productForm_usageNotes": "Notatki o stosowaniu", + "productForm_usageNotesPlaceholder": "np. Nakładaj na wilgotną skórę, unikaj okolic oczu", + "productForm_safetyFlags": "Flagi bezpieczeństwa", + "productForm_fragranceFree": "Bez zapachów", + "productForm_essentialOilsFree": "Bez olejków eterycznych", + "productForm_alcoholDenatFree": "Bez alkoholu denat.", + "productForm_pregnancySafe": "Bezpieczny w ciąży", + "productForm_usageConstraints": "Ograniczenia stosowania", + "productForm_minIntervalHours": "Min. przerwa (godziny)", + "productForm_maxFrequencyPerWeek": "Max użyć na tydzień", + "productForm_isMedication": "To lek", + "productForm_isTool": "To narzędzie (np. dermaroller)", + "productForm_needleLengthMm": "Długość igły (mm, tylko narzędzia)", + "productForm_personalNotes": "Notatki osobiste", + "productForm_repurchaseIntent": "Zamiar ponownego zakupu", + "productForm_toleranceNotes": "Notatki o tolerancji", + "productForm_toleranceNotesPlaceholder": "np. Lekkie pieczenie, ustępuje po 2 tygodniach", + + "productForm_categoryCleanser": "Żel/pianka do mycia", + "productForm_categoryToner": "Tonik", + "productForm_categoryEssence": "Esencja", + "productForm_categorySerum": "Serum", + "productForm_categoryMoisturizer": "Krem", + "productForm_categorySpf": "SPF", + "productForm_categoryMask": "Maska", + "productForm_categoryExfoliant": "Peeling", + "productForm_categoryHairTreatment": "Pielęgnacja włosów", + "productForm_categoryTool": "Narzędzie", + "productForm_categorySpotTreatment": "Punkt leczenia", + "productForm_categoryOil": "Olejek", + + "productForm_textureWatery": "Wodnista", + "productForm_textureGel": "Żel", + "productForm_textureEmulsion": "Emulsja", + "productForm_textureCream": "Krem", + "productForm_textureOil": "Olejek", + "productForm_textureBalm": "Balsam", + "productForm_textureFoam": "Pianka", + "productForm_textureFluid": "Fluid", + + "productForm_absorptionVeryFast": "Bardzo szybkie", + "productForm_absorptionFast": "Szybkie", + "productForm_absorptionModerate": "Umiarkowane", + "productForm_absorptionSlow": "Wolne", + "productForm_absorptionVerySlow": "Bardzo wolne", + + "productForm_priceBudget": "Budżetowy", + "productForm_priceMid": "Średni", + "productForm_pricePremium": "Premium", + "productForm_priceLuxury": "Luksusowy", + + "productForm_skinTypeDry": "sucha", + "productForm_skinTypeOily": "tłusta", + "productForm_skinTypeCombination": "mieszana", + "productForm_skinTypeSensitive": "wrażliwa", + "productForm_skinTypeNormal": "normalna", + "productForm_skinTypeAcneProne": "trądzikowa", + + "productForm_concernAcne": "trądzik", + "productForm_concernRosacea": "rosacea", + "productForm_concernHyperpigmentation": "przebarwienia", + "productForm_concernAging": "starzenie", + "productForm_concernDehydration": "odwodnienie", + "productForm_concernRedness": "zaczerwienienie", + "productForm_concernDamagedBarrier": "naruszona bariera", + "productForm_concernPoreVisibility": "widoczność porów", + "productForm_concernUnevenTexture": "nierówna tekstura", + "productForm_concernHairGrowth": "wzrost włosów", + "productForm_concernSebumExcess": "nadmiar sebum", + + "productForm_fnHumectant": "humektant", + "productForm_fnEmollient": "emolient", + "productForm_fnOcclusive": "okluzja", + "productForm_fnExfoliantAha": "peeling AHA", + "productForm_fnExfoliantBha": "peeling BHA", + "productForm_fnExfoliantPha": "peeling PHA", + "productForm_fnRetinoid": "retinoid", + "productForm_fnAntioxidant": "antyoksydant", + "productForm_fnSoothing": "łagodzący", + "productForm_fnBarrierSupport": "wsparcie bariery", + "productForm_fnBrightening": "rozjaśniający", + "productForm_fnAntiAcne": "przeciwtrądzikowy", + "productForm_fnCeramide": "ceramid", + "productForm_fnNiacinamide": "niacynamid", + "productForm_fnSunscreen": "filtr UV", + "productForm_fnPeptide": "peptyd", + "productForm_fnHairGrowth": "stymulator wzrostu włosów", + "productForm_fnPrebiotic": "prebiotyk", + "productForm_fnVitaminC": "witamina C", + "productForm_fnAntiAging": "przeciwstarzeniowy", + + "productForm_scopeSameStep": "ten sam krok", + "productForm_scopeSameDay": "ten sam dzień", + "productForm_scopeSamePeriod": "ten sam okres", + + "productForm_strengthLow": "1 Niskie", + "productForm_strengthMedium": "2 Średnie", + "productForm_strengthHigh": "3 Wysokie", + + "productForm_effectHydrationImmediate": "Nawilżenie (natychmiastowe)", + "productForm_effectHydrationLongTerm": "Nawilżenie (długoterminowe)", + "productForm_effectBarrierRepair": "Naprawa bariery", + "productForm_effectSoothing": "Łagodzenie", + "productForm_effectExfoliation": "Złuszczanie", + "productForm_effectRetinoid": "Aktywność retinoidu", + "productForm_effectIrritation": "Ryzyko podrażnienia", + "productForm_effectComedogenic": "Ryzyko komedogenności", + "productForm_effectBarrierDisruption": "Ryzyko naruszenia bariery", + "productForm_effectDryness": "Ryzyko przesuszenia", + "productForm_effectBrightening": "Rozjaśnienie", + "productForm_effectAntiAcne": "Działanie przeciwtrądzikowe", + "productForm_effectAntiAging": "Działanie przeciwstarzeniowe", + + "lang_pl": "PL", + "lang_en": "EN" +} diff --git a/frontend/package.json b/frontend/package.json index 371022b..0d75051 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -26,6 +26,7 @@ "vite": "^7.3.1" }, "dependencies": { + "@inlang/paraglide-js": "^2.13.0", "bits-ui": "^2.16.2", "clsx": "^2.1.1", "lucide-svelte": "^0.575.0", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 64ad603..f5aa872 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -8,9 +8,12 @@ importers: .: dependencies: + '@inlang/paraglide-js': + specifier: ^2.13.0 + version: 2.13.0 bits-ui: specifier: ^2.16.2 - version: 2.16.2(@internationalized/date@3.11.0)(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5) + version: 2.16.2(@internationalized/date@3.11.0)(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -32,16 +35,16 @@ importers: version: 0.561.0(svelte@5.53.5) '@sveltejs/adapter-node': specifier: ^5.0.0 - version: 5.5.4(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1))) + version: 5.5.4(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1))) '@sveltejs/kit': specifier: ^2.50.2 - version: 2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) + version: 2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)) '@sveltejs/vite-plugin-svelte': specifier: ^6.2.4 - version: 6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) + version: 6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)) '@tailwindcss/vite': specifier: ^4.2.1 - version: 4.2.1(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) + version: 4.2.1(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)) svelte: specifier: ^5.51.0 version: 5.53.5 @@ -59,7 +62,7 @@ importers: version: 5.9.3 vite: specifier: ^7.3.1 - version: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1) + version: 7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1) packages: @@ -228,6 +231,17 @@ packages: '@floating-ui/utils@0.2.10': resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + '@inlang/paraglide-js@2.13.0': + resolution: {integrity: sha512-m7JQiTeLC3tY3DusUCc4iRWlsKoMuDLhw4iGhkY0yI96ki7PK42DLsi1kMk8ubSVenKOwgrs7eqQZN1Htvkhew==} + hasBin: true + + '@inlang/recommend-sherlock@0.2.1': + resolution: {integrity: sha512-ckv8HvHy/iTqaVAEKrr+gnl+p3XFNwe5D2+6w6wJk2ORV2XkcRkKOJ/XsTUJbPSiyi4PI+p+T3bqbmNx/rDUlg==} + + '@inlang/sdk@2.7.0': + resolution: {integrity: sha512-yJNBD0o8i29TTJqWX5uDRHxnalDGcsUDctxepzFXsUfkzqGWfiFBxODdxvReqvM2CuKAAOo/kib/F1UcgdYFNQ==} + engines: {node: '>=18.0.0'} + '@internationalized/date@3.11.0': resolution: {integrity: sha512-BOx5huLAWhicM9/ZFs84CzP+V3gBW6vlpM02yzsdYC7TGlZJX1OJiEEHcSayF00Z+3jLlm4w79amvSt6RqKN3Q==} @@ -247,6 +261,13 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@lix-js/sdk@0.4.7': + resolution: {integrity: sha512-pRbW+joG12L0ULfMiWYosIW0plmW4AsUdiPCp+Z8rAsElJ+wJ6in58zhD3UwUcd4BNcpldEGjg6PdA7e0RgsDQ==} + engines: {node: '>=18'} + + '@lix-js/server-protocol-schema@0.1.1': + resolution: {integrity: sha512-jBeALB6prAbtr5q4vTuxnRZZv1M2rKe8iNqRQhFJ4Tv7150unEa0vKyz0hs8Gl3fUGsWaNJBh3J8++fpbrpRBQ==} + '@lucide/svelte@0.561.0': resolution: {integrity: sha512-vofKV2UFVrKE6I4ewKJ3dfCXSV6iP6nWVmiM83MLjsU91EeJcEg7LoWUABLp/aOTxj1HQNbJD1f3g3L0JQgH9A==} peerDependencies: @@ -429,6 +450,13 @@ packages: cpu: [x64] os: [win32] + '@sinclair/typebox@0.31.28': + resolution: {integrity: sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ==} + + '@sqlite.org/sqlite-wasm@3.48.0-build4': + resolution: {integrity: sha512-hI6twvUkzOmyGZhQMza1gpfqErZxXRw6JEsiVjUbo7tFanVD+8Oil0Ih3l2nGzHdxPI41zFmfUQG7GHqhciKZQ==} + hasBin: true + '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -576,6 +604,9 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/node@25.3.3': + resolution: {integrity: sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -591,6 +622,9 @@ packages: resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} engines: {node: '>= 0.4'} + array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -610,13 +644,36 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + comment-json@4.5.1: + resolution: {integrity: sha512-taEtr3ozUmOB7it68Jll7s0Pwm+aoiHyXKrEC8SEodL4rNpdfDLqa7PfBlrgFoCNNdR8ImL+muti5IGvktJAAg==} + engines: {node: '>= 6'} + commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + consola@3.4.0: + resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==} + engines: {node: ^14.18.0 || >=16.10.0} + cookie@0.6.0: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + dedent@1.5.1: + resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -644,6 +701,11 @@ packages: esm-env@1.2.2: resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esrap@2.2.3: resolution: {integrity: sha512-8fOS+GIGCQZl/ZIlhl59htOlms6U8NvX6ZYgYHpRU/b6tVSh3uHkOHZikl3D4cMbYM0JlpBe+p/BkZEi8J9XIQ==} @@ -674,6 +736,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + human-id@4.1.3: + resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} + hasBin: true + inline-style-parser@0.2.7: resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} @@ -694,10 +760,22 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + js-sha256@0.11.1: + resolution: {integrity: sha512-o6WSo/LUvY2uC4j7mO50a2ms7E/EAdbP0swigLV+nzHKTTaYnaLIWJ02VdXrsJX0vGedDESQnLsOekr94ryfjg==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + kysely@0.27.6: + resolution: {integrity: sha512-FIyV/64EkKhJmjgC0g2hygpBv5RNWVPyNCqSAD7eTCv6eFWNIi4PN1UvdSJGicN/o35bnevgis4Y0UDC0qi8jQ==} + engines: {node: '>=14.0.0'} + lightningcss-android-arm64@1.31.1: resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} engines: {node: '>= 12.0.0'} @@ -870,6 +948,11 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + sqlite-wasm-kysely@0.3.0: + resolution: {integrity: sha512-TzjBNv7KwRw6E3pdKdlRyZiTmUIE0UttT/Sl56MVwVARl/u5gp978KepazCJZewFUnlWHz9i3NQd4kOtP/Afdg==} + peerDependencies: + kysely: '*' + style-to-object@1.0.14: resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} @@ -940,6 +1023,24 @@ packages: engines: {node: '>=14.17'} hasBin: true + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} + + urlpattern-polyfill@10.1.0: + resolution: {integrity: sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==} + + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + + uuid@13.0.0: + resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} + hasBin: true + vite@7.3.1: resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -988,6 +1089,9 @@ packages: vite: optional: true + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + zimmerframe@1.1.4: resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} @@ -1082,6 +1186,32 @@ snapshots: '@floating-ui/utils@0.2.10': {} + '@inlang/paraglide-js@2.13.0': + dependencies: + '@inlang/recommend-sherlock': 0.2.1 + '@inlang/sdk': 2.7.0 + commander: 11.1.0 + consola: 3.4.0 + json5: 2.2.3 + unplugin: 2.3.11 + urlpattern-polyfill: 10.1.0 + transitivePeerDependencies: + - babel-plugin-macros + + '@inlang/recommend-sherlock@0.2.1': + dependencies: + comment-json: 4.5.1 + + '@inlang/sdk@2.7.0': + dependencies: + '@lix-js/sdk': 0.4.7 + '@sinclair/typebox': 0.31.28 + kysely: 0.27.6 + sqlite-wasm-kysely: 0.3.0(kysely@0.27.6) + uuid: 13.0.0 + transitivePeerDependencies: + - babel-plugin-macros + '@internationalized/date@3.11.0': dependencies: '@swc/helpers': 0.5.19 @@ -1105,6 +1235,20 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@lix-js/sdk@0.4.7': + dependencies: + '@lix-js/server-protocol-schema': 0.1.1 + dedent: 1.5.1 + human-id: 4.1.3 + js-sha256: 0.11.1 + kysely: 0.27.6 + sqlite-wasm-kysely: 0.3.0(kysely@0.27.6) + uuid: 10.0.0 + transitivePeerDependencies: + - babel-plugin-macros + + '@lix-js/server-protocol-schema@0.1.1': {} + '@lucide/svelte@0.561.0(svelte@5.53.5)': dependencies: svelte: 5.53.5 @@ -1222,25 +1366,29 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.59.0': optional: true + '@sinclair/typebox@0.31.28': {} + + '@sqlite.org/sqlite-wasm@3.48.0-build4': {} + '@standard-schema/spec@1.1.0': {} '@sveltejs/acorn-typescript@1.0.9(acorn@8.16.0)': dependencies: acorn: 8.16.0 - '@sveltejs/adapter-node@5.5.4(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))': + '@sveltejs/adapter-node@5.5.4(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))': dependencies: '@rollup/plugin-commonjs': 29.0.0(rollup@4.59.0) '@rollup/plugin-json': 6.1.0(rollup@4.59.0) '@rollup/plugin-node-resolve': 16.0.3(rollup@4.59.0) - '@sveltejs/kit': 2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) + '@sveltejs/kit': 2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)) rollup: 4.59.0 - '@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1))': + '@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1))': dependencies: '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) - '@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) + '@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)) '@types/cookie': 0.6.0 acorn: 8.16.0 cookie: 0.6.0 @@ -1252,26 +1400,26 @@ snapshots: set-cookie-parser: 3.0.1 sirv: 3.0.2 svelte: 5.53.5 - vite: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1) + vite: 7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1) optionalDependencies: typescript: 5.9.3 - '@sveltejs/vite-plugin-svelte-inspector@5.0.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1))': + '@sveltejs/vite-plugin-svelte-inspector@5.0.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) + '@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)) obug: 2.1.1 svelte: 5.53.5 - vite: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1) + vite: 7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1) - '@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1))': + '@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 5.0.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) + '@sveltejs/vite-plugin-svelte-inspector': 5.0.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)) deepmerge: 4.3.1 magic-string: 0.30.21 obug: 2.1.1 svelte: 5.53.5 - vite: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1) - vitefu: 1.1.2(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) + vite: 7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1) + vitefu: 1.1.2(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)) '@swc/helpers@0.5.19': dependencies: @@ -1338,17 +1486,22 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.2.1 '@tailwindcss/oxide-win32-x64-msvc': 4.2.1 - '@tailwindcss/vite@4.2.1(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1))': + '@tailwindcss/vite@4.2.1(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1))': dependencies: '@tailwindcss/node': 4.2.1 '@tailwindcss/oxide': 4.2.1 tailwindcss: 4.2.1 - vite: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1) + vite: 7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1) '@types/cookie@0.6.0': {} '@types/estree@1.0.8': {} + '@types/node@25.3.3': + dependencies: + undici-types: 7.18.2 + optional: true + '@types/resolve@1.20.2': {} '@types/trusted-types@2.0.7': {} @@ -1357,17 +1510,19 @@ snapshots: aria-query@5.3.1: {} + array-timsort@1.0.3: {} + axobject-query@4.1.0: {} - bits-ui@2.16.2(@internationalized/date@3.11.0)(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5): + bits-ui@2.16.2(@internationalized/date@3.11.0)(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5): dependencies: '@floating-ui/core': 1.7.4 '@floating-ui/dom': 1.7.5 '@internationalized/date': 3.11.0 esm-env: 1.2.2 - runed: 0.35.1(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5) + runed: 0.35.1(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5) svelte: 5.53.5 - svelte-toolbelt: 0.10.6(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5) + svelte-toolbelt: 0.10.6(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5) tabbable: 6.4.0 transitivePeerDependencies: - '@sveltejs/kit' @@ -1378,10 +1533,24 @@ snapshots: clsx@2.1.1: {} + commander@11.1.0: {} + + comment-json@4.5.1: + dependencies: + array-timsort: 1.0.3 + core-util-is: 1.0.3 + esprima: 4.0.1 + commondir@1.0.1: {} + consola@3.4.0: {} + cookie@0.6.0: {} + core-util-is@1.0.3: {} + + dedent@1.5.1: {} + deepmerge@4.3.1: {} dequal@2.0.3: {} @@ -1426,6 +1595,8 @@ snapshots: esm-env@1.2.2: {} + esprima@4.0.1: {} + esrap@2.2.3: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -1447,6 +1618,8 @@ snapshots: dependencies: function-bind: 1.1.2 + human-id@4.1.3: {} + inline-style-parser@0.2.7: {} is-core-module@2.16.1: @@ -1465,8 +1638,14 @@ snapshots: jiti@2.6.1: {} + js-sha256@0.11.1: {} + + json5@2.2.3: {} + kleur@4.1.5: {} + kysely@0.27.6: {} + lightningcss-android-arm64@1.31.1: optional: true @@ -1603,14 +1782,14 @@ snapshots: esm-env: 1.2.2 svelte: 5.53.5 - runed@0.35.1(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5): + runed@0.35.1(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5): dependencies: dequal: 2.0.3 esm-env: 1.2.2 lz-string: 1.5.0 svelte: 5.53.5 optionalDependencies: - '@sveltejs/kit': 2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)) + '@sveltejs/kit': 2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)) sade@1.8.1: dependencies: @@ -1626,6 +1805,11 @@ snapshots: source-map-js@1.2.1: {} + sqlite-wasm-kysely@0.3.0(kysely@0.27.6): + dependencies: + '@sqlite.org/sqlite-wasm': 3.48.0-build4 + kysely: 0.27.6 + style-to-object@1.0.14: dependencies: inline-style-parser: 0.2.7 @@ -1644,10 +1828,10 @@ snapshots: transitivePeerDependencies: - picomatch - svelte-toolbelt@0.10.6(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5): + svelte-toolbelt@0.10.6(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5): dependencies: clsx: 2.1.1 - runed: 0.35.1(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5) + runed: 0.35.1(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.5)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)))(svelte@5.53.5) style-to-object: 1.0.14 svelte: 5.53.5 transitivePeerDependencies: @@ -1704,7 +1888,23 @@ snapshots: typescript@5.9.3: {} - vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1): + undici-types@7.18.2: + optional: true + + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.16.0 + picomatch: 4.0.3 + webpack-virtual-modules: 0.6.2 + + urlpattern-polyfill@10.1.0: {} + + uuid@10.0.0: {} + + uuid@13.0.0: {} + + vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1): dependencies: esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) @@ -1713,12 +1913,15 @@ snapshots: rollup: 4.59.0 tinyglobby: 0.2.15 optionalDependencies: + '@types/node': 25.3.3 fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.31.1 - vitefu@1.1.2(vite@7.3.1(jiti@2.6.1)(lightningcss@1.31.1)): + vitefu@1.1.2(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)): optionalDependencies: - vite: 7.3.1(jiti@2.6.1)(lightningcss@1.31.1) + vite: 7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1) + + webpack-virtual-modules@0.6.2: {} zimmerframe@1.1.4: {} diff --git a/frontend/project.inlang/settings.json b/frontend/project.inlang/settings.json new file mode 100644 index 0000000..8342010 --- /dev/null +++ b/frontend/project.inlang/settings.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://inlang.com/schema/project-settings", + "baseLocale": "pl", + "locales": ["pl", "en"], + "modules": [ + "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js" + ], + "plugin.inlang.messageFormat": { + "pathPattern": "./messages/{locale}.json" + } +} diff --git a/frontend/src/hooks.server.ts b/frontend/src/hooks.server.ts new file mode 100644 index 0000000..4449456 --- /dev/null +++ b/frontend/src/hooks.server.ts @@ -0,0 +1,6 @@ +import { paraglideMiddleware } from '$lib/paraglide/server.js'; +import type { Handle } from '@sveltejs/kit'; + +export const handle: Handle = async ({ event, resolve }) => { + return paraglideMiddleware(event.request, () => resolve(event)); +}; diff --git a/frontend/src/lib/components/LanguageSwitcher.svelte b/frontend/src/lib/components/LanguageSwitcher.svelte new file mode 100644 index 0000000..7b19090 --- /dev/null +++ b/frontend/src/lib/components/LanguageSwitcher.svelte @@ -0,0 +1,15 @@ + + +
+ + | + +
diff --git a/frontend/src/lib/components/ProductForm.svelte b/frontend/src/lib/components/ProductForm.svelte index 67b81a5..430b101 100644 --- a/frontend/src/lib/components/ProductForm.svelte +++ b/frontend/src/lib/components/ProductForm.svelte @@ -8,13 +8,10 @@ import { Select, SelectContent, SelectItem, SelectTrigger } from '$lib/components/ui/select'; import { Card, CardContent, CardHeader, CardTitle } from '$lib/components/ui/card'; import { parseProductText, type ProductParseResponse } from '$lib/api'; + import { m } from '$lib/paraglide/messages.js'; let { product }: { product?: Product } = $props(); - function lbl(val: string) { - return val.replace(/_/g, ' '); - } - // ── Enum option lists ───────────────────────────────────────────────────── const categories = [ @@ -38,26 +35,127 @@ 'sunscreen', 'peptide', 'hair_growth_stimulant', 'prebiotic', 'vitamin_c', 'anti_aging' ]; const interactionScopes: InteractionScope[] = ['same_step', 'same_day', 'same_period']; - const tristate = [ - { value: '', label: 'Unknown' }, - { value: 'true', label: 'Yes' }, - { value: 'false', label: 'No' } - ]; - const effectFields = [ - { key: 'hydration_immediate', label: 'Hydration (immediate)' }, - { key: 'hydration_long_term', label: 'Hydration (long term)' }, - { key: 'barrier_repair_strength', label: 'Barrier repair' }, - { key: 'soothing_strength', label: 'Soothing' }, - { key: 'exfoliation_strength', label: 'Exfoliation' }, - { key: 'retinoid_strength', label: 'Retinoid activity' }, - { key: 'irritation_risk', label: 'Irritation risk' }, - { key: 'comedogenic_risk', label: 'Comedogenic risk' }, - { key: 'barrier_disruption_risk', label: 'Barrier disruption risk' }, - { key: 'dryness_risk', label: 'Dryness risk' }, - { key: 'brightening_strength', label: 'Brightening' }, - { key: 'anti_acne_strength', label: 'Anti-acne' }, - { key: 'anti_aging_strength', label: 'Anti-aging' } - ] as const; + + // ── Translated label maps ───────────────────────────────────────────────── + + const categoryLabels = $derived>({ + cleanser: m["productForm_categoryCleanser"](), + toner: m["productForm_categoryToner"](), + essence: m["productForm_categoryEssence"](), + serum: m["productForm_categorySerum"](), + moisturizer: m["productForm_categoryMoisturizer"](), + spf: m["productForm_categorySpf"](), + mask: m["productForm_categoryMask"](), + exfoliant: m["productForm_categoryExfoliant"](), + hair_treatment: m["productForm_categoryHairTreatment"](), + tool: m["productForm_categoryTool"](), + spot_treatment: m["productForm_categorySpotTreatment"](), + oil: m["productForm_categoryOil"]() + }); + + const textureLabels = $derived>({ + watery: m["productForm_textureWatery"](), + gel: m["productForm_textureGel"](), + emulsion: m["productForm_textureEmulsion"](), + cream: m["productForm_textureCream"](), + oil: m["productForm_textureOil"](), + balm: m["productForm_textureBalm"](), + foam: m["productForm_textureFoam"](), + fluid: m["productForm_textureFluid"]() + }); + + const absorptionLabels = $derived>({ + very_fast: m["productForm_absorptionVeryFast"](), + fast: m["productForm_absorptionFast"](), + moderate: m["productForm_absorptionModerate"](), + slow: m["productForm_absorptionSlow"](), + very_slow: m["productForm_absorptionVerySlow"]() + }); + + const priceTierLabels = $derived>({ + budget: m["productForm_priceBudget"](), + mid: m["productForm_priceMid"](), + premium: m["productForm_pricePremium"](), + luxury: m["productForm_priceLuxury"]() + }); + + const skinTypeLabels = $derived>({ + dry: m["productForm_skinTypeDry"](), + oily: m["productForm_skinTypeOily"](), + combination: m["productForm_skinTypeCombination"](), + sensitive: m["productForm_skinTypeSensitive"](), + normal: m["productForm_skinTypeNormal"](), + acne_prone: m["productForm_skinTypeAcneProne"]() + }); + + const skinConcernLabels = $derived>({ + acne: m["productForm_concernAcne"](), + rosacea: m["productForm_concernRosacea"](), + hyperpigmentation: m["productForm_concernHyperpigmentation"](), + aging: m["productForm_concernAging"](), + dehydration: m["productForm_concernDehydration"](), + redness: m["productForm_concernRedness"](), + damaged_barrier: m["productForm_concernDamagedBarrier"](), + pore_visibility: m["productForm_concernPoreVisibility"](), + uneven_texture: m["productForm_concernUnevenTexture"](), + hair_growth: m["productForm_concernHairGrowth"](), + sebum_excess: m["productForm_concernSebumExcess"]() + }); + + const ingFunctionLabels = $derived>({ + humectant: m["productForm_fnHumectant"](), + emollient: m["productForm_fnEmollient"](), + occlusive: m["productForm_fnOcclusive"](), + exfoliant_aha: m["productForm_fnExfoliantAha"](), + exfoliant_bha: m["productForm_fnExfoliantBha"](), + exfoliant_pha: m["productForm_fnExfoliantPha"](), + retinoid: m["productForm_fnRetinoid"](), + antioxidant: m["productForm_fnAntioxidant"](), + soothing: m["productForm_fnSoothing"](), + barrier_support: m["productForm_fnBarrierSupport"](), + brightening: m["productForm_fnBrightening"](), + anti_acne: m["productForm_fnAntiAcne"](), + ceramide: m["productForm_fnCeramide"](), + niacinamide: m["productForm_fnNiacinamide"](), + sunscreen: m["productForm_fnSunscreen"](), + peptide: m["productForm_fnPeptide"](), + hair_growth_stimulant: m["productForm_fnHairGrowth"](), + prebiotic: m["productForm_fnPrebiotic"](), + vitamin_c: m["productForm_fnVitaminC"](), + anti_aging: m["productForm_fnAntiAging"]() + }); + + const scopeLabels = $derived>({ + same_step: m["productForm_scopeSameStep"](), + same_day: m["productForm_scopeSameDay"](), + same_period: m["productForm_scopeSamePeriod"]() + }); + + const tristate = $derived([ + { value: '', label: m.common_unknown() }, + { value: 'true', label: m.common_yes() }, + { value: 'false', label: m.common_no() } + ]); + + function tristateLabel(val: string): string { + return val === '' ? m.common_unknown() : val === 'true' ? m.common_yes() : m.common_no(); + } + + const effectFields = $derived([ + { key: 'hydration_immediate' as const, label: m["productForm_effectHydrationImmediate"]() }, + { key: 'hydration_long_term' as const, label: m["productForm_effectHydrationLongTerm"]() }, + { key: 'barrier_repair_strength' as const, label: m["productForm_effectBarrierRepair"]() }, + { key: 'soothing_strength' as const, label: m["productForm_effectSoothing"]() }, + { key: 'exfoliation_strength' as const, label: m["productForm_effectExfoliation"]() }, + { key: 'retinoid_strength' as const, label: m["productForm_effectRetinoid"]() }, + { key: 'irritation_risk' as const, label: m["productForm_effectIrritation"]() }, + { key: 'comedogenic_risk' as const, label: m["productForm_effectComedogenic"]() }, + { key: 'barrier_disruption_risk' as const, label: m["productForm_effectBarrierDisruption"]() }, + { key: 'dryness_risk' as const, label: m["productForm_effectDryness"]() }, + { key: 'brightening_strength' as const, label: m["productForm_effectBrightening"]() }, + { key: 'anti_acne_strength' as const, label: m["productForm_effectAntiAcne"]() }, + { key: 'anti_aging_strength' as const, label: m["productForm_effectAntiAging"]() } + ]); // ── Controlled text/number inputs ──────────────────────────────────────── @@ -328,25 +426,22 @@ {#if aiPanelOpen} -

- Wklej opis produktu ze strony, listę składników lub inny tekst. - AI uzupełni dostępne pola — możesz je przejrzeć i poprawić przed zapisem. -

+

{m["productForm_aiPrefillText"]()}

{#if aiError}

{aiError}

{/if}
{/if} @@ -354,36 +449,36 @@ - Basic info + {m["productForm_basicInfo"]()}
- - + +
- - + +
- - + +
- +
- - + +
- - + +
@@ -391,70 +486,70 @@ - Classification + {m["productForm_classification"]()}
- +
- +
- +
- +
- + @@ -465,10 +560,10 @@ - Skin profile + {m["productForm_skinProfile"]()}
- +
{#each skinTypes as st} {/each}
- +
{#each skinConcerns as sc} {/each}
- + @@ -531,10 +626,10 @@ - Ingredients + {m["productForm_ingredients"]()}
- + @@ -865,16 +946,14 @@ - Safety flags + {m["productForm_safetyFlags"]()}
- +
- +
@@ -955,7 +1028,7 @@ onchange={() => (isMedication = !isMedication)} class="rounded border-input" /> - Is medication + {m["productForm_isMedication"]()}
- +
@@ -978,23 +1051,17 @@ - Personal notes + {m["productForm_personalNotes"]()}
- +
diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index 110b8ff..f966efd 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -1,18 +1,20 @@ -Dashboard — innercontext +{m.dashboard_title()} — innercontext
-

Dashboard

-

Your recent health & skincare overview

+

{m.dashboard_title()}

+

{m.dashboard_subtitle()}

- Latest Skin Snapshot + {m["dashboard_latestSnapshot"]()} {#if data.latestSnapshot} @@ -51,7 +52,7 @@ {/if}
{:else} -

No skin snapshots yet.

+

{m["dashboard_noSnapshots"]()}

{/if} @@ -59,7 +60,7 @@ - Recent Routines + {m["dashboard_recentRoutines"]()} {#if data.recentRoutines.length} @@ -76,7 +77,7 @@ {/each} {:else} -

No routines in the past 2 weeks.

+

{m["dashboard_noRoutines"]()}

{/if}
diff --git a/frontend/src/routes/health/lab-results/+page.svelte b/frontend/src/routes/health/lab-results/+page.svelte index 6df401d..20597f9 100644 --- a/frontend/src/routes/health/lab-results/+page.svelte +++ b/frontend/src/routes/health/lab-results/+page.svelte @@ -1,6 +1,7 @@ -Lab Results — innercontext +{m["labResults_title"]()} — innercontext
-

Lab Results

-

{data.results.length} results

+

{m["labResults_title"]()}

+

{m["labResults_count"]({ count: data.results.length })}

@@ -51,12 +52,12 @@
{form.error}
{/if} {#if form?.created} -
Result added.
+
{m["labResults_added"]()}
{/if}
- Flag: + {m["labResults_flagFilter"]()}
- +
- - + +
- - + +
- +
- - + +
- +
- +
@@ -128,12 +129,12 @@ - Date - Test - LOINC - Value - Flag - Lab + {m["labResults_colDate"]()} + {m["labResults_colTest"]()} + {m["labResults_colLoinc"]()} + {m["labResults_colValue"]()} + {m["labResults_colFlag"]()} + {m["labResults_colLab"]()} @@ -165,7 +166,7 @@ {:else} - No lab results found. + {m["labResults_noResults"]()} {/each} diff --git a/frontend/src/routes/health/medications/+page.svelte b/frontend/src/routes/health/medications/+page.svelte index e33c79d..7e6edf7 100644 --- a/frontend/src/routes/health/medications/+page.svelte +++ b/frontend/src/routes/health/medications/+page.svelte @@ -1,6 +1,7 @@ -Medications — innercontext +{m.medications_title()} — innercontext
-

Medications

-

{data.medications.length} entries

+

{m.medications_title()}

+

{m.medications_count({ count: data.medications.length })}

@@ -40,40 +49,40 @@
{form.error}
{/if} {#if form?.created} -
Medication added.
+
{m.medications_added()}
{/if} {#if showForm} - New medication + {m["medications_newTitle"]()}
- +
- - + +
- - + +
- +
- +
@@ -86,21 +95,21 @@
- {med.kind} + {kindLabels[med.kind]?.() ?? med.kind} {med.product_name} {#if med.active_substance} {med.active_substance} {/if}
- {med.usage_history.length} usages + {m.medications_usages({ count: med.usage_history.length })}
{#if med.notes}

{med.notes}

{/if}
{:else} -

No medications recorded.

+

{m["medications_noMedications"]()}

{/each} diff --git a/frontend/src/routes/products/+page.svelte b/frontend/src/routes/products/+page.svelte index a8ab046..d97b7d6 100644 --- a/frontend/src/routes/products/+page.svelte +++ b/frontend/src/routes/products/+page.svelte @@ -1,6 +1,7 @@ -Products — innercontext +{m.products_title()} — innercontext
-

Products

-

{totalCount} products

+

{m.products_title()}

+

{m.products_count({ count: totalCount })}

- +
@@ -72,7 +73,7 @@ size="sm" onclick={() => ownershipFilter = f} > - {f === 'all' ? 'All' : f === 'owned' ? 'Owned' : 'Not owned'} + {f === 'all' ? m["products_filterAll"]() : f === 'owned' ? m["products_filterOwned"]() : m["products_filterUnowned"]()} {/each}
@@ -81,17 +82,17 @@
- Name - Brand - Targets - Time + {m["products_colName"]()} + {m["products_colBrand"]()} + {m["products_colTargets"]()} + {m["products_colTime"]()} {#if totalCount === 0} - No products found. + {m["products_noProducts"]()} {:else} diff --git a/frontend/src/routes/products/[id]/+page.svelte b/frontend/src/routes/products/[id]/+page.svelte index 0843bc5..017e71d 100644 --- a/frontend/src/routes/products/[id]/+page.svelte +++ b/frontend/src/routes/products/[id]/+page.svelte @@ -1,6 +1,7 @@ -New Product — innercontext +{m["products_newTitle"]()} — innercontext
- ← Products -

New Product

+ {m["products_backToList"]()} +

{m["products_newTitle"]()}

{#if form?.error} @@ -33,8 +34,8 @@
- - + +
diff --git a/frontend/src/routes/routines/+page.svelte b/frontend/src/routes/routines/+page.svelte index bea4647..4fa4acc 100644 --- a/frontend/src/routes/routines/+page.svelte +++ b/frontend/src/routes/routines/+page.svelte @@ -1,5 +1,6 @@ -Routines — innercontext +{m.routines_title()} — innercontext
-

Routines

-

{data.routines.length} routines (last 30 days)

+

{m.routines_title()}

+

{m.routines_count({ count: data.routines.length })}

- - + +
@@ -47,7 +48,7 @@ {routine.part_of_day.toUpperCase()} - {routine.steps?.length ?? 0} steps + {routine.steps?.length ?? 0} {m.common_steps()}
{#if routine.notes} {routine.notes} @@ -59,6 +60,6 @@ {/each} {:else} -

No routines found.

+

{m["routines_noRoutines"]()}

{/if} diff --git a/frontend/src/routes/routines/[id]/+page.svelte b/frontend/src/routes/routines/[id]/+page.svelte index 7ddb326..767349f 100644 --- a/frontend/src/routes/routines/[id]/+page.svelte +++ b/frontend/src/routes/routines/[id]/+page.svelte @@ -1,6 +1,7 @@ -Grooming Schedule — innercontext +{m.grooming_title()} — innercontext
- ← Routines -

Grooming Schedule

+ {m["grooming_backToRoutines"]()} +

{m.grooming_title()}

@@ -49,13 +60,13 @@
{form.error}
{/if} {#if form?.created} -
Wpis dodany.
+
{m["grooming_entryAdded"]()}
{/if} {#if form?.updated} -
Wpis zaktualizowany.
+
{m["grooming_entryUpdated"]()}
{/if} {#if form?.deleted} -
Wpis usunięty.
+
{m["grooming_entryDeleted"]()}
{/if} @@ -74,7 +85,7 @@ class="grid grid-cols-2 gap-4" >
- +
- - + +
- +
@@ -116,7 +127,7 @@ {#if schedule.length === 0} -

Brak wpisów. Kliknij "+ Dodaj wpis", aby zacząć.

+

{m["grooming_noEntries"]()}

{:else}
{#each byDay as { name, entries, day } (day)} @@ -138,19 +149,19 @@ size="sm" onclick={() => (editingId = editingId === entry.id ? null : entry.id)} > - {editingId === entry.id ? 'Anuluj' : 'Edytuj'} + {editingId === entry.id ? m.common_cancel() : m.common_edit()}
{ - if (!confirm('Usunąć ten wpis?')) e.preventDefault(); + if (!confirm(m["grooming_confirmDelete"]())) e.preventDefault(); }} >
@@ -172,7 +183,7 @@ >
- +
- - + +
- - +
diff --git a/frontend/src/routes/routines/new/+page.svelte b/frontend/src/routes/routines/new/+page.svelte index 9de88b0..2a40008 100644 --- a/frontend/src/routes/routines/new/+page.svelte +++ b/frontend/src/routes/routines/new/+page.svelte @@ -1,6 +1,7 @@ -New Routine — innercontext +{m["routines_newTitle"]()} — innercontext
- ← Routines -

New Routine

+ {m["routines_backToList"]()} +

{m["routines_newTitle"]()}

{#if form?.error} @@ -24,16 +25,16 @@ {/if} - Routine details + {m["routines_detailsTitle"]()}
- +
- + + +
- - + +
diff --git a/frontend/src/routes/routines/suggest/+page.svelte b/frontend/src/routes/routines/suggest/+page.svelte index 34a1052..d86ae9f 100644 --- a/frontend/src/routes/routines/suggest/+page.svelte +++ b/frontend/src/routes/routines/suggest/+page.svelte @@ -3,6 +3,7 @@ import { SvelteSet } from 'svelte/reactivity'; import type { ActionData, PageData } from './$types'; import type { BatchSuggestion, RoutineSuggestion, SuggestedStep } from '$lib/types'; + import { m } from '$lib/paraglide/messages.js'; import { Badge } from '$lib/components/ui/badge'; import { Button } from '$lib/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '$lib/components/ui/card'; @@ -37,7 +38,7 @@ return `${p.brand} ${p.name}`; } if (step.action_type) return step.action_type.replace(/_/g, ' '); - return step.action_notes ?? 'Unknown step'; + return step.action_notes ?? m.common_unknown(); } function stepMeta(step: SuggestedStep): string { @@ -64,7 +65,7 @@ suggestionPod = result.data.part_of_day as string; errorMsg = null; } else if (result.type === 'failure') { - errorMsg = (result.data?.error as string) ?? 'Błąd podczas generowania.'; + errorMsg = (result.data?.error as string) ?? m["suggest_errorDefault"](); } await update({ reset: false }); }; @@ -81,7 +82,7 @@ for (const d of batch.days) expandedDays.add(d.date); errorMsg = null; } else if (result.type === 'failure') { - errorMsg = (result.data?.error as string) ?? 'Błąd podczas generowania planu.'; + errorMsg = (result.data?.error as string) ?? m["suggest_errorBatch"](); } await update({ reset: false }); }; @@ -92,19 +93,19 @@ return async ({ result, update }: { result: { type: string; data?: Record }; update: (opts?: { reset?: boolean }) => Promise }) => { loadingSave = false; if (result.type === 'failure') { - errorMsg = (result.data?.error as string) ?? 'Błąd podczas zapisywania.'; + errorMsg = (result.data?.error as string) ?? m["suggest_errorSave"](); } await update({ reset: false }); }; } -Zaproponuj rutynę AI — innercontext +{m.suggest_title()} — innercontext
- ← Rutyny -

Propozycja rutyny AI

+ {m["suggest_backToRoutines"]()} +

{m.suggest_title()}

{#if errorMsg} @@ -113,41 +114,41 @@ - { errorMsg = null; }}>Jedna rutyna - { errorMsg = null; }}>Batch / Urlop + { errorMsg = null; }}>{m["suggest_singleTab"]()} + { errorMsg = null; }}>{m["suggest_batchTab"]()} - Parametry + {m["suggest_singleParams"]()}
- +
- +
- +
@@ -155,9 +156,9 @@ @@ -167,7 +168,7 @@ {#if suggestion}
-

Propozycja

+

{m["suggest_proposalTitle"]()}

{suggestionPod.toUpperCase()} @@ -206,13 +207,13 @@
@@ -222,27 +223,27 @@ - Zakres dat + {m["suggest_batchRange"]()}
- +
- +
- +
@@ -250,9 +251,9 @@ @@ -261,7 +262,7 @@ {#if batch}
-

Plan ({batch.days.length} dni)

+

{m["suggest_planTitle"]({ count: batch.days.length })}

{#if batch.overall_reasoning} @@ -285,7 +286,7 @@ {day.date}
- AM {day.am_steps.length} kroków · PM {day.pm_steps.length} kroków + AM {day.am_steps.length} {m["suggest_amSteps"]()} · PM {day.pm_steps.length} {m["suggest_pmSteps"]()} {isOpen ? '▲' : '▼'}
@@ -301,7 +302,7 @@
AM - {day.am_steps.length} kroków + {day.am_steps.length} {m["suggest_amSteps"]()}
{#if day.am_steps.length}
@@ -318,7 +319,7 @@ {/each}
{:else} -

Brak kroków AM.

+

{m["suggest_noAmSteps"]()}

{/if}
@@ -326,7 +327,7 @@
PM - {day.pm_steps.length} kroków + {day.pm_steps.length} {m["suggest_pmSteps"]()}
{#if day.pm_steps.length}
@@ -343,7 +344,7 @@ {/each}
{:else} -

Brak kroków PM.

+

{m["suggest_noPmSteps"]()}

{/if}
@@ -358,13 +359,13 @@
diff --git a/frontend/src/routes/skin/+page.svelte b/frontend/src/routes/skin/+page.svelte index 9f13c18..c399284 100644 --- a/frontend/src/routes/skin/+page.svelte +++ b/frontend/src/routes/skin/+page.svelte @@ -1,6 +1,7 @@ -Skin — innercontext +{m.skin_title()} — innercontext
-

Skin Snapshots

-

{data.snapshots.length} snapshots

+

{m.skin_title()}

+

{m.skin_count({ count: data.snapshots.length })}

@@ -129,13 +159,13 @@
{form.error}
{/if} {#if form?.created} -
Snapshot added.
+
{m["skin_snapshotAdded"]()}
{/if} {#if form?.updated} -
Snapshot updated.
+
{m["skin_snapshotUpdated"]()}
{/if} {#if form?.deleted} -
Snapshot deleted.
+
{m["skin_snapshotDeleted"]()}
{/if} {#if showForm} @@ -147,14 +177,14 @@ class="flex w-full items-center justify-between text-left" onclick={() => (aiPanelOpen = !aiPanelOpen)} > - AI analysis from photos + {m["skin_aiAnalysisTitle"]()} {aiPanelOpen ? '▲' : '▼'} {#if aiPanelOpen}

- Upload 1–3 photos of your skin. AI will pre-fill the form fields below. + {m["skin_aiUploadText"]()}

- {aiLoading ? 'Analyzing…' : 'Analyze photos'} + {aiLoading ? m.skin_analyzing() : m["skin_analyzePhotos"]()}
{/if} @@ -188,11 +218,11 @@ - New skin snapshot + {m["skin_newSnapshotTitle"]()}
- +
- +
- +
- +
- +
- - + +
- - + +
- - + +
- - + +
- - + +
- +
- +
@@ -333,147 +328,84 @@ >
- - + +
- + - (editOverallState = v)}> + {editOverallState ? stateLabels[editOverallState]?.() ?? editOverallState : m.common_select()} {#each states as s (s)} - {s} + {stateLabels[s]?.() ?? s} {/each}
- + - (editTexture = v)}> + {editTexture ? textureLabels[editTexture]?.() ?? editTexture : m.common_select()} {#each skinTextures as t (t)} - {t} + {textureLabels[t]?.() ?? t} {/each}
- + - (editSkinType = v)}> + {editSkinType ? skinTypeLabels[editSkinType]?.() ?? editSkinType : m.common_select()} {#each skinTypes as st (st)} - {st.replace(/_/g, ' ')} + {skinTypeLabels[st]?.() ?? st} {/each}
- + - (editBarrierState = v)}> + {editBarrierState ? barrierLabels[editBarrierState]?.() ?? editBarrierState : m.common_select()} {#each barrierStates as b (b)} - {b.replace(/_/g, ' ')} + {barrierLabels[b]?.() ?? b} {/each}
- - + +
- - + +
- - + +
- - + +
- - + +
- +
- - + +
{:else} @@ -482,34 +414,20 @@ {snap.snapshot_date}
{#if snap.overall_state} - - {snap.overall_state} + + {stateLabels[snap.overall_state]?.() ?? snap.overall_state} {/if} {#if snap.texture} - {snap.texture} + {textureLabels[snap.texture]?.() ?? snap.texture} {/if} -
-
@@ -517,20 +435,20 @@
{#if snap.hydration_level != null}
-

Hydration

+

{m["skin_hydrationLabel"]()}

{snap.hydration_level}/5

{/if} {#if snap.sensitivity_level != null}
-

Sensitivity

+

{m["skin_sensitivityLabel"]()}

{snap.sensitivity_level}/5

{/if} {#if snap.barrier_state}
-

Barrier

-

{snap.barrier_state.replace(/_/g, ' ')}

+

{m["skin_barrierLabel"]()}

+

{barrierLabels[snap.barrier_state]?.() ?? snap.barrier_state.replace(/_/g, ' ')}

{/if}
@@ -548,7 +466,7 @@
{:else} -

No skin snapshots yet.

+

{m["skin_noSnapshots"]()}

{/each}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index bf699a8..83e18dc 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,7 +1,12 @@ import { sveltekit } from '@sveltejs/kit/vite'; import tailwindcss from '@tailwindcss/vite'; import { defineConfig } from 'vite'; +import { paraglideVitePlugin } from '@inlang/paraglide-js'; export default defineConfig({ - plugins: [tailwindcss(), sveltekit()] + plugins: [ + paraglideVitePlugin({ project: './project.inlang', outdir: './src/lib/paraglide' }), + tailwindcss(), + sveltekit() + ] });