From 3a6ae4a64ad11c62794cea752415092a8f28fd1a Mon Sep 17 00:00:00 2001 From: Ulas Date: Sun, 5 Apr 2026 12:01:16 +0200 Subject: [PATCH] feat(i18n): add Swedish (sv) translation and Italian as explicit language option (#19) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swedish translation contributed by @olsson82 (PR #19), integrated with minor corrections (dayShortSunday: Sun → Sön, amountLabel aligned with v0.11.2, new v0.11.2 currency keys added). Italian was already supported server-side but is now explicitly listed in the locale picker alongside German, English, and Swedish. --- CHANGELOG.md | 6 + package.json | 2 +- public/components/oikos-locale-picker.js | 1 + public/i18n.js | 2 +- public/locales/sv.json | 552 +++++++++++++++++++++++ 5 files changed, 561 insertions(+), 2 deletions(-) create mode 100644 public/locales/sv.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 64232c2..bf40715 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.11.3] - 2026-04-05 + +### Added +- Swedish (Svenska) translation - contributed by @olsson82 (#19) +- Italian (Italiano) is now explicitly listed as a language option in Settings + ## [0.11.2] - 2026-04-05 ### Added diff --git a/package.json b/package.json index a294e6f..ff88856 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oikos", - "version": "0.11.2", + "version": "0.11.3", "description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.", "main": "server/index.js", "type": "module", diff --git a/public/components/oikos-locale-picker.js b/public/components/oikos-locale-picker.js index fedee5f..1a4eb29 100644 --- a/public/components/oikos-locale-picker.js +++ b/public/components/oikos-locale-picker.js @@ -11,6 +11,7 @@ const LOCALE_LABELS = { de: 'Deutsch', en: 'English', it: 'Italiano', + sv: 'Svenska', }; class OikosLocalePicker extends HTMLElement { diff --git a/public/i18n.js b/public/i18n.js index 16519bd..3d09c56 100644 --- a/public/i18n.js +++ b/public/i18n.js @@ -5,7 +5,7 @@ * Dependencies: none (vanilla JS, Fetch API, Intl API) */ -const SUPPORTED_LOCALES = ['de', 'en', 'it']; +const SUPPORTED_LOCALES = ['de', 'en', 'it', 'sv']; const DEFAULT_LOCALE = 'de'; const STORAGE_KEY = 'oikos-locale'; diff --git a/public/locales/sv.json b/public/locales/sv.json new file mode 100644 index 0000000..dc74d38 --- /dev/null +++ b/public/locales/sv.json @@ -0,0 +1,552 @@ +{ + "common": { + "save": "Spara", + "cancel": "Avbryt", + "delete": "Radera", + "edit": "Redigera", + "close": "Stäng", + "create": "Skapa", + "add": "Lägg till", + "back": "Tillbaka", + "next": "Nästa", + "loading": "Laddar…", + "saving": "Sparar…", + "required": "Detta fält är obligatoriskt.", + "error": "Fel", + "allFieldsRequired": "Vänligen fyll i alla fält.", + "today": "I dag", + "tomorrow": "I morgon", + "skipToContent": "Hoppa till innehållet", + "reload": "Ladda om", + "errorOccurred": "Något gick fel.", + "unexpectedError": "Ett oväntat fel inträffade.", + "errorGeneric": "Ett fel uppstod.", + "updateAvailable": "Uppdatering tillgänglig - ladda om sidan för att få den senaste versionen.", + "titleRequired": "Titel krävs", + "nameRequired": "Namn krävs", + "contentRequired": "Innehåll krävs", + "all": "Alla", + "unknownError": "Okänt fel" + }, + + "nav": { + "dashboard": "Översikt", + "tasks": "Uppgifter", + "calendar": "Kalender", + "meals": "Måltider", + "shopping": "Shopping", + "notes": "Anteckningar", + "contacts": "Kontakter", + "budget": "Budget", + "settings": "Inställningar", + "main": "Huvudnavigering", + "navigation": "Navigering", + "quickActions": "Snabba åtgärder" + }, + + "dashboard": { + "title": "Översikt", + "greetingMorning": "God morgon, {{name}}", + "greetingDay": "God eftermiddag, {{name}}", + "greetingEvening": "God kväll, {{name}}", + "allDone": "Allt klart", + "noEvents": "Inga händelser", + "noPinnedNotes": "Inga fästa anteckningar", + "todayMeals": "Dagens måltider", + "allLink": "Alla", + "weekLink": "Vecka", + "urgentTasksChip": "{{count}} brådskande uppgift", + "urgentTasksChipPlural": "{{count}} brådskande uppgifter", + "eventsChip": "{{count}} händelse idag", + "eventsChipPlural": "{{count}} evenemang idag", + "todayMealChip": "Idag: {{title}}", + "loadError": "Instrumentpanelen kunde inte laddas helt.", + "weatherRefresh": "Uppdatera vädret", + "weatherRefreshTitle": "Uppdatera", + "weatherFeelsLike": "Känns som {{temp}}° · {{humidity}}% · Vind {{wind}} km/h", + "fabTaskLabel": "Lägg till uppgift", + "fabCalendarLabel": "Lägg till händelse", + "fabShoppingLabel": "Lägg till shopping", + "fabNoteLabel": "Lägg till anteckning", + "fabTask": "Uppgift", + "fabCalendar": "Händelse", + "fabShopping": "Shopping", + "fabNote": "Anteckning", + "overdue": "Försenad", + "dueSoon": "Förfaller idag", + "dueTomorrow": "Förfaller imorgon", + "allDay": "Hela dagen", + "shoppingMore": "+{{count}} till" + }, + + "tasks": { + "title": "Uppgifter", + "newTask": "Ny uppgift", + "editTask": "Redigera uppgift", + "emptyTitle": "Inga uppgifter - allt klart?", + "emptyDescription": "Skapa nya uppgifter med + knappen.", + "titleLabel": "Titel *", + "titlePlaceholder": "Vad behöver göras?", + "descriptionLabel": "Anteckning", + "descriptionPlaceholder": "Valfria detaljer...", + "priorityLabel": "Prioritet", + "categoryLabel": "Kategori", + "dueDateLabel": "Förfallo datum", + "dueTimeLabel": "Tid", + "assignedLabel": "Tilldelad till", + "assignedNobody": "- Ingen -", + "statusLabel": "Status", + "priorityUrgent": "Brådskande", + "priorityHigh": "Hög", + "priorityMedium": "Medium", + "priorityLow": "Låg", + "priorityNone": "Ingen", + "statusOpen": "Öppna", + "statusInProgress": "Pågår", + "statusDone": "Slutfört", + "categoryHousehold": "Hushåll", + "categorySchool": "Skola", + "categoryShopping": "Shopping", + "categoryRepair": "Reparera", + "categoryHealth": "Hälsa", + "categoryFinance": "Finansiera", + "categoryLeisure": "Fritid", + "categoryMisc": "Diverse", + "overdue": "Försenad", + "overdueDay": "{{count}}d försenad", + "dueToday": "Förfaller idag", + "dueTomorrow": "Förfaller imorgon", + "groupOverdue": "Försenad", + "groupToday": "I dag", + "groupThisWeek": "Denna vecka", + "groupNextWeek": "Nästa vecka", + "groupLater": "Senare", + "groupNoDate": "Inget datum", + "markDone": "Markera {{title}} som klar", + "editButton": "Redigera uppgift", + "swipeOpen": "Öppna igen", + "swipeDone": "Klart", + "swipeEdit": "Redigera", + "subtaskAdd": "+ Lägg till deluppgift", + "subtaskToggle": "Visa deluppgifter", + "subtaskMarkDone": "Markera {{title}} som klar", + "deleteConfirm": "Ta bort uppgift och alla deluppgifter?", + "savedToast": "Uppgiften sparad.", + "createdToast": "Uppgift skapad.", + "deletedToast": "Uppgiften raderad.", + "loadError": "Uppgiften kunde inte laddas.", + "subtaskPrompt": "Deluppgift:", + "kanbanOpen": "Öppna", + "kanbanInProgress": "Pågår", + "kanbanDone": "Slutfört", + "recurring": "Återkommande", + "listView": "Listvy", + "kanbanView": "Kanban-vy" + }, + + "shopping": { + "title": "Shopping", + "noLists": "Inga listor", + "noListsDescription": "Skapa en lista med + knappen.", + "emptyList": "Listan är tom", + "emptyListDescription": "Lägg till objekt med inmatningsfältet ovan.", + "newListPrompt": "Namn på den nya listan:", + "newListButton": "Skapa ny lista", + "renameListPrompt": "Nytt listnamn:", + "deleteListConfirm": "Ta bort listan \"{{name}}\" och alla objekt?", + "deletedListToast": "Lista raderad.", + "itemsRemovedToast": "{{count}} objekt har tagits bort.", + "clearChecked": "Ta bort markerad ({{count}})", + "itemNamePlaceholder": "Lägg till objekt...", + "itemQtyPlaceholder": "Kvantitet", + "itemNameLabel": "Objektets namn", + "itemQtyLabel": "Kvantitet", + "categoryLabel": "Kategori", + "addItemLabel": "Lägg till objekt", + "renameListLabel": "Byt namn på listan", + "deleteListLabel": "Ta bort lista", + "swipeBack": "Ångra", + "swipeCheck": "Bocka av", + "swipeDelete": "Radera", + "markDoneLabel": "Bocka av {{name}}", + "markUndoneLabel": "Avmarkera {{name}}", + "deleteItemLabel": "Ta bort {{name}}", + "listsLoadError": "Det gick inte att ladda listor.", + "itemsLoadError": "Objekt kunde inte laddas.", + "catFruitVeg": "Frukt & Grönt", + "catBakery": "Bageri", + "catDairy": "Mejeri", + "catMeatFish": "Kött & Fisk", + "catFrozen": "Frysvaror", + "catDrinks": "Drycker", + "catHousehold": "Hushåll", + "catDrugstore": "Apotek", + "catMisc": "Diverse" + }, + + "meals": { + "title": "Måltidsplan", + "noMealPlanned": "Ingen måltid planerad", + "addMeal": "Lägg till {{type}}", + "editMeal": "Redigera måltid", + "addMealTitle": "Lägg till måltid", + "deleteMeal": "Ta bort måltid", + "transferToShoppingList": "Lägg till ingredienser till inköpslistan", + "today": "I dag", + "prevWeek": "Föregående vecka", + "nextWeek": "Nästa vecka", + "loadError": "Det gick inte att läsa in måltidsplanen.", + "typeBreakfast": "Frukost", + "typeLunch": "Lunch", + "typeDinner": "Middag", + "typeSnack": "Mellanmål", + "dayMo": "Mån", + "dayDi": "Tis", + "dayMi": "Ons", + "dayDo": "Tor", + "dayFr": "Fre", + "daySa": "Lö", + "daySo": "Sön", + "dateLabel": "Datum", + "mealTypeLabel": "Måltid", + "titleLabel": "Titel *", + "titlePlaceholder": "till exempel Spaghetti Bolognese", + "notesLabel": "Anteckningar", + "notesPlaceholder": "Frivillig…", + "ingredientsLabel": "Ingredienser", + "addIngredient": "Tillsätt ingrediens", + "ingredientNamePlaceholder": "Ingrediens", + "ingredientQtyPlaceholder": "Kvantitet", + "removeIngredient": "Ta bort ingrediensen", + "transferLabel": "Överför ingredienserna till inköpslistan", + "transferNow": "Överför nu", + "noShoppingLists": "Inga inköpslistor tillgängliga", + "transferSuccess": "{{count}} ingrediens har överförts", + "transferSuccessPlural": "{{count}} ingredienser har överförts", + "transferAlreadyDone": "Alla ingredienser är redan överförda", + "ingredientCount": "{{count}} ingrediens", + "ingredientCountPlural": "{{count}} ingredienser", + "titleRequired": "Titel krävs", + "loadingIndicator": "Laddar…" + }, + + "calendar": { + "title": "Kalender", + "newEvent": "Ny händelse", + "editEvent": "Redigera händelse", + "addEvent": "Lägg till händelse", + "deleteEvent": "Ta bort händelse", + "noEvents": "Inga händelser under den valda perioden.", + "today": "I dag", + "back": "Tillbaka", + "forward": "Fram", + "viewMonth": "Månad", + "viewWeek": "Vecka", + "viewDay": "Dag", + "viewAgenda": "Agenda", + "allDay": "Hela dagen", + "allDayShort": "hela dagen", + "moreEvents": "+{{count}} fler", + "weekNumberLabel": "V{{week}} · {{month}} {{year}}", + "agendaFrom": "Från {{date}}", + "titleLabel": "Titel *", + "titlePlaceholder": "till exempel Tandläkare", + "allDayToggle": "Hela dagen", + "startDateLabel": "Startdatum", + "startTimeLabel": "Starttid", + "endDateLabel": "Slutdatum", + "endTimeLabel": "Sluttid", + "fromLabel": "Från", + "toLabel": "Till", + "locationLabel": "Plats", + "locationPlaceholder": "Frivillig", + "assignedLabel": "Tilldelad till", + "assignedNobody": "- Ingen -", + "colorLabel": "Färg", + "descriptionLabel": "Beskrivning", + "descriptionPlaceholder": "Frivillig…", + "popupEdit": "Redigera", + "deleteConfirm": "Vill du verkligen ta bort \"{{title}}\"?", + "createdToast": "Händelse skapad", + "savedToast": "Händelsen har sparats", + "deletedToast": "Händelse raderad", + "loadError": "Händelser kunde inte laddas.", + "saveError": "Det gick inte att spara", + "deleteError": "Fel vid borttagning", + "titleRequired": "Titel krävs", + "monthJanuary": "Januari", + "monthFebruary": "Februari", + "monthMarch": "Mars", + "monthApril": "April", + "monthMay": "Maj", + "monthJune": "Juni", + "monthJuly": "Juli", + "monthAugust": "Augusti", + "monthSeptember": "September", + "monthOctober": "Oktober", + "monthNovember": "November", + "monthDecember": "December", + "dayShortSunday": "Sön", + "dayShortMonday": "Mån", + "dayShortTuesday": "Tis", + "dayShortWednesday": "Ons", + "dayShortThursday": "Tor", + "dayShortFriday": "Fre", + "dayShortSaturday": "Lör", + "dayLongSunday": "Söndag", + "dayLongMonday": "Måndag", + "dayLongTuesday": "Tisdag", + "dayLongWednesday": "Onsdag", + "dayLongThursday": "Torsdag", + "dayLongFriday": "Fredag", + "dayLongSaturday": "Lördag", + "timeSuffix": "", + "colorLabel": "Färg {{color}}" + }, + + "notes": { + "title": "Anteckningar", + "newNote": "Ny anteckning", + "editNote": "Redigera anteckning", + "addNoteLabel": "Ny anteckning", + "searchPlaceholder": "Sök anteckningar...", + "emptyTitle": "Inga anteckningar ännu", + "emptyDescription": "Skapa en ny anteckning med + knappen.", + "noResultsTitle": "Inga resultat", + "noResultsDescription": "Ingen anteckning innehåller \"{{query}}\".", + "titleLabel": "Titel (valfritt)", + "titlePlaceholder": "Ingen titel", + "contentLabel": "Innehåll", + "contentMarkdownHint": "(Markdown-formatering stöds)", + "contentPlaceholder": "Ange anteckning...", + "colorLabel": "Färg", + "pinnedLabel": "Fäst (visas på instrumentpanelen)", + "pinAction": "Fäst", + "unpinAction": "Lossa", + "deleteLabel": "Ta bort anteckning", + "deleteConfirm": "Vill du verkligen ta bort den här anteckningen?", + "createdToast": "Anteckning skapad", + "savedToast": "Anteckningen sparad", + "deletedToast": "Anteckningen raderad", + "loadError": "Det gick inte att ladda anteckningar.", + "formatBold": "Fet (Ctrl+B)", + "formatItalic": "Kursiv (Ctrl+I)", + "formatUnderline": "Understrykning (Ctrl+U)", + "formatStrikethrough": "Genomstruken", + "formatHeading": "Rubrik", + "formatList": "Kullista", + "formatOrderedList": "Numrerad lista", + "formatChecklist": "Checklista", + "formatLink": "Länk", + "formatCode": "Kod", + "formatQuote": "Citationstecken", + "formatDivider": "Delare" + }, + + "contacts": { + "title": "Kontakter", + "newContact": "Ny kontakt", + "editContact": "Redigera kontakt", + "addButton": "Ny", + "newContactLabel": "Ny kontakt", + "searchPlaceholder": "Sök på namn, telefon eller e-post...", + "importButton": "Importera", + "importLabel": "Importera kontakt från vCard", + "importTooltip": "Importera vCard", + "emptyTitle": "Inga kontakter än", + "emptyDescription": "Lägg till nya kontakter med + knappen.", + "filterAll": "Alla", + "nameLabel": "Namn *", + "namePlaceholder": "Fullständigt namn", + "categoryLabel": "Kategori", + "phoneLabel": "Telefon", + "phonePlaceholder": "+46 …", + "emailLabel": "E-post", + "emailPlaceholder": "namn@exempel.se", + "addressLabel": "Adress", + "addressPlaceholder": "Gatunamn, Postnummer Stad", + "notesLabel": "Anteckningar", + "notesPlaceholder": "Frivillig…", + "callLabel": "Samtal", + "emailActionLabel": "E-post", + "mapsLabel": "Öppna i Kartor", + "exportLabel": "Exportera som vCard", + "exportTooltip": "Exportera vCard", + "deleteLabel": "Ta bort kontakt", + "deleteConfirm": "Vill du verkligen ta bort den här kontakten?", + "deletePersonConfirm": "Vill du verkligen ta bort \"{{name}}\"?", + "savedToast": "Kontakten har sparats", + "updatedToast": "Kontakten uppdaterad", + "deletedToast": "Kontakt raderad", + "importedToast": "{{name}} har importerats.", + "importError": "Import misslyckades: {{error}}", + "vcardNoName": "vCard innehåller inget namn.", + "catDoctor": "Läkare", + "catSchool": "Skola/Barnomsorg", + "catAuthority": "Myndighet", + "catInsurance": "Försäkring", + "catCraftsman": "Handlare", + "catEmergency": "Nödsituation", + "catMisc": "Diverse", + "categoryDoctor": "Läkare", + "categorySchool": "Skola/daghem", + "categoryAuthority": "Myndighet", + "categoryInsurance": "Försäkring", + "categoryCraftsman": "Handlare", + "categoryEmergency": "Nödsituation", + "categoryOther": "Andra" + }, + + "budget": { + "title": "Budget", + "newEntry": "Nytt inlägg", + "editEntry": "Redigera inlägg", + "addEntryLabel": "Lägg till inlägg", + "newEntryFabLabel": "Nytt inlägg", + "currentMonth": "Nuvarande", + "prevMonth": "Föregående månad", + "nextMonth": "Nästa månad", + "income": "Inkomst", + "expenses": "Utgifter", + "balance": "Balans", + "byCategory": "Efter kategori", + "transactions": "Transaktioner", + "emptyTitle": "Inga inlägg denna månad", + "emptyDescription": "Lägg till budgetposter med + knappen.", + "csvExport": "CSV", + "typeExpense": "Utgift", + "typeIncome": "Inkomst", + "titleLabel": "Titel *", + "titlePlaceholder": "till exempel Stormarknad", + "amountLabel": "Belopp *", + "amountPlaceholder": "0,00", + "categoryLabel": "Kategori", + "dateLabel": "Datum *", + "recurringLabel": "Återkommande", + "deleteLabel": "Ta bort post", + "deleteConfirm": "Vill du verkligen ta bort den här posten?", + "deletePersonConfirm": "Vill du verkligen ta bort \"{{title}}\"?", + "addedToast": "Post tillagd", + "savedToast": "Posten sparad", + "deletedToast": "Posten raderad", + "loadError": "Budget kunde inte laddas.", + "trendNeutral": "- samma som {{month}}", + "validAmountRequired": "Ange ett giltigt belopp", + "dateRequired": "Datum krävs", + "catFood": "Specerier", + "catRent": "Hyra", + "catInsurance": "Försäkring", + "catMobility": "Transport", + "catLeisure": "Fritid", + "catClothing": "Kläder", + "catHealth": "Hälsa", + "catEducation": "Utbildning", + "catMisc": "Diverse", + "loadingIndicator": "Laddar…" + }, + + "settings": { + "title": "Inställningar", + "sectionDesign": "Utseende", + "sectionAccount": "Mitt konto", + "sectionCalendarSync": "Kalendersynkronisering", + "sectionFamily": "Familjemedlemmar", + "cardAppearance": "Visa", + "themeSystem": "System", + "themeSysLabel": "Använd systeminställning", + "themeLight": "Ljus", + "themeLightLabel": "Ljusläge", + "themeDark": "Mörk", + "themeDarkLabel": "Mörkt läge", + "changePassword": "Byt lösenord", + "currentPasswordLabel": "Aktuellt lösenord", + "newPasswordLabel": "Nytt lösenord", + "confirmPasswordLabel": "Bekräfta nytt lösenord", + "savePassword": "Spara lösenord", + "passwordMismatch": "Lösenord stämmer inte överens.", + "passwordSavedToast": "Lösenordet har ändrats.", + "googleCalendar": "Google Kalender", + "appleCalendar": "Apple Calendar (iCloud)", + "syncNow": "Synkronisera nu", + "disconnect": "Koppla från", + "connectGoogle": "Anslut till Google", + "connected": "Ansluten", + "connectedLastSync": "Ansluten · Senast: {{date}}", + "notConnected": "Ej ansluten", + "notConfigured": "Ej konfigurerad (saknar .env-variabler)", + "configured": "Konfigurerad (via .env)", + "configuredLastSync": "Konfigurerad (via .env) · Senast: {{date}}", + "syncSuccess": "{{provider}} synkroniserad.", + "disconnectedToast": "{{provider}} frånkopplad.", + "googleOnlyAdmin": "Endast administratörer kan ansluta Google Kalender.", + "appleOnlyAdmin": "Endast admin kan ansluta Apple Calendar.", + "caldavUrlLabel": "CalDAV Server URL", + "caldavUrlPlaceholder": "https://caldav.icloud.com", + "appleIdLabel": "Apple ID (e-post)", + "applePasswordLabel": "Appspecifikt lösenord", + "applePasswordHint": "Skapa lösenord på appleid.apple.com → Säkerhet.", + "appleConnectBtn": "Anslut & testa", + "appleConnecting": "Ansluter...", + "appleConnectedToast": "Apple Calendar ansluten.", + "syncSuccessGoogle": "Kalendersynkronisering med Google ansluten.", + "syncSuccessApple": "Kalendersynkronisering med Apple ansluten.", + "syncErrorGoogle": "Anslutningen till Google misslyckades. Försök igen.", + "syncErrorApple": "Anslutningen till Apple misslyckades. Försök igen.", + "addMember": "+ Lägg till medlem", + "newMemberTitle": "Ny familjemedlem", + "usernameLabel": "Användarnamn", + "displayNameLabel": "Visningsnamn", + "memberPasswordLabel": "Lösenord", + "colorLabel": "Färg", + "roleLabel": "Roll", + "roleMember": "Medlem", + "roleAdmin": "Admin", + "createMember": "Skapa", + "cancelAddMember": "Avbryt", + "memberAddedToast": "{{name}} har lagts till.", + "deleteMemberConfirm": "Vill du verkligen ta bort {{name}}?", + "memberDeletedToast": "{{name}} raderade.", + "deleteMemberLabel": "Radera", + "logout": "Logga ut", + "synchronizing": "Synkroniseras...", + "googleDisconnectConfirm": "Koppla bort Google Kalender?", + "appleDisconnectConfirm": "Koppla bort Apple Calendar?", + "localeSystem": "System", + "localeLabel": "Språk", + "languageTitle": "Språk", + "sectionMeals": "Måltidsplan", + "mealTypesLabel": "Synliga måltider", + "mealTypesHint": "Endast utvalda måltidstyper visas i måltidsplaneraren.", + "mealTypesSaved": "Inställningar för måltidsplan har sparats.", + "mealTypesMinOne": "Minst en måltidstyp måste vara aktiv.", + "sectionBudget": "Budget", + "currencyLabel": "Valuta", + "currencyHint": "Ställer in valutan som används i hela budgetavsnittet.", + "currencySaved": "Valuta sparad." + }, + + "login": { + "tagline": "Familjeplanering. Säker. Sekretessvänlig. Öppen källkod.", + "usernameLabel": "Användarnamn", + "usernamePlaceholder": "användarnamn", + "passwordLabel": "Lösenord", + "passwordPlaceholder": "••••••••", + "loginButton": "Logga in", + "loggingIn": "Loggar in...", + "tooManyAttempts": "För många försök. Vänta ett ögonblick.", + "invalidCredentials": "Ogiltiga användaruppgifter." + }, + + "install": { + "title": "Installera Oikos", + "subtitle": "Lägg till på startskärmen", + "iosTip1": "Tryck", + "iosTip2": "→ \"Lägg till på startskärmen\"", + "installButton": "Installera", + "dismissLabel": "Stäng" + }, + + "modal": { + "closeLabel": "Stäng" + } +}