feat(frontend): add PL/EN i18n using @inlang/paraglide-js v2

- Install @inlang/paraglide-js v2 with Vite plugin and paraglideMiddleware hook
- Add messages/pl.json and messages/en.json with ~400 translation keys
- Create project.inlang/settings.json (PL as base locale)
- Add LanguageSwitcher component (cookie-based, no URL prefix needed)
- Replace all hardcoded strings across 14 pages/components with m.*() calls
- ProductForm uses derived label maps for all enum types (category, texture, etc.)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Piotr Oleszczyk 2026-03-01 13:20:34 +01:00
parent 9524e4df54
commit 99584521a1
22 changed files with 1742 additions and 612 deletions

437
frontend/messages/pl.json Normal file
View file

@ -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 13 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 (15)",
"skin_sensitivity": "Wrażliwość (15)",
"skin_sebumTzone": "Sebum T-zone (15)",
"skin_sebumCheeks": "Sebum policzki (15)",
"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 (05)",
"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"
}