Merge branch 'main' of github.com:rafaelfoster/oikos

This commit is contained in:
Rafael Foster
2026-04-29 19:44:18 -03:00
31 changed files with 507 additions and 208 deletions
+23
View File
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [0.36.1] - 2026-04-29
### Fixed
- Date input: default date format changed from US (`MM/DD/YYYY`) to day-month-year (`DD.MM.YYYY`) for new users
- Date input: dot-separated dates (`DD.MM.YYYY`) are now accepted in addition to slash-separated dates
- Date input: `dmy` placeholder and display format updated to use dots instead of slashes
## [0.36.0] - 2026-04-29
### Added
- Navigation: Kitchen (Meals/Recipes/Shopping) is now grouped as a single "Küche" entry in the desktop sidebar, consistent with the mobile bottom bar
- UX: empty states in Tasks, Notes, Contacts, Shopping, Recipes and Budget now include a primary CTA button that triggers the page FAB
- UX: `friendlyError(err)` helper added to `window.oikos`; unhandled promise rejections now show status-code-aware messages (offline, forbidden, not found, server error, timeout) instead of raw error text
- i18n: five new `common.error*` keys (offline, forbidden, notFound, server, timeout) added to all 15 locale files
### Changed
- Navigation: more-button icon changed from `grid-2x2` to `ellipsis` (matches the sheet it opens)
- Navigation: desktop sidebar expands labels at 1 280 px instead of 1 440 px
- UX: search overlay input field is now at the top, results below (standard top-to-bottom scan path)
- UX: touch targets for kitchen tabs and shopping list tabs raised to 44 px (iOS minimum)
- UX: dashboard metric values enlarged to `xl`/`bold` and labels styled as `2xs`/`uppercase` for clearer data hierarchy
- Onboarding: step 2 text and icon updated to accurately describe the navigation structure (···-button and module groups); step 3 text and icon updated to explain the FAB and swipe gestures
## [0.35.0] - 2026-04-29 ## [0.35.0] - 2026-04-29
### Added ### Added
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "oikos", "name": "oikos",
"version": "0.34.1", "version": "0.36.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "oikos", "name": "oikos",
"version": "0.34.1", "version": "0.36.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"bcrypt": "^6.0.0", "bcrypt": "^6.0.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "oikos", "name": "oikos",
"version": "0.35.0", "version": "0.36.1",
"description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.", "description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.",
"main": "server/index.js", "main": "server/index.js",
"type": "module", "type": "module",
+4 -4
View File
@@ -9,7 +9,7 @@ const SUPPORTED_LOCALES = ['de', 'en', 'es', 'fr', 'it', 'sv', 'el', 'ru', 'tr',
const DEFAULT_LOCALE = 'de'; const DEFAULT_LOCALE = 'de';
const STORAGE_KEY = 'oikos-locale'; const STORAGE_KEY = 'oikos-locale';
const DATE_FORMAT_KEY = 'oikos-date-format'; const DATE_FORMAT_KEY = 'oikos-date-format';
const DEFAULT_DATE_FORMAT = 'mdy'; const DEFAULT_DATE_FORMAT = 'dmy';
let currentLocale = DEFAULT_LOCALE; let currentLocale = DEFAULT_LOCALE;
let translations = {}; let translations = {};
@@ -100,7 +100,7 @@ function formatDateParts(date, useUtc = false) {
const month = String((useUtc ? d.getUTCMonth() : d.getMonth()) + 1).padStart(2, '0'); const month = String((useUtc ? d.getUTCMonth() : d.getMonth()) + 1).padStart(2, '0');
const day = String(useUtc ? d.getUTCDate() : d.getDate()).padStart(2, '0'); const day = String(useUtc ? d.getUTCDate() : d.getDate()).padStart(2, '0');
switch (getDateFormatPreference()) { switch (getDateFormatPreference()) {
case 'dmy': return `${day}/${month}/${year}`; case 'dmy': return `${day}.${month}.${year}`;
case 'ymd': return `${year}-${month}-${day}`; case 'ymd': return `${year}-${month}-${day}`;
default: return `${month}/${day}/${year}`; default: return `${month}/${day}/${year}`;
} }
@@ -127,7 +127,7 @@ export function formatDate(date) {
export function dateInputPlaceholder() { export function dateInputPlaceholder() {
switch (getDateFormatPreference()) { switch (getDateFormatPreference()) {
case 'dmy': return 'DD/MM/YYYY'; case 'dmy': return 'DD.MM.YYYY';
case 'ymd': return 'YYYY-MM-DD'; case 'ymd': return 'YYYY-MM-DD';
default: return 'MM/DD/YYYY'; default: return 'MM/DD/YYYY';
} }
@@ -145,7 +145,7 @@ export function parseDateInput(value) {
const isoMatch = raw.match(/^(\d{4})-(\d{2})-(\d{2})$/); const isoMatch = raw.match(/^(\d{4})-(\d{2})-(\d{2})$/);
if (isoMatch) return isValidDateParts(isoMatch[1], isoMatch[2], isoMatch[3]) ? raw : ''; if (isoMatch) return isValidDateParts(isoMatch[1], isoMatch[2], isoMatch[3]) ? raw : '';
const slashMatch = raw.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/); const slashMatch = raw.match(/^(\d{1,2})[\/.](\d{1,2})[\/.](\d{4})$/);
if (!slashMatch) return ''; if (!slashMatch) return '';
const [, first, second, year] = slashMatch; const [, first, second, year] = slashMatch;
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "خطأ غير معروف", "unknownError": "خطأ غير معروف",
"confirm": "تأكيد", "confirm": "تأكيد",
"undo": "تراجع", "undo": "تراجع",
"reset": "إعادة التعيين للأصل" "reset": "إعادة التعيين للأصل",
"errorOffline": "لا يوجد اتصال بالإنترنت. يرجى التحقق من شبكتك.",
"errorForbidden": "تم رفض الوصول. يرجى تسجيل الدخول مرة أخرى.",
"errorNotFound": "لم يتم العثور على السجل.",
"errorServer": "خطأ في الخادم. يرجى المحاولة لاحقاً.",
"errorTimeout": "استغرق الاتصال وقتاً طويلاً. يرجى المحاولة مجدداً."
}, },
"nav": { "nav": {
"dashboard": "لوحة التحكم", "dashboard": "لوحة التحكم",
@@ -187,7 +192,8 @@
"archiveButton": "أرشفة المهمة", "archiveButton": "أرشفة المهمة",
"archivedToast": "تم أرشفة المهمة.", "archivedToast": "تم أرشفة المهمة.",
"kanbanArchived": "مؤرشف", "kanbanArchived": "مؤرشف",
"reminderNeedsDueDate": "حدّد تاريخ استحقاق لتفعيل تذكيرات المهمة." "reminderNeedsDueDate": "حدّد تاريخ استحقاق لتفعيل تذكيرات المهمة.",
"emptyAction": "إنشاء مهمة"
}, },
"shopping": { "shopping": {
"title": "التسوق", "title": "التسوق",
@@ -227,7 +233,8 @@
"catDrinks": "مشروبات", "catDrinks": "مشروبات",
"catHousehold": "مستلزمات المنزل", "catHousehold": "مستلزمات المنزل",
"catDrugstore": "صيدلية", "catDrugstore": "صيدلية",
"catMisc": "متنوع" "catMisc": "متنوع",
"emptyAction": "إضافة عنصر"
}, },
"meals": { "meals": {
"title": "خطة الوجبات", "title": "خطة الوجبات",
@@ -403,7 +410,8 @@
"formatLink": "رابط", "formatLink": "رابط",
"formatCode": "كود", "formatCode": "كود",
"formatQuote": "اقتباس", "formatQuote": "اقتباس",
"formatDivider": "فاصل" "formatDivider": "فاصل",
"emptyAction": "إنشاء ملاحظة"
}, },
"contacts": { "contacts": {
"title": "جهات الاتصال", "title": "جهات الاتصال",
@@ -456,7 +464,8 @@
"categoryInsurance": "تأمين", "categoryInsurance": "تأمين",
"categoryCraftsman": "حرفي", "categoryCraftsman": "حرفي",
"categoryEmergency": "طوارئ", "categoryEmergency": "طوارئ",
"categoryOther": "متنوع" "categoryOther": "متنوع",
"emptyAction": "إضافة جهة اتصال"
}, },
"budget": { "budget": {
"title": "الميزانية", "title": "الميزانية",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Name of the new category:", "newCategoryPrompt": "Name of the new category:",
"newSubcategoryPrompt": "Name of the new subcategory:", "newSubcategoryPrompt": "Name of the new subcategory:",
"categoryAddedToast": "Category added.", "categoryAddedToast": "Category added.",
"subcategoryAddedToast": "Subcategory added." "subcategoryAddedToast": "Subcategory added.",
"emptyAction": "إضافة إدخال"
}, },
"settings": { "settings": {
"title": "الإعدادات", "title": "الإعدادات",
@@ -843,7 +853,8 @@
"titleRequired": "العنوان مطلوب", "titleRequired": "العنوان مطلوب",
"duplicate": "نسخ", "duplicate": "نسخ",
"duplicated": "تم نسخ الوصفة.", "duplicated": "تم نسخ الوصفة.",
"copySuffix": "نسخة" "copySuffix": "نسخة",
"emptyAction": "إنشاء وصفة"
}, },
"search": { "search": {
"title": "بحث", "title": "بحث",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "التنقل والوحدات",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "في الأسفل يمكنك الوصول مباشرة إلى لوحة التحكم والتقويم. بزر ··· تفتح وحدات أخرى مثل المطبخ والملاحظات وجهات الاتصال.",
"step3Title": "Ready to go", "step3Title": "ابدأ بسرعة",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "بزر + الكبير يمكنك إنشاء إدخالات جديدة في أي مكان. اسحب عناصر القائمة يساراً أو يميناً للإجراءات السريعة.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+16 -5
View File
@@ -29,7 +29,12 @@
"unknownError": "Unbekannter Fehler", "unknownError": "Unbekannter Fehler",
"confirm": "Bestätigen", "confirm": "Bestätigen",
"undo": "Rückgängig", "undo": "Rückgängig",
"reset": "Auf Original zurücksetzen" "reset": "Auf Original zurücksetzen",
"errorOffline": "Keine Internetverbindung. Bitte prüfe dein Netzwerk.",
"errorForbidden": "Zugriff verweigert. Bitte erneut anmelden.",
"errorNotFound": "Der Eintrag wurde nicht gefunden.",
"errorServer": "Serverfehler. Bitte versuche es später erneut.",
"errorTimeout": "Die Verbindung hat zu lange gedauert. Bitte erneut versuchen."
}, },
"nav": { "nav": {
"dashboard": "Übersicht", "dashboard": "Übersicht",
@@ -121,6 +126,7 @@
"editTask": "Aufgabe bearbeiten", "editTask": "Aufgabe bearbeiten",
"emptyTitle": "Keine Aufgaben - alles erledigt?", "emptyTitle": "Keine Aufgaben - alles erledigt?",
"emptyDescription": "Neue Aufgaben über den + Button erstellen.", "emptyDescription": "Neue Aufgaben über den + Button erstellen.",
"emptyAction": "Aufgabe erstellen",
"titleLabel": "Titel *", "titleLabel": "Titel *",
"titlePlaceholder": "Was muss erledigt werden?", "titlePlaceholder": "Was muss erledigt werden?",
"descriptionLabel": "Notiz", "descriptionLabel": "Notiz",
@@ -202,6 +208,7 @@
"noListsDescription": "Erstelle eine Liste mit dem + Button.", "noListsDescription": "Erstelle eine Liste mit dem + Button.",
"emptyList": "Die Liste ist leer", "emptyList": "Die Liste ist leer",
"emptyListDescription": "Artikel über das Eingabefeld oben hinzufügen.", "emptyListDescription": "Artikel über das Eingabefeld oben hinzufügen.",
"emptyAction": "Artikel hinzufügen",
"newListPrompt": "Name der neuen Liste:", "newListPrompt": "Name der neuen Liste:",
"newListButton": "Neue Liste erstellen", "newListButton": "Neue Liste erstellen",
"renameListPrompt": "Neuer Listen-Name:", "renameListPrompt": "Neuer Listen-Name:",
@@ -392,6 +399,7 @@
"searchPlaceholder": "Notizen durchsuchen…", "searchPlaceholder": "Notizen durchsuchen…",
"emptyTitle": "Noch keine Notizen", "emptyTitle": "Noch keine Notizen",
"emptyDescription": "Neue Notiz über den + Button erstellen.", "emptyDescription": "Neue Notiz über den + Button erstellen.",
"emptyAction": "Notiz erstellen",
"noResultsTitle": "Keine Treffer", "noResultsTitle": "Keine Treffer",
"noResultsDescription": "Keine Notiz enthält \"{{query}}\".", "noResultsDescription": "Keine Notiz enthält \"{{query}}\".",
"titleLabel": "Titel (optional)", "titleLabel": "Titel (optional)",
@@ -442,6 +450,7 @@
"importTooltip": "vCard importieren", "importTooltip": "vCard importieren",
"emptyTitle": "Noch keine Kontakte", "emptyTitle": "Noch keine Kontakte",
"emptyDescription": "Neue Kontakte über den + Button hinzufügen.", "emptyDescription": "Neue Kontakte über den + Button hinzufügen.",
"emptyAction": "Kontakt hinzufügen",
"filterAll": "Alle", "filterAll": "Alle",
"nameLabel": "Name *", "nameLabel": "Name *",
"namePlaceholder": "Vollständiger Name", "namePlaceholder": "Vollständiger Name",
@@ -499,6 +508,7 @@
"transactions": "Transaktionen", "transactions": "Transaktionen",
"emptyTitle": "Keine Einträge diesen Monat", "emptyTitle": "Keine Einträge diesen Monat",
"emptyDescription": "Budget-Einträge über den + Button hinzufügen.", "emptyDescription": "Budget-Einträge über den + Button hinzufügen.",
"emptyAction": "Eintrag erstellen",
"csvExport": "CSV", "csvExport": "CSV",
"typeExpense": "Ausgabe", "typeExpense": "Ausgabe",
"typeIncome": "Einnahme", "typeIncome": "Einnahme",
@@ -912,6 +922,7 @@
"editRecipe": "Rezept bearbeiten", "editRecipe": "Rezept bearbeiten",
"emptyTitle": "Noch keine Rezepte", "emptyTitle": "Noch keine Rezepte",
"emptyDescription": "Speichere deine Lieblingsrezepte und nutze sie für die Essensplanung.", "emptyDescription": "Speichere deine Lieblingsrezepte und nutze sie für die Essensplanung.",
"emptyAction": "Rezept erstellen",
"titleLabel": "Titel *", "titleLabel": "Titel *",
"titlePlaceholder": "z. B. Pasta Carbonara", "titlePlaceholder": "z. B. Pasta Carbonara",
"notesLabel": "Notizen", "notesLabel": "Notizen",
@@ -933,10 +944,10 @@
"onboarding": { "onboarding": {
"step1Title": "Willkommen bei Oikos", "step1Title": "Willkommen bei Oikos",
"step1Body": "Dein persönlicher Familienplaner. Aufgaben, Kalender, Einkauf und mehr alles an einem Ort.", "step1Body": "Dein persönlicher Familienplaner. Aufgaben, Kalender, Einkauf und mehr alles an einem Ort.",
"step2Title": "Alles im Blick", "step2Title": "Navigation & Module",
"step2Body": "Über die Navigation unten erreichst du alle Module. Mit dem +-Button erstellst du schnell neue Einträge.", "step2Body": "Unten erreichst du Dashboard und Kalender direkt. Mit dem ···-Button öffnest du weitere Module wie Küche, Notizen und Kontakte.",
"step3Title": "Bereit loszulegen", "step3Title": "Schnell loslegen",
"step3Body": "Das Dashboard zeigt dir die wichtigsten Infos auf einen Blick. Du kannst es unter \"Anpassen\" nach deinen Wünschen einrichten.", "step3Body": "Mit dem + FAB-Button erstellst du überall neue Einträge. Wische Listeneinträge nach links oder rechts für Schnellaktionen.",
"next": "Weiter", "next": "Weiter",
"done": "Loslegen", "done": "Loslegen",
"skip": "Überspringen" "skip": "Überspringen"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "Άγνωστο σφάλμα", "unknownError": "Άγνωστο σφάλμα",
"confirm": "Επιβεβαίωση", "confirm": "Επιβεβαίωση",
"undo": "Αναίρεση", "undo": "Αναίρεση",
"reset": "Επαναφορά στο αρχικό" "reset": "Επαναφορά στο αρχικό",
"errorOffline": "Δεν υπάρχει σύνδεση στο διαδίκτυο. Ελέγξτε το δίκτυό σας.",
"errorForbidden": "Η πρόσβαση απορρίφθηκε. Παρακαλώ συνδεθείτε ξανά.",
"errorNotFound": "Η εγγραφή δεν βρέθηκε.",
"errorServer": "Σφάλμα διακομιστή. Δοκιμάστε ξανά αργότερα.",
"errorTimeout": "Η σύνδεση διήρκεσε πολύ. Παρακαλώ δοκιμάστε ξανά."
}, },
"nav": { "nav": {
"dashboard": "Επισκόπηση", "dashboard": "Επισκόπηση",
@@ -187,7 +192,8 @@
"archiveButton": "Αρχειοθέτηση εργασίας", "archiveButton": "Αρχειοθέτηση εργασίας",
"archivedToast": "Η εργασία αρχειοθετήθηκε.", "archivedToast": "Η εργασία αρχειοθετήθηκε.",
"kanbanArchived": "Αρχειοθετημένο", "kanbanArchived": "Αρχειοθετημένο",
"reminderNeedsDueDate": "Ορίστε ημερομηνία λήξης για να ενεργοποιήσετε τις υπενθυμίσεις." "reminderNeedsDueDate": "Ορίστε ημερομηνία λήξης για να ενεργοποιήσετε τις υπενθυμίσεις.",
"emptyAction": "Δημιουργία εργασίας"
}, },
"shopping": { "shopping": {
"title": "Αγορές", "title": "Αγορές",
@@ -227,7 +233,8 @@
"catDrinks": "Ποτά", "catDrinks": "Ποτά",
"catHousehold": "Οικιακά", "catHousehold": "Οικιακά",
"catDrugstore": "Φαρμακείο", "catDrugstore": "Φαρμακείο",
"catMisc": "Διάφορα" "catMisc": "Διάφορα",
"emptyAction": "Προσθήκη στοιχείου"
}, },
"meals": { "meals": {
"title": "Πρόγραμμα γευμάτων", "title": "Πρόγραμμα γευμάτων",
@@ -403,7 +410,8 @@
"formatLink": "Σύνδεσμος", "formatLink": "Σύνδεσμος",
"formatCode": "Κώδικας", "formatCode": "Κώδικας",
"formatQuote": "Παράθεση", "formatQuote": "Παράθεση",
"formatDivider": "Διαχωριστής" "formatDivider": "Διαχωριστής",
"emptyAction": "Δημιουργία σημείωσης"
}, },
"contacts": { "contacts": {
"title": "Επαφές", "title": "Επαφές",
@@ -456,7 +464,8 @@
"categoryInsurance": "Ασφάλεια", "categoryInsurance": "Ασφάλεια",
"categoryCraftsman": "Τεχνίτης", "categoryCraftsman": "Τεχνίτης",
"categoryEmergency": "Έκτακτη ανάγκη", "categoryEmergency": "Έκτακτη ανάγκη",
"categoryOther": "Άλλο" "categoryOther": "Άλλο",
"emptyAction": "Προσθήκη επαφής"
}, },
"budget": { "budget": {
"title": "Προϋπολογισμός", "title": "Προϋπολογισμός",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Name of the new category:", "newCategoryPrompt": "Name of the new category:",
"newSubcategoryPrompt": "Name of the new subcategory:", "newSubcategoryPrompt": "Name of the new subcategory:",
"categoryAddedToast": "Category added.", "categoryAddedToast": "Category added.",
"subcategoryAddedToast": "Subcategory added." "subcategoryAddedToast": "Subcategory added.",
"emptyAction": "Προσθήκη εγγραφής"
}, },
"settings": { "settings": {
"title": "Ρυθμίσεις", "title": "Ρυθμίσεις",
@@ -843,7 +853,8 @@
"titleRequired": "Ο τίτλος είναι υποχρεωτικός", "titleRequired": "Ο τίτλος είναι υποχρεωτικός",
"duplicate": "Διπλότυπο", "duplicate": "Διπλότυπο",
"duplicated": "Η συνταγή αντιγράφηκε.", "duplicated": "Η συνταγή αντιγράφηκε.",
"copySuffix": "αντίγραφο" "copySuffix": "αντίγραφο",
"emptyAction": "Δημιουργία συνταγής"
}, },
"search": { "search": {
"title": "Αναζήτηση", "title": "Αναζήτηση",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "Πλοήγηση & Ενότητες",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "Στο κάτω μέρος έχεις άμεση πρόσβαση στον Πίνακα ελέγχου και το Ημερολόγιο. Με το κουμπί ··· ανοίγεις άλλες ενότητες όπως Κουζίνα, Σημειώσεις και Επαφές.",
"step3Title": "Ready to go", "step3Title": "Ξεκίνα γρήγορα",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "Με το κουμπί + δημιουργείς νέες καταχωρήσεις οπουδήποτε. Σύρε στοιχεία λίστας αριστερά ή δεξιά για γρήγορες ενέργειες.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "Unknown error", "unknownError": "Unknown error",
"confirm": "Confirm", "confirm": "Confirm",
"undo": "Undo", "undo": "Undo",
"reset": "Reset to original" "reset": "Reset to original",
"errorOffline": "No internet connection. Please check your network.",
"errorForbidden": "Access denied. Please sign in again.",
"errorNotFound": "The entry was not found.",
"errorServer": "Server error. Please try again later.",
"errorTimeout": "The connection took too long. Please try again."
}, },
"nav": { "nav": {
"dashboard": "Overview", "dashboard": "Overview",
@@ -187,7 +192,8 @@
"filterGroupStatus": "Status", "filterGroupStatus": "Status",
"swipedDoneToast": "Marked as done.", "swipedDoneToast": "Marked as done.",
"swipedOpenToast": "Marked as open.", "swipedOpenToast": "Marked as open.",
"reminderNeedsDueDate": "Set a due date to enable task reminders." "reminderNeedsDueDate": "Set a due date to enable task reminders.",
"emptyAction": "Create task"
}, },
"shopping": { "shopping": {
"title": "Shopping", "title": "Shopping",
@@ -227,7 +233,8 @@
"catDrinks": "Drinks", "catDrinks": "Drinks",
"catHousehold": "Household", "catHousehold": "Household",
"catDrugstore": "Drugstore", "catDrugstore": "Drugstore",
"catMisc": "Miscellaneous" "catMisc": "Miscellaneous",
"emptyAction": "Add item"
}, },
"meals": { "meals": {
"title": "Meal Plan", "title": "Meal Plan",
@@ -403,7 +410,8 @@
"formatLink": "Link", "formatLink": "Link",
"formatCode": "Code", "formatCode": "Code",
"formatQuote": "Quote", "formatQuote": "Quote",
"formatDivider": "Divider" "formatDivider": "Divider",
"emptyAction": "Create note"
}, },
"contacts": { "contacts": {
"title": "Contacts", "title": "Contacts",
@@ -456,7 +464,8 @@
"categoryInsurance": "Insurance", "categoryInsurance": "Insurance",
"categoryCraftsman": "Tradesperson", "categoryCraftsman": "Tradesperson",
"categoryEmergency": "Emergency", "categoryEmergency": "Emergency",
"categoryOther": "Other" "categoryOther": "Other",
"emptyAction": "Add contact"
}, },
"budget": { "budget": {
"title": "Budget", "title": "Budget",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Name of the new category:", "newCategoryPrompt": "Name of the new category:",
"newSubcategoryPrompt": "Name of the new subcategory:", "newSubcategoryPrompt": "Name of the new subcategory:",
"categoryAddedToast": "Category added.", "categoryAddedToast": "Category added.",
"subcategoryAddedToast": "Subcategory added." "subcategoryAddedToast": "Subcategory added.",
"emptyAction": "Add entry"
}, },
"settings": { "settings": {
"title": "Settings", "title": "Settings",
@@ -903,7 +913,8 @@
"titleRequired": "Title is required", "titleRequired": "Title is required",
"duplicate": "Duplicate", "duplicate": "Duplicate",
"duplicated": "Recipe duplicated.", "duplicated": "Recipe duplicated.",
"copySuffix": "copy" "copySuffix": "copy",
"emptyAction": "Create recipe"
}, },
"search": { "search": {
"title": "Search", "title": "Search",
@@ -914,10 +925,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "Navigation & Modules",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "At the bottom you can directly access Dashboard and Calendar. The ··· button opens additional modules like Kitchen, Notes and Contacts.",
"step3Title": "Ready to go", "step3Title": "Get started quickly",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "Use the + FAB button to create new entries anywhere. Swipe list items left or right for quick actions.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "Error desconocido", "unknownError": "Error desconocido",
"confirm": "Confirmar", "confirm": "Confirmar",
"undo": "Deshacer", "undo": "Deshacer",
"reset": "Restaurar original" "reset": "Restaurar original",
"errorOffline": "Sin conexión a internet. Por favor, revisa tu red.",
"errorForbidden": "Acceso denegado. Por favor, inicia sesión de nuevo.",
"errorNotFound": "No se encontró el registro.",
"errorServer": "Error del servidor. Por favor, inténtalo más tarde.",
"errorTimeout": "La conexión tardó demasiado. Por favor, inténtalo de nuevo."
}, },
"nav": { "nav": {
"dashboard": "Inicio", "dashboard": "Inicio",
@@ -187,7 +192,8 @@
"archiveButton": "Archivar tarea", "archiveButton": "Archivar tarea",
"archivedToast": "Tarea archivada.", "archivedToast": "Tarea archivada.",
"kanbanArchived": "Archivado", "kanbanArchived": "Archivado",
"reminderNeedsDueDate": "Establece una fecha de vencimiento para activar los recordatorios de tareas." "reminderNeedsDueDate": "Establece una fecha de vencimiento para activar los recordatorios de tareas.",
"emptyAction": "Crear tarea"
}, },
"shopping": { "shopping": {
"title": "Compras", "title": "Compras",
@@ -227,7 +233,8 @@
"catDrinks": "Bebidas", "catDrinks": "Bebidas",
"catHousehold": "Hogar", "catHousehold": "Hogar",
"catDrugstore": "Droguería", "catDrugstore": "Droguería",
"catMisc": "Otros" "catMisc": "Otros",
"emptyAction": "Agregar artículo"
}, },
"meals": { "meals": {
"title": "Plan de comidas", "title": "Plan de comidas",
@@ -403,7 +410,8 @@
"formatLink": "Enlace", "formatLink": "Enlace",
"formatCode": "Código", "formatCode": "Código",
"formatQuote": "Cita", "formatQuote": "Cita",
"formatDivider": "Separador" "formatDivider": "Separador",
"emptyAction": "Crear nota"
}, },
"contacts": { "contacts": {
"title": "Contactos", "title": "Contactos",
@@ -456,7 +464,8 @@
"categoryInsurance": "Seguro", "categoryInsurance": "Seguro",
"categoryCraftsman": "Artesano", "categoryCraftsman": "Artesano",
"categoryEmergency": "Emergencia", "categoryEmergency": "Emergencia",
"categoryOther": "Otros" "categoryOther": "Otros",
"emptyAction": "Agregar contacto"
}, },
"budget": { "budget": {
"title": "Presupuesto", "title": "Presupuesto",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Nombre de la nueva categoría:", "newCategoryPrompt": "Nombre de la nueva categoría:",
"newSubcategoryPrompt": "Nombre de la nueva subcategoría:", "newSubcategoryPrompt": "Nombre de la nueva subcategoría:",
"categoryAddedToast": "Categoría añadida.", "categoryAddedToast": "Categoría añadida.",
"subcategoryAddedToast": "Subcategoría añadida." "subcategoryAddedToast": "Subcategoría añadida.",
"emptyAction": "Agregar entrada"
}, },
"settings": { "settings": {
"title": "Ajustes", "title": "Ajustes",
@@ -843,7 +853,8 @@
"titleRequired": "El título es obligatorio", "titleRequired": "El título es obligatorio",
"duplicate": "Duplicar", "duplicate": "Duplicar",
"duplicated": "Receta duplicada.", "duplicated": "Receta duplicada.",
"copySuffix": "copia" "copySuffix": "copia",
"emptyAction": "Crear receta"
}, },
"search": { "search": {
"title": "Búsqueda", "title": "Búsqueda",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "Navegación y módulos",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "En la parte inferior accedes directamente al Panel y el Calendario. Con el botón ··· abres más módulos como Cocina, Notas y Contactos.",
"step3Title": "Ready to go", "step3Title": "Empieza rápido",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "Con el botón + creas nuevas entradas en cualquier lugar. Desliza elementos de la lista a la izquierda o derecha para acciones rápidas.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "Erreur inconnue", "unknownError": "Erreur inconnue",
"confirm": "Confirmer", "confirm": "Confirmer",
"undo": "Annuler", "undo": "Annuler",
"reset": "Réinitialiser" "reset": "Réinitialiser",
"errorOffline": "Pas de connexion internet. Vérifiez votre réseau.",
"errorForbidden": "Accès refusé. Veuillez vous reconnecter.",
"errorNotFound": "L'entrée n'a pas été trouvée.",
"errorServer": "Erreur serveur. Veuillez réessayer plus tard.",
"errorTimeout": "La connexion a pris trop de temps. Veuillez réessayer."
}, },
"nav": { "nav": {
"dashboard": "Accueil", "dashboard": "Accueil",
@@ -187,7 +192,8 @@
"archiveButton": "Archiver la tâche", "archiveButton": "Archiver la tâche",
"archivedToast": "Tâche archivée.", "archivedToast": "Tâche archivée.",
"kanbanArchived": "Archivé", "kanbanArchived": "Archivé",
"reminderNeedsDueDate": "Définissez une date d'échéance pour activer les rappels de tâche." "reminderNeedsDueDate": "Définissez une date d'échéance pour activer les rappels de tâche.",
"emptyAction": "Créer une tâche"
}, },
"shopping": { "shopping": {
"title": "Courses", "title": "Courses",
@@ -227,7 +233,8 @@
"catDrinks": "Boissons", "catDrinks": "Boissons",
"catHousehold": "Ménage", "catHousehold": "Ménage",
"catDrugstore": "Pharmacie", "catDrugstore": "Pharmacie",
"catMisc": "Divers" "catMisc": "Divers",
"emptyAction": "Ajouter un article"
}, },
"meals": { "meals": {
"title": "Plan de repas", "title": "Plan de repas",
@@ -403,7 +410,8 @@
"formatLink": "Lien", "formatLink": "Lien",
"formatCode": "Code", "formatCode": "Code",
"formatQuote": "Citation", "formatQuote": "Citation",
"formatDivider": "Séparateur" "formatDivider": "Séparateur",
"emptyAction": "Créer une note"
}, },
"contacts": { "contacts": {
"title": "Contacts", "title": "Contacts",
@@ -456,7 +464,8 @@
"categoryInsurance": "Assurance", "categoryInsurance": "Assurance",
"categoryCraftsman": "Artisan", "categoryCraftsman": "Artisan",
"categoryEmergency": "Urgence", "categoryEmergency": "Urgence",
"categoryOther": "Autre" "categoryOther": "Autre",
"emptyAction": "Ajouter un contact"
}, },
"budget": { "budget": {
"title": "Budget", "title": "Budget",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Nom de la nouvelle catégorie :", "newCategoryPrompt": "Nom de la nouvelle catégorie :",
"newSubcategoryPrompt": "Nom de la nouvelle sous-catégorie :", "newSubcategoryPrompt": "Nom de la nouvelle sous-catégorie :",
"categoryAddedToast": "Catégorie ajoutée.", "categoryAddedToast": "Catégorie ajoutée.",
"subcategoryAddedToast": "Sous-catégorie ajoutée." "subcategoryAddedToast": "Sous-catégorie ajoutée.",
"emptyAction": "Ajouter une entrée"
}, },
"settings": { "settings": {
"title": "Paramètres", "title": "Paramètres",
@@ -843,7 +853,8 @@
"titleRequired": "Le titre est requis", "titleRequired": "Le titre est requis",
"duplicate": "Dupliquer", "duplicate": "Dupliquer",
"duplicated": "Recette dupliquée.", "duplicated": "Recette dupliquée.",
"copySuffix": "copie" "copySuffix": "copie",
"emptyAction": "Créer une recette"
}, },
"search": { "search": {
"title": "Recherche", "title": "Recherche",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "Navigation & modules",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "En bas, accédez directement au Tableau de bord et au Calendrier. Le bouton ··· ouvre d'autres modules comme Cuisine, Notes et Contacts.",
"step3Title": "Ready to go", "step3Title": "Démarrer rapidement",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "Avec le bouton +, créez de nouvelles entrées n'importe où. Faites glisser les éléments de liste à gauche ou à droite pour des actions rapides.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "अज्ञात त्रुटि", "unknownError": "अज्ञात त्रुटि",
"confirm": "पुष्टि करें", "confirm": "पुष्टि करें",
"undo": "पूर्ववत करें", "undo": "पूर्ववत करें",
"reset": "मूल पर वापस जाएं" "reset": "मूल पर वापस जाएं",
"errorOffline": "इंटरनेट कनेक्शन नहीं है। कृपया अपना नेटवर्क जांचें।",
"errorForbidden": "पहुँच अस्वीकृत। कृपया फिर से लॉग इन करें।",
"errorNotFound": "प्रविष्टि नहीं मिली।",
"errorServer": "सर्वर त्रुटि। कृपया बाद में पुनः प्रयास करें।",
"errorTimeout": "कनेक्शन बहुत देर से हुआ। कृपया पुनः प्रयास करें।"
}, },
"nav": { "nav": {
"dashboard": "डैशबोर्ड", "dashboard": "डैशबोर्ड",
@@ -187,7 +192,8 @@
"archiveButton": "कार्य संग्रहित करें", "archiveButton": "कार्य संग्रहित करें",
"archivedToast": "कार्य संग्रहित किया गया।", "archivedToast": "कार्य संग्रहित किया गया।",
"kanbanArchived": "संग्रहित", "kanbanArchived": "संग्रहित",
"reminderNeedsDueDate": "कार्य अनुस्मारक सक्षम करने के लिए एक नियत तारीख निर्धारित करें।" "reminderNeedsDueDate": "कार्य अनुस्मारक सक्षम करने के लिए एक नियत तारीख निर्धारित करें।",
"emptyAction": "कार्य बनाएं"
}, },
"shopping": { "shopping": {
"title": "खरीदारी", "title": "खरीदारी",
@@ -227,7 +233,8 @@
"catDrinks": "पेय", "catDrinks": "पेय",
"catHousehold": "घरेलू", "catHousehold": "घरेलू",
"catDrugstore": "दवाखाना", "catDrugstore": "दवाखाना",
"catMisc": "विविध" "catMisc": "विविध",
"emptyAction": "आइटम जोड़ें"
}, },
"meals": { "meals": {
"title": "भोजन योजना", "title": "भोजन योजना",
@@ -403,7 +410,8 @@
"formatLink": "लिंक", "formatLink": "लिंक",
"formatCode": "कोड", "formatCode": "कोड",
"formatQuote": "उद्धरण", "formatQuote": "उद्धरण",
"formatDivider": "विभाजक" "formatDivider": "विभाजक",
"emptyAction": "नोट बनाएं"
}, },
"contacts": { "contacts": {
"title": "संपर्क", "title": "संपर्क",
@@ -456,7 +464,8 @@
"categoryInsurance": "बीमा", "categoryInsurance": "बीमा",
"categoryCraftsman": "कारीगर", "categoryCraftsman": "कारीगर",
"categoryEmergency": "आपातकालीन", "categoryEmergency": "आपातकालीन",
"categoryOther": "विविध" "categoryOther": "विविध",
"emptyAction": "संपर्क जोड़ें"
}, },
"budget": { "budget": {
"title": "बजट", "title": "बजट",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Name of the new category:", "newCategoryPrompt": "Name of the new category:",
"newSubcategoryPrompt": "Name of the new subcategory:", "newSubcategoryPrompt": "Name of the new subcategory:",
"categoryAddedToast": "Category added.", "categoryAddedToast": "Category added.",
"subcategoryAddedToast": "Subcategory added." "subcategoryAddedToast": "Subcategory added.",
"emptyAction": "प्रविष्टि जोड़ें"
}, },
"settings": { "settings": {
"title": "सेटिंग्स", "title": "सेटिंग्स",
@@ -843,7 +853,8 @@
"titleRequired": "शीर्षक आवश्यक है", "titleRequired": "शीर्षक आवश्यक है",
"duplicate": "डुप्लिकेट", "duplicate": "डुप्लिकेट",
"duplicated": "रेसिपी डुप्लिकेट की गई।", "duplicated": "रेसिपी डुप्लिकेट की गई।",
"copySuffix": "कॉपी" "copySuffix": "कॉपी",
"emptyAction": "रेसिपी बनाएं"
}, },
"search": { "search": {
"title": "खोज", "title": "खोज",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "नेविगेशन और मॉड्यूल",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "नीचे से डैशबोर्ड और कैलेंडर तक सीधी पहुँच। ··· बटन से किचन, नोट्स और संपर्क जैसे अन्य मॉड्यूल खोलें।",
"step3Title": "Ready to go", "step3Title": "जल्दी शुरू करें",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "किसी भी जगह नई प्रविष्टियाँ बनाने के लिए + बटन दबाएँ। त्वरित क्रियाओं के लिए सूची आइटम को बाएँ या दाएँ स्वाइप करें।",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "Errore sconosciuto", "unknownError": "Errore sconosciuto",
"confirm": "Conferma", "confirm": "Conferma",
"undo": "Annulla", "undo": "Annulla",
"reset": "Ripristina originale" "reset": "Ripristina originale",
"errorOffline": "Nessuna connessione internet. Controlla la tua rete.",
"errorForbidden": "Accesso negato. Per favore accedi di nuovo.",
"errorNotFound": "La voce non è stata trovata.",
"errorServer": "Errore del server. Riprova più tardi.",
"errorTimeout": "La connessione ha impiegato troppo tempo. Riprova."
}, },
"nav": { "nav": {
"dashboard": "Panoramica", "dashboard": "Panoramica",
@@ -187,7 +192,8 @@
"archiveButton": "Archivia attività", "archiveButton": "Archivia attività",
"archivedToast": "Attività archiviata.", "archivedToast": "Attività archiviata.",
"kanbanArchived": "Archiviato", "kanbanArchived": "Archiviato",
"reminderNeedsDueDate": "Imposta una data di scadenza per abilitare i promemoria delle attività." "reminderNeedsDueDate": "Imposta una data di scadenza per abilitare i promemoria delle attività.",
"emptyAction": "Crea attività"
}, },
"shopping": { "shopping": {
"title": "Spesa", "title": "Spesa",
@@ -227,7 +233,8 @@
"catDrinks": "Bevande", "catDrinks": "Bevande",
"catHousehold": "Casa", "catHousehold": "Casa",
"catDrugstore": "Drogheria", "catDrugstore": "Drogheria",
"catMisc": "Varie" "catMisc": "Varie",
"emptyAction": "Aggiungi articolo"
}, },
"meals": { "meals": {
"title": "Piano pasti", "title": "Piano pasti",
@@ -403,7 +410,8 @@
"formatLink": "Link", "formatLink": "Link",
"formatCode": "Codice", "formatCode": "Codice",
"formatQuote": "Citazione", "formatQuote": "Citazione",
"formatDivider": "Divisore" "formatDivider": "Divisore",
"emptyAction": "Crea nota"
}, },
"contacts": { "contacts": {
"title": "Contatti", "title": "Contatti",
@@ -456,7 +464,8 @@
"categoryInsurance": "Assicurazione", "categoryInsurance": "Assicurazione",
"categoryCraftsman": "Artigiano", "categoryCraftsman": "Artigiano",
"categoryEmergency": "Emergenza", "categoryEmergency": "Emergenza",
"categoryOther": "Altro" "categoryOther": "Altro",
"emptyAction": "Aggiungi contatto"
}, },
"budget": { "budget": {
"title": "Bilancio", "title": "Bilancio",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Nome della nuova categoria:", "newCategoryPrompt": "Nome della nuova categoria:",
"newSubcategoryPrompt": "Nome della nuova sottocategoria:", "newSubcategoryPrompt": "Nome della nuova sottocategoria:",
"categoryAddedToast": "Categoria aggiunta.", "categoryAddedToast": "Categoria aggiunta.",
"subcategoryAddedToast": "Sottocategoria aggiunta." "subcategoryAddedToast": "Sottocategoria aggiunta.",
"emptyAction": "Aggiungi voce"
}, },
"settings": { "settings": {
"title": "Impostazioni", "title": "Impostazioni",
@@ -843,7 +853,8 @@
"titleRequired": "Il titolo è obbligatorio", "titleRequired": "Il titolo è obbligatorio",
"duplicate": "Duplica", "duplicate": "Duplica",
"duplicated": "Ricetta duplicata.", "duplicated": "Ricetta duplicata.",
"copySuffix": "copia" "copySuffix": "copia",
"emptyAction": "Crea ricetta"
}, },
"search": { "search": {
"title": "Ricerca", "title": "Ricerca",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "Navigazione e moduli",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "In basso accedi direttamente alla Dashboard e al Calendario. Con il pulsante ··· apri altri moduli come Cucina, Note e Contatti.",
"step3Title": "Ready to go", "step3Title": "Inizia subito",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "Con il pulsante + crei nuove voci ovunque. Scorri gli elementi dell'elenco a sinistra o a destra per azioni rapide.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "不明なエラー", "unknownError": "不明なエラー",
"confirm": "確認", "confirm": "確認",
"undo": "元に戻す", "undo": "元に戻す",
"reset": "元に戻す" "reset": "元に戻す",
"errorOffline": "インターネット接続がありません。ネットワークを確認してください。",
"errorForbidden": "アクセスが拒否されました。再度サインインしてください。",
"errorNotFound": "エントリが見つかりませんでした。",
"errorServer": "サーバーエラーが発生しました。後でもう一度お試しください。",
"errorTimeout": "接続に時間がかかりすぎました。もう一度お試しください。"
}, },
"nav": { "nav": {
"dashboard": "ダッシュボード", "dashboard": "ダッシュボード",
@@ -187,7 +192,8 @@
"archiveButton": "タスクをアーカイブ", "archiveButton": "タスクをアーカイブ",
"archivedToast": "タスクをアーカイブしました。", "archivedToast": "タスクをアーカイブしました。",
"kanbanArchived": "アーカイブ済み", "kanbanArchived": "アーカイブ済み",
"reminderNeedsDueDate": "タスクのリマインダーを有効にするには期日を設定してください。" "reminderNeedsDueDate": "タスクのリマインダーを有効にするには期日を設定してください。",
"emptyAction": "タスクを作成"
}, },
"shopping": { "shopping": {
"title": "買い物", "title": "買い物",
@@ -227,7 +233,8 @@
"catDrinks": "飲み物", "catDrinks": "飲み物",
"catHousehold": "日用品", "catHousehold": "日用品",
"catDrugstore": "薬局", "catDrugstore": "薬局",
"catMisc": "その他" "catMisc": "その他",
"emptyAction": "アイテムを追加"
}, },
"meals": { "meals": {
"title": "食事計画", "title": "食事計画",
@@ -403,7 +410,8 @@
"formatLink": "リンク", "formatLink": "リンク",
"formatCode": "コード", "formatCode": "コード",
"formatQuote": "引用", "formatQuote": "引用",
"formatDivider": "区切り線" "formatDivider": "区切り線",
"emptyAction": "メモを作成"
}, },
"contacts": { "contacts": {
"title": "連絡先", "title": "連絡先",
@@ -456,7 +464,8 @@
"categoryInsurance": "保険", "categoryInsurance": "保険",
"categoryCraftsman": "職人", "categoryCraftsman": "職人",
"categoryEmergency": "緊急連絡先", "categoryEmergency": "緊急連絡先",
"categoryOther": "その他" "categoryOther": "その他",
"emptyAction": "連絡先を追加"
}, },
"budget": { "budget": {
"title": "家計", "title": "家計",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Name of the new category:", "newCategoryPrompt": "Name of the new category:",
"newSubcategoryPrompt": "Name of the new subcategory:", "newSubcategoryPrompt": "Name of the new subcategory:",
"categoryAddedToast": "Category added.", "categoryAddedToast": "Category added.",
"subcategoryAddedToast": "Subcategory added." "subcategoryAddedToast": "Subcategory added.",
"emptyAction": "エントリを追加"
}, },
"settings": { "settings": {
"title": "設定", "title": "設定",
@@ -843,7 +853,8 @@
"titleRequired": "タイトルが必要です", "titleRequired": "タイトルが必要です",
"duplicate": "複製", "duplicate": "複製",
"duplicated": "レシピが複製されました。", "duplicated": "レシピが複製されました。",
"copySuffix": "コピー" "copySuffix": "コピー",
"emptyAction": "レシピを作成"
}, },
"search": { "search": {
"title": "検索", "title": "検索",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "ナビゲーションとモジュール",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "画面下部からダッシュボードとカレンダーに直接アクセスできます。···ボタンでキッチン、メモ、連絡先などの追加モジュールを開きます。",
"step3Title": "Ready to go", "step3Title": "さっそく始めよう",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "+ボタンでどこでも新しいエントリを作成できます。リストアイテムを左右にスワイプして素早く操作できます。",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "Erro desconhecido", "unknownError": "Erro desconhecido",
"confirm": "Confirmar", "confirm": "Confirmar",
"undo": "Desfazer", "undo": "Desfazer",
"reset": "Restaurar original" "reset": "Restaurar original",
"errorOffline": "Sem ligação à internet. Por favor, verifique a sua rede.",
"errorForbidden": "Acesso negado. Por favor, inicie sessão novamente.",
"errorNotFound": "O registo não foi encontrado.",
"errorServer": "Erro no servidor. Por favor, tente mais tarde.",
"errorTimeout": "A ligação demorou demasiado. Por favor, tente novamente."
}, },
"nav": { "nav": {
"dashboard": "Painel", "dashboard": "Painel",
@@ -187,7 +192,8 @@
"filterGroupStatus": "Estado", "filterGroupStatus": "Estado",
"swipedDoneToast": "Marcado como concluído.", "swipedDoneToast": "Marcado como concluído.",
"swipedOpenToast": "Marcado como aberto.", "swipedOpenToast": "Marcado como aberto.",
"reminderNeedsDueDate": "Defina uma data de vencimento para habilitar lembretes da tarefa." "reminderNeedsDueDate": "Defina uma data de vencimento para habilitar lembretes da tarefa.",
"emptyAction": "Criar tarefa"
}, },
"shopping": { "shopping": {
"title": "Compras", "title": "Compras",
@@ -227,7 +233,8 @@
"catDrinks": "Bebidas", "catDrinks": "Bebidas",
"catHousehold": "Casa", "catHousehold": "Casa",
"catDrugstore": "Farmácia", "catDrugstore": "Farmácia",
"catMisc": "Outros" "catMisc": "Outros",
"emptyAction": "Adicionar item"
}, },
"meals": { "meals": {
"title": "Plano de refeições", "title": "Plano de refeições",
@@ -403,7 +410,8 @@
"formatLink": "Link", "formatLink": "Link",
"formatCode": "Código", "formatCode": "Código",
"formatQuote": "Citação", "formatQuote": "Citação",
"formatDivider": "Divisor" "formatDivider": "Divisor",
"emptyAction": "Criar nota"
}, },
"contacts": { "contacts": {
"title": "Contatos", "title": "Contatos",
@@ -456,7 +464,8 @@
"categoryInsurance": "Seguro", "categoryInsurance": "Seguro",
"categoryCraftsman": "Artesão", "categoryCraftsman": "Artesão",
"categoryEmergency": "Emergência", "categoryEmergency": "Emergência",
"categoryOther": "Outros" "categoryOther": "Outros",
"emptyAction": "Adicionar contato"
}, },
"budget": { "budget": {
"title": "Orçamento", "title": "Orçamento",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Nome da nova categoria:", "newCategoryPrompt": "Nome da nova categoria:",
"newSubcategoryPrompt": "Nome da nova subcategoria:", "newSubcategoryPrompt": "Nome da nova subcategoria:",
"categoryAddedToast": "Categoria adicionada.", "categoryAddedToast": "Categoria adicionada.",
"subcategoryAddedToast": "Subcategoria adicionada." "subcategoryAddedToast": "Subcategoria adicionada.",
"emptyAction": "Adicionar entrada"
}, },
"settings": { "settings": {
"title": "Configurações", "title": "Configurações",
@@ -843,7 +853,8 @@
"titleRequired": "O título é obrigatório", "titleRequired": "O título é obrigatório",
"duplicate": "Duplicar", "duplicate": "Duplicar",
"duplicated": "Receita duplicada.", "duplicated": "Receita duplicada.",
"copySuffix": "cópia" "copySuffix": "cópia",
"emptyAction": "Criar receita"
}, },
"search": { "search": {
"title": "Pesquisa", "title": "Pesquisa",
@@ -914,10 +925,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "Navegação e módulos",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "Na parte inferior acessa diretamente o Painel e o Calendário. Com o botão ··· abre módulos adicionais como Cozinha, Notas e Contactos.",
"step3Title": "Ready to go", "step3Title": "Comece rapidamente",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "Com o botão + cria novas entradas em qualquer lugar. Deslize itens da lista para a esquerda ou direita para ações rápidas.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "Неизвестная ошибка", "unknownError": "Неизвестная ошибка",
"confirm": "Подтвердить", "confirm": "Подтвердить",
"undo": "Отменить", "undo": "Отменить",
"reset": "Сбросить к исходному" "reset": "Сбросить к исходному",
"errorOffline": "Нет подключения к интернету. Проверьте сеть.",
"errorForbidden": "Доступ запрещён. Пожалуйста, войдите снова.",
"errorNotFound": "Запись не найдена.",
"errorServer": "Ошибка сервера. Повторите попытку позже.",
"errorTimeout": "Соединение заняло слишком много времени. Попробуйте снова."
}, },
"nav": { "nav": {
"dashboard": "Обзор", "dashboard": "Обзор",
@@ -187,7 +192,8 @@
"archiveButton": "Архивировать задачу", "archiveButton": "Архивировать задачу",
"archivedToast": "Задача архивирована.", "archivedToast": "Задача архивирована.",
"kanbanArchived": "Архивировано", "kanbanArchived": "Архивировано",
"reminderNeedsDueDate": "Установите срок выполнения, чтобы включить напоминания о задаче." "reminderNeedsDueDate": "Установите срок выполнения, чтобы включить напоминания о задаче.",
"emptyAction": "Создать задачу"
}, },
"shopping": { "shopping": {
"title": "Покупки", "title": "Покупки",
@@ -227,7 +233,8 @@
"catDrinks": "Напитки", "catDrinks": "Напитки",
"catHousehold": "Хозтовары", "catHousehold": "Хозтовары",
"catDrugstore": "Аптека", "catDrugstore": "Аптека",
"catMisc": "Разное" "catMisc": "Разное",
"emptyAction": "Добавить товар"
}, },
"meals": { "meals": {
"title": "План питания", "title": "План питания",
@@ -403,7 +410,8 @@
"formatLink": "Ссылка", "formatLink": "Ссылка",
"formatCode": "Код", "formatCode": "Код",
"formatQuote": "Цитата", "formatQuote": "Цитата",
"formatDivider": "Разделитель" "formatDivider": "Разделитель",
"emptyAction": "Создать заметку"
}, },
"contacts": { "contacts": {
"title": "Контакты", "title": "Контакты",
@@ -456,7 +464,8 @@
"categoryInsurance": "Страховая", "categoryInsurance": "Страховая",
"categoryCraftsman": "Мастер", "categoryCraftsman": "Мастер",
"categoryEmergency": "Экстренная помощь", "categoryEmergency": "Экстренная помощь",
"categoryOther": "Другое" "categoryOther": "Другое",
"emptyAction": "Добавить контакт"
}, },
"budget": { "budget": {
"title": "Бюджет", "title": "Бюджет",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Name of the new category:", "newCategoryPrompt": "Name of the new category:",
"newSubcategoryPrompt": "Name of the new subcategory:", "newSubcategoryPrompt": "Name of the new subcategory:",
"categoryAddedToast": "Category added.", "categoryAddedToast": "Category added.",
"subcategoryAddedToast": "Subcategory added." "subcategoryAddedToast": "Subcategory added.",
"emptyAction": "Добавить запись"
}, },
"settings": { "settings": {
"title": "Настройки", "title": "Настройки",
@@ -843,7 +853,8 @@
"titleRequired": "Название обязательно", "titleRequired": "Название обязательно",
"duplicate": "Дублировать", "duplicate": "Дублировать",
"duplicated": "Рецепт дублирован.", "duplicated": "Рецепт дублирован.",
"copySuffix": "копия" "copySuffix": "копия",
"emptyAction": "Создать рецепт"
}, },
"search": { "search": {
"title": "Поиск", "title": "Поиск",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "Навигация и модули",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "Внизу доступны Панель управления и Календарь напрямую. Кнопка ··· открывает дополнительные модули: Кухня, Заметки и Контакты.",
"step3Title": "Ready to go", "step3Title": "Начните быстро",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "Кнопка + позволяет создавать новые записи везде. Смахните элементы списка влево или вправо для быстрых действий.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "Okänt fel", "unknownError": "Okänt fel",
"confirm": "Bekräfta", "confirm": "Bekräfta",
"undo": "Ångra", "undo": "Ångra",
"reset": "Återställ till original" "reset": "Återställ till original",
"errorOffline": "Ingen internetanslutning. Kontrollera ditt nätverk.",
"errorForbidden": "Åtkomst nekad. Logga in igen.",
"errorNotFound": "Posten hittades inte.",
"errorServer": "Serverfel. Försök igen senare.",
"errorTimeout": "Anslutningen tog för lång tid. Försök igen."
}, },
"nav": { "nav": {
"dashboard": "Översikt", "dashboard": "Översikt",
@@ -187,7 +192,8 @@
"archiveButton": "Arkivera uppgift", "archiveButton": "Arkivera uppgift",
"archivedToast": "Uppgiften arkiverades.", "archivedToast": "Uppgiften arkiverades.",
"kanbanArchived": "Arkiverad", "kanbanArchived": "Arkiverad",
"reminderNeedsDueDate": "Ange ett förfallodatum för att aktivera påminnelser för uppgiften." "reminderNeedsDueDate": "Ange ett förfallodatum för att aktivera påminnelser för uppgiften.",
"emptyAction": "Skapa uppgift"
}, },
"shopping": { "shopping": {
"title": "Shopping", "title": "Shopping",
@@ -227,7 +233,8 @@
"catDrinks": "Drycker", "catDrinks": "Drycker",
"catHousehold": "Hushåll", "catHousehold": "Hushåll",
"catDrugstore": "Apotek", "catDrugstore": "Apotek",
"catMisc": "Diverse" "catMisc": "Diverse",
"emptyAction": "Lägg till artikel"
}, },
"meals": { "meals": {
"title": "Måltidsplan", "title": "Måltidsplan",
@@ -403,7 +410,8 @@
"formatLink": "Länk", "formatLink": "Länk",
"formatCode": "Kod", "formatCode": "Kod",
"formatQuote": "Citationstecken", "formatQuote": "Citationstecken",
"formatDivider": "Delare" "formatDivider": "Delare",
"emptyAction": "Skapa anteckning"
}, },
"contacts": { "contacts": {
"title": "Kontakter", "title": "Kontakter",
@@ -456,7 +464,8 @@
"categoryInsurance": "Försäkring", "categoryInsurance": "Försäkring",
"categoryCraftsman": "Handlare", "categoryCraftsman": "Handlare",
"categoryEmergency": "Nödsituation", "categoryEmergency": "Nödsituation",
"categoryOther": "Andra" "categoryOther": "Andra",
"emptyAction": "Lägg till kontakt"
}, },
"budget": { "budget": {
"title": "Budget", "title": "Budget",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Name of the new category:", "newCategoryPrompt": "Name of the new category:",
"newSubcategoryPrompt": "Name of the new subcategory:", "newSubcategoryPrompt": "Name of the new subcategory:",
"categoryAddedToast": "Category added.", "categoryAddedToast": "Category added.",
"subcategoryAddedToast": "Subcategory added." "subcategoryAddedToast": "Subcategory added.",
"emptyAction": "Lägg till post"
}, },
"settings": { "settings": {
"title": "Inställningar", "title": "Inställningar",
@@ -843,7 +853,8 @@
"titleRequired": "Titel krävs", "titleRequired": "Titel krävs",
"duplicate": "Duplicera", "duplicate": "Duplicera",
"duplicated": "Recept duplicerat.", "duplicated": "Recept duplicerat.",
"copySuffix": "kopia" "copySuffix": "kopia",
"emptyAction": "Skapa recept"
}, },
"search": { "search": {
"title": "Sök", "title": "Sök",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "Navigering och moduler",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "Nere på skärmen når du direkt Dashboard och Kalender. Med ···-knappen öppnar du fler moduler som Kök, Anteckningar och Kontakter.",
"step3Title": "Ready to go", "step3Title": "Kom igång snabbt",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "Med +-knappen skapar du nya poster var som helst. Svep listobjekt åt vänster eller höger för snabbåtgärder.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "Bilinmeyen hata", "unknownError": "Bilinmeyen hata",
"confirm": "Onayla", "confirm": "Onayla",
"undo": "Geri al", "undo": "Geri al",
"reset": "Orijinale sıfırla" "reset": "Orijinale sıfırla",
"errorOffline": "İnternet bağlantısı yok. Lütfen ağınızı kontrol edin.",
"errorForbidden": "Erişim reddedildi. Lütfen tekrar giriş yapın.",
"errorNotFound": "Kayıt bulunamadı.",
"errorServer": "Sunucu hatası. Lütfen daha sonra tekrar deneyin.",
"errorTimeout": "Bağlantı çok uzun sürdü. Lütfen tekrar deneyin."
}, },
"nav": { "nav": {
"dashboard": "Genel Bakış", "dashboard": "Genel Bakış",
@@ -187,7 +192,8 @@
"archiveButton": "Görevi arşivle", "archiveButton": "Görevi arşivle",
"archivedToast": "Görev arşivlendi.", "archivedToast": "Görev arşivlendi.",
"kanbanArchived": "Arşivlenmiş", "kanbanArchived": "Arşivlenmiş",
"reminderNeedsDueDate": "Görev hatırlatıcılarını etkinleştirmek için bir son tarih belirleyin." "reminderNeedsDueDate": "Görev hatırlatıcılarını etkinleştirmek için bir son tarih belirleyin.",
"emptyAction": "Görev oluştur"
}, },
"shopping": { "shopping": {
"title": "Alışveriş", "title": "Alışveriş",
@@ -227,7 +233,8 @@
"catDrinks": "İçecekler", "catDrinks": "İçecekler",
"catHousehold": "Ev Gereçleri", "catHousehold": "Ev Gereçleri",
"catDrugstore": "Eczane", "catDrugstore": "Eczane",
"catMisc": "Diğer" "catMisc": "Diğer",
"emptyAction": "Öğe ekle"
}, },
"meals": { "meals": {
"title": "Yemek Planı", "title": "Yemek Planı",
@@ -403,7 +410,8 @@
"formatLink": "Bağlantı", "formatLink": "Bağlantı",
"formatCode": "Kod", "formatCode": "Kod",
"formatQuote": "Alıntı", "formatQuote": "Alıntı",
"formatDivider": "Ayırıcı" "formatDivider": "Ayırıcı",
"emptyAction": "Not oluştur"
}, },
"contacts": { "contacts": {
"title": "Kişiler", "title": "Kişiler",
@@ -456,7 +464,8 @@
"categoryInsurance": "Sigorta", "categoryInsurance": "Sigorta",
"categoryCraftsman": "Usta", "categoryCraftsman": "Usta",
"categoryEmergency": "Acil", "categoryEmergency": "Acil",
"categoryOther": "Diğer" "categoryOther": "Diğer",
"emptyAction": "Kişi ekle"
}, },
"budget": { "budget": {
"title": "Bütçe", "title": "Bütçe",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Name of the new category:", "newCategoryPrompt": "Name of the new category:",
"newSubcategoryPrompt": "Name of the new subcategory:", "newSubcategoryPrompt": "Name of the new subcategory:",
"categoryAddedToast": "Category added.", "categoryAddedToast": "Category added.",
"subcategoryAddedToast": "Subcategory added." "subcategoryAddedToast": "Subcategory added.",
"emptyAction": "Giriş ekle"
}, },
"settings": { "settings": {
"title": "Ayarlar", "title": "Ayarlar",
@@ -843,7 +853,8 @@
"titleRequired": "Başlık gerekli", "titleRequired": "Başlık gerekli",
"duplicate": "Çoğalt", "duplicate": "Çoğalt",
"duplicated": "Tarif çoğaltıldı.", "duplicated": "Tarif çoğaltıldı.",
"copySuffix": "kopya" "copySuffix": "kopya",
"emptyAction": "Tarif oluştur"
}, },
"search": { "search": {
"title": "Arama", "title": "Arama",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "Gezinme ve Modüller",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "Aşağıda Gösterge Paneli ve Takvim'e doğrudan erişebilirsiniz. ···-düğmesiyle Mutfak, Notlar ve Kişiler gibi ek modülleri açabilirsiniz.",
"step3Title": "Ready to go", "step3Title": "Hızlıca başlayın",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "+ düğmesiyle her yerde yeni girişler oluşturabilirsiniz. Hızlı işlemler için liste öğelerini sola veya sağa kaydırın.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "Невідома помилка", "unknownError": "Невідома помилка",
"confirm": "Підтвердити", "confirm": "Підтвердити",
"undo": "Скасувати", "undo": "Скасувати",
"reset": "Скинути до оригіналу" "reset": "Скинути до оригіналу",
"errorOffline": "Немає підключення до інтернету. Перевірте мережу.",
"errorForbidden": "Доступ заборонено. Будь ласка, увійдіть знову.",
"errorNotFound": "Запис не знайдено.",
"errorServer": "Помилка сервера. Спробуйте пізніше.",
"errorTimeout": "З'єднання тривало занадто довго. Спробуйте ще раз."
}, },
"nav": { "nav": {
"dashboard": "Огляд", "dashboard": "Огляд",
@@ -187,7 +192,8 @@
"archiveButton": "Архівувати завдання", "archiveButton": "Архівувати завдання",
"archivedToast": "Завдання архівовано.", "archivedToast": "Завдання архівовано.",
"kanbanArchived": "Архівовано", "kanbanArchived": "Архівовано",
"reminderNeedsDueDate": "Встановіть дату виконання, щоб увімкнути нагадування про завдання." "reminderNeedsDueDate": "Встановіть дату виконання, щоб увімкнути нагадування про завдання.",
"emptyAction": "Створити завдання"
}, },
"shopping": { "shopping": {
"title": "Покупки", "title": "Покупки",
@@ -227,7 +233,8 @@
"catDrinks": "Напої", "catDrinks": "Напої",
"catHousehold": "Господарські товари", "catHousehold": "Господарські товари",
"catDrugstore": "Аптека", "catDrugstore": "Аптека",
"catMisc": "Різне" "catMisc": "Різне",
"emptyAction": "Додати товар"
}, },
"meals": { "meals": {
"title": "План харчування", "title": "План харчування",
@@ -403,7 +410,8 @@
"formatLink": "Посилання", "formatLink": "Посилання",
"formatCode": "Код", "formatCode": "Код",
"formatQuote": "Цитата", "formatQuote": "Цитата",
"formatDivider": "Розділювач" "formatDivider": "Розділювач",
"emptyAction": "Створити нотатку"
}, },
"contacts": { "contacts": {
"title": "Контакти", "title": "Контакти",
@@ -456,7 +464,8 @@
"categoryInsurance": "Страхування", "categoryInsurance": "Страхування",
"categoryCraftsman": "Майстер", "categoryCraftsman": "Майстер",
"categoryEmergency": "Екстрена служба", "categoryEmergency": "Екстрена служба",
"categoryOther": "Інше" "categoryOther": "Інше",
"emptyAction": "Додати контакт"
}, },
"budget": { "budget": {
"title": "Бюджет", "title": "Бюджет",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Name of the new category:", "newCategoryPrompt": "Name of the new category:",
"newSubcategoryPrompt": "Name of the new subcategory:", "newSubcategoryPrompt": "Name of the new subcategory:",
"categoryAddedToast": "Category added.", "categoryAddedToast": "Category added.",
"subcategoryAddedToast": "Subcategory added." "subcategoryAddedToast": "Subcategory added.",
"emptyAction": "Додати запис"
}, },
"settings": { "settings": {
"title": "Налаштування", "title": "Налаштування",
@@ -874,7 +884,8 @@
"titleRequired": "Назва обов'язкова", "titleRequired": "Назва обов'язкова",
"duplicate": "Дублювати", "duplicate": "Дублювати",
"duplicated": "Рецепт продубльовано.", "duplicated": "Рецепт продубльовано.",
"copySuffix": "копія" "copySuffix": "копія",
"emptyAction": "Створити рецепт"
}, },
"search": { "search": {
"title": "Пошук", "title": "Пошук",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "Навігація та модулі",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "Унизу ви маєте прямий доступ до Панелі керування та Календаря. Кнопка ··· відкриває додаткові модулі: Кухня, Нотатки та Контакти.",
"step3Title": "Ready to go", "step3Title": "Починайте швидко",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "За допомогою кнопки + створюйте нові записи будь-де. Проведіть пальцем по елементу списку ліворуч або праворуч для швидких дій.",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+22 -11
View File
@@ -29,7 +29,12 @@
"unknownError": "未知错误", "unknownError": "未知错误",
"confirm": "确认", "confirm": "确认",
"undo": "撤销", "undo": "撤销",
"reset": "重置为原始" "reset": "重置为原始",
"errorOffline": "无网络连接。请检查您的网络。",
"errorForbidden": "访问被拒绝。请重新登录。",
"errorNotFound": "未找到该条目。",
"errorServer": "服务器错误。请稍后重试。",
"errorTimeout": "连接超时。请重试。"
}, },
"nav": { "nav": {
"dashboard": "概览", "dashboard": "概览",
@@ -187,7 +192,8 @@
"archiveButton": "归档任务", "archiveButton": "归档任务",
"archivedToast": "任务已归档。", "archivedToast": "任务已归档。",
"kanbanArchived": "已归档", "kanbanArchived": "已归档",
"reminderNeedsDueDate": "设置截止日期以启用任务提醒。" "reminderNeedsDueDate": "设置截止日期以启用任务提醒。",
"emptyAction": "创建任务"
}, },
"shopping": { "shopping": {
"title": "购物", "title": "购物",
@@ -227,7 +233,8 @@
"catDrinks": "饮料", "catDrinks": "饮料",
"catHousehold": "家居", "catHousehold": "家居",
"catDrugstore": "日化", "catDrugstore": "日化",
"catMisc": "其他" "catMisc": "其他",
"emptyAction": "添加商品"
}, },
"meals": { "meals": {
"title": "饮食计划", "title": "饮食计划",
@@ -403,7 +410,8 @@
"formatLink": "链接", "formatLink": "链接",
"formatCode": "代码", "formatCode": "代码",
"formatQuote": "引用", "formatQuote": "引用",
"formatDivider": "分隔线" "formatDivider": "分隔线",
"emptyAction": "创建笔记"
}, },
"contacts": { "contacts": {
"title": "联系人", "title": "联系人",
@@ -456,7 +464,8 @@
"categoryInsurance": "保险", "categoryInsurance": "保险",
"categoryCraftsman": "技工", "categoryCraftsman": "技工",
"categoryEmergency": "紧急联系", "categoryEmergency": "紧急联系",
"categoryOther": "其他" "categoryOther": "其他",
"emptyAction": "添加联系人"
}, },
"budget": { "budget": {
"title": "预算", "title": "预算",
@@ -555,7 +564,8 @@
"newCategoryPrompt": "Name of the new category:", "newCategoryPrompt": "Name of the new category:",
"newSubcategoryPrompt": "Name of the new subcategory:", "newSubcategoryPrompt": "Name of the new subcategory:",
"categoryAddedToast": "Category added.", "categoryAddedToast": "Category added.",
"subcategoryAddedToast": "Subcategory added." "subcategoryAddedToast": "Subcategory added.",
"emptyAction": "添加记录"
}, },
"settings": { "settings": {
"title": "设置", "title": "设置",
@@ -843,7 +853,8 @@
"titleRequired": "标题必填", "titleRequired": "标题必填",
"duplicate": "复制", "duplicate": "复制",
"duplicated": "食谱已复制。", "duplicated": "食谱已复制。",
"copySuffix": "副本" "copySuffix": "副本",
"emptyAction": "创建食谱"
}, },
"search": { "search": {
"title": "搜索", "title": "搜索",
@@ -913,10 +924,10 @@
"onboarding": { "onboarding": {
"step1Title": "Welcome to Oikos", "step1Title": "Welcome to Oikos",
"step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.", "step1Body": "Your personal family planner. Tasks, calendar, shopping and more all in one place.",
"step2Title": "Everything at a glance", "step2Title": "导航与模块",
"step2Body": "Use the navigation below to reach all modules. The + button creates new entries quickly.", "step2Body": "底部可直接访问仪表板和日历。点击···按钮可打开厨房、笔记和联系人等更多模块。",
"step3Title": "Ready to go", "step3Title": "快速开始",
"step3Body": "The dashboard shows you the most important information at a glance. Customize it under \"Customize\".", "step3Body": "点击+按钮可在任意位置创建新条目。向左或向右滑动列表项可执行快捷操作。",
"next": "Next", "next": "Next",
"done": "Get started", "done": "Get started",
"skip": "Skip" "skip": "Skip"
+7
View File
@@ -332,6 +332,9 @@ function renderBody() {
`; `;
if (window.lucide) lucide.createIcons(); if (window.lucide) lucide.createIcons();
_container.querySelector('#empty-cta-budget')?.addEventListener('click', () => {
document.querySelector('.page-fab')?.click();
});
stagger(_container.querySelector('#budget-list')?.querySelectorAll('.budget-entry') ?? []); stagger(_container.querySelector('#budget-list')?.querySelectorAll('.budget-entry') ?? []);
_container.querySelector('#budget-list')?.addEventListener('click', async (e) => { _container.querySelector('#budget-list')?.addEventListener('click', async (e) => {
@@ -378,6 +381,10 @@ function renderEntries() {
<div class="empty-state__title">${t('budget.emptyTitle')}</div> <div class="empty-state__title">${t('budget.emptyTitle')}</div>
<div class="empty-state__description">${t('budget.emptyDescription')}</div> <div class="empty-state__description">${t('budget.emptyDescription')}</div>
<p class="empty-state__hint">${t('emptyHint.budget')}</p> <p class="empty-state__hint">${t('emptyHint.budget')}</p>
<button class="btn btn--primary empty-state__cta" id="empty-cta-budget">
<i data-lucide="plus" aria-hidden="true" class="icon-base"></i>
${t('budget.emptyAction')}
</button>
</div>`; </div>`;
} }
+7
View File
@@ -181,9 +181,16 @@ function renderList() {
<div class="empty-state__title">${t('contacts.emptyTitle')}</div> <div class="empty-state__title">${t('contacts.emptyTitle')}</div>
<div class="empty-state__description">${t('contacts.emptyDescription')}</div> <div class="empty-state__description">${t('contacts.emptyDescription')}</div>
<p class="empty-state__hint">${t('emptyHint.contacts')}</p> <p class="empty-state__hint">${t('emptyHint.contacts')}</p>
<button class="btn btn--primary empty-state__cta" id="empty-cta-contacts">
<i data-lucide="plus" aria-hidden="true" class="icon-base"></i>
${t('contacts.emptyAction')}
</button>
</div> </div>
`; `;
if (window.lucide) lucide.createIcons(); if (window.lucide) lucide.createIcons();
container.querySelector('#empty-cta-contacts')?.addEventListener('click', () => {
document.querySelector('.page-fab')?.click();
});
return; return;
} }
+2 -2
View File
@@ -19,8 +19,8 @@ const ONBOARDING_KEY = 'oikos-onboarded';
function getOnboardingSteps() { function getOnboardingSteps() {
return [ return [
{ icon: 'home', title: t('onboarding.step1Title'), body: t('onboarding.step1Body') }, { icon: 'home', title: t('onboarding.step1Title'), body: t('onboarding.step1Body') },
{ icon: 'grid-2x2', title: t('onboarding.step2Title'), body: t('onboarding.step2Body') }, { icon: 'navigation', title: t('onboarding.step2Title'), body: t('onboarding.step2Body') },
{ icon: 'circle-check', title: t('onboarding.step3Title'), body: t('onboarding.step3Body') }, { icon: 'plus-circle', title: t('onboarding.step3Title'), body: t('onboarding.step3Body') },
]; ];
} }
+8 -1
View File
@@ -146,10 +146,17 @@ function renderGrid() {
</svg> </svg>
<div class="empty-state__title">${isFiltered ? t('notes.noResultsTitle') : t('notes.emptyTitle')}</div> <div class="empty-state__title">${isFiltered ? t('notes.noResultsTitle') : t('notes.emptyTitle')}</div>
<div class="empty-state__description">${isFiltered ? t('notes.noResultsDescription', { query: state.filterQuery }) : t('notes.emptyDescription')}</div> <div class="empty-state__description">${isFiltered ? t('notes.noResultsDescription', { query: state.filterQuery }) : t('notes.emptyDescription')}</div>
${!isFiltered ? `<p class="empty-state__hint">${t('emptyHint.notes')}</p>` : ''} ${!isFiltered ? `<p class="empty-state__hint">${t('emptyHint.notes')}</p>
<button class="btn btn--primary empty-state__cta" id="empty-cta-notes">
<i data-lucide="plus" aria-hidden="true" class="icon-base"></i>
${t('notes.emptyAction')}
</button>` : ''}
</div> </div>
`; `;
if (window.lucide) lucide.createIcons(); if (window.lucide) lucide.createIcons();
grid.querySelector('#empty-cta-notes')?.addEventListener('click', () => {
document.querySelector('.page-fab')?.click();
});
return; return;
} }
+9 -1
View File
@@ -131,8 +131,16 @@ function renderRecipeList() {
const emptyHint = document.createElement('p'); const emptyHint = document.createElement('p');
emptyHint.className = 'empty-state__hint'; emptyHint.className = 'empty-state__hint';
emptyHint.textContent = t('emptyHint.recipes'); emptyHint.textContent = t('emptyHint.recipes');
empty.append(emptyTitle, emptyDesc, emptyHint); const emptyCta = document.createElement('button');
emptyCta.className = 'btn btn--primary empty-state__cta';
emptyCta.insertAdjacentHTML('afterbegin', '<i data-lucide="plus" aria-hidden="true" class="icon-base"></i>');
emptyCta.append(document.createTextNode(t('recipes.emptyAction')));
emptyCta.addEventListener('click', () => {
document.querySelector('.page-fab')?.click();
});
empty.append(emptyTitle, emptyDesc, emptyHint, emptyCta);
list.appendChild(empty); list.appendChild(empty);
if (window.lucide) window.lucide.createIcons({ el: empty });
return; return;
} }
+7
View File
@@ -172,6 +172,10 @@ function renderItems() {
<div class="empty-state__title">${t('shopping.emptyList')}</div> <div class="empty-state__title">${t('shopping.emptyList')}</div>
<div class="empty-state__description">${t('shopping.emptyListDescription')}</div> <div class="empty-state__description">${t('shopping.emptyListDescription')}</div>
<p class="empty-state__hint">${t('emptyHint.shopping')}</p> <p class="empty-state__hint">${t('emptyHint.shopping')}</p>
<button class="btn btn--primary empty-state__cta" id="empty-cta-shopping">
<i data-lucide="plus" aria-hidden="true" class="icon-base"></i>
${t('shopping.emptyAction')}
</button>
</div>`; </div>`;
} }
@@ -527,6 +531,9 @@ function updateItemsList(container) {
stagger(listEl.querySelectorAll('.shopping-item')); stagger(listEl.querySelectorAll('.shopping-item'));
wireSwipeGestures(container); wireSwipeGestures(container);
maybeShowSwipeHint(container); maybeShowSwipeHint(container);
listEl.querySelector('#empty-cta-shopping')?.addEventListener('click', () => {
document.querySelector('.page-fab')?.click();
});
} }
// clear-checked Button aktualisieren // clear-checked Button aktualisieren
const checkedCount = state.items.filter((i) => i.is_checked).length; const checkedCount = state.items.filter((i) => i.is_checked).length;
+7
View File
@@ -268,6 +268,10 @@ function renderTaskGroups(tasks, groupMode) {
<div class="empty-state__title">${t('tasks.emptyTitle')}</div> <div class="empty-state__title">${t('tasks.emptyTitle')}</div>
<div class="empty-state__description">${t('tasks.emptyDescription')}</div> <div class="empty-state__description">${t('tasks.emptyDescription')}</div>
<p class="empty-state__hint">${t('emptyHint.tasks')}</p> <p class="empty-state__hint">${t('emptyHint.tasks')}</p>
<button class="btn btn--primary empty-state__cta" id="empty-cta-tasks">
<i data-lucide="plus" aria-hidden="true" class="icon-base"></i>
${t('tasks.emptyAction')}
</button>
</div>`; </div>`;
} }
@@ -1029,6 +1033,9 @@ function renderTaskList(container) {
updateOverdueBadge(); updateOverdueBadge();
wireSwipeGestures(container); wireSwipeGestures(container);
maybeShowSwipeHint(container); maybeShowSwipeHint(container);
listEl.querySelector('#empty-cta-tasks')?.addEventListener('click', () => {
document.querySelector('.page-fab')?.click();
});
} }
function renderFilters(container) { function renderFilters(container) {
+73 -12
View File
@@ -465,7 +465,13 @@ function renderAppShell(container) {
const sidebarItems = document.createElement('div'); const sidebarItems = document.createElement('div');
sidebarItems.className = 'nav-sidebar__items'; sidebarItems.className = 'nav-sidebar__items';
sidebarItems.setAttribute('role', 'list'); sidebarItems.setAttribute('role', 'list');
navItems().forEach((item) => sidebarItems.appendChild(navItemEl(item))); navItems()
.filter((item) => !item.kitchenGroup)
.forEach((item) => {
sidebarItems.appendChild(navItemEl(item));
if (item.path === '/calendar') sidebarItems.appendChild(sidebarKitchenEl());
});
if (window.lucide) window.lucide.createIcons({ el: sidebarItems });
sidebar.appendChild(sidebarLogo); sidebar.appendChild(sidebarLogo);
sidebar.appendChild(sidebarItems); sidebar.appendChild(sidebarItems);
@@ -521,7 +527,7 @@ function renderAppShell(container) {
moreBtn.setAttribute('aria-label', t('nav.more')); moreBtn.setAttribute('aria-label', t('nav.more'));
moreBtn.setAttribute('aria-expanded', 'false'); moreBtn.setAttribute('aria-expanded', 'false');
const moreBtnIcon = document.createElement('i'); const moreBtnIcon = document.createElement('i');
moreBtnIcon.dataset.lucide = 'grid-2x2'; moreBtnIcon.dataset.lucide = 'ellipsis';
moreBtnIcon.className = 'nav-item__icon'; moreBtnIcon.className = 'nav-item__icon';
moreBtnIcon.setAttribute('aria-hidden', 'true'); moreBtnIcon.setAttribute('aria-hidden', 'true');
const moreBtnLabel = document.createElement('span'); const moreBtnLabel = document.createElement('span');
@@ -547,7 +553,7 @@ function renderAppShell(container) {
dragHandle.className = 'more-sheet__handle'; dragHandle.className = 'more-sheet__handle';
dragHandle.setAttribute('aria-hidden', 'true'); dragHandle.setAttribute('aria-hidden', 'true');
moreSheet.insertAdjacentElement('afterbegin', dragHandle); moreSheet.insertAdjacentElement('afterbegin', dragHandle);
navItems().filter((i) => !i.sidebarOnly).slice(PRIMARY_NAV).forEach((item) => moreSheet.appendChild(moreItemEl(item))); navItems().filter((i) => !i.kitchenGroup).slice(PRIMARY_NAV).forEach((item) => moreSheet.appendChild(moreItemEl(item)));
const searchOverlay = document.createElement('div'); const searchOverlay = document.createElement('div');
searchOverlay.className = 'search-overlay'; searchOverlay.className = 'search-overlay';
@@ -945,10 +951,10 @@ function navItems() {
{ path: '/budget', label: t('nav.budget'), icon: 'wallet' }, { path: '/budget', label: t('nav.budget'), icon: 'wallet' },
{ path: '/documents', label: t('nav.documents'), icon: 'folder-lock' }, { path: '/documents', label: t('nav.documents'), icon: 'folder-lock' },
{ path: '/settings', label: t('nav.settings'), icon: 'settings' }, { path: '/settings', label: t('nav.settings'), icon: 'settings' },
// Sidebar only (Küche-Gruppe): // Kitchen-Gruppe: via Küche-Nav-Button (Bottom-Nav + Sidebar) + kitchen-tabs-bar erreichbar
{ path: '/meals', label: t('nav.meals'), icon: 'utensils', sidebarOnly: true }, { path: '/meals', label: t('nav.meals'), icon: 'utensils', kitchenGroup: true },
{ path: '/recipes', label: t('nav.recipes'), icon: 'book-text', sidebarOnly: true }, { path: '/recipes', label: t('nav.recipes'), icon: 'book-text', kitchenGroup: true },
{ path: '/shopping', label: t('nav.shopping'), icon: 'shopping-cart', sidebarOnly: true }, { path: '/shopping', label: t('nav.shopping'), icon: 'shopping-cart', kitchenGroup: true },
]; ];
} }
@@ -972,6 +978,30 @@ function navItemEl({ path, label, icon }) {
return a; return a;
} }
function sidebarKitchenEl() {
const a = document.createElement('a');
a.href = '/meals';
a.id = 'sidebar-kitchen-nav';
a.className = 'nav-item';
a.setAttribute('role', 'listitem');
a.setAttribute('aria-label', t('nav.kitchen'));
a.setAttribute('title', t('nav.kitchen'));
const icon = document.createElement('i');
icon.dataset.lucide = 'utensils';
icon.className = 'nav-item__icon';
icon.setAttribute('aria-hidden', 'true');
const label = document.createElement('span');
label.className = 'nav-item__label';
label.textContent = t('nav.kitchen');
a.appendChild(icon);
a.appendChild(label);
a.addEventListener('click', (e) => {
e.preventDefault();
navigate(getLastKitchenRoute());
});
return a;
}
function moreItemEl({ path, label, icon }) { function moreItemEl({ path, label, icon }) {
const a = document.createElement('a'); const a = document.createElement('a');
a.href = path; a.href = path;
@@ -1008,9 +1038,18 @@ function updateNav(path) {
kitchenNavBtn.toggleAttribute('aria-current', isKitchen); kitchenNavBtn.toggleAttribute('aria-current', isKitchen);
} }
const sidebarKitchenNav = document.querySelector('#sidebar-kitchen-nav');
if (sidebarKitchenNav) {
if (isKitchenRoute(path)) {
sidebarKitchenNav.setAttribute('aria-current', 'page');
} else {
sidebarKitchenNav.removeAttribute('aria-current');
}
}
const moreBtn = document.querySelector('#more-btn'); const moreBtn = document.querySelector('#more-btn');
if (moreBtn) { if (moreBtn) {
const secondaryItems = navItems().filter((i) => !i.sidebarOnly).slice(PRIMARY_NAV); const secondaryItems = navItems().filter((i) => !i.kitchenGroup).slice(PRIMARY_NAV);
const activeSecondary = secondaryItems.find((n) => n.path === path); const activeSecondary = secondaryItems.find((n) => n.path === path);
const inMoreSheet = !!activeSecondary; const inMoreSheet = !!activeSecondary;
@@ -1123,6 +1162,20 @@ function showToast(message, type = 'default', duration = 3000, onUndo = null) {
// Event-Listener // Event-Listener
// -------------------------------------------------------- // --------------------------------------------------------
// --------------------------------------------------------
// Fehler-Hilfsfunktion
// --------------------------------------------------------
function friendlyError(err) {
if (!navigator.onLine) return t('common.errorOffline');
const status = err?.status ?? err?.response?.status;
if (status === 403) return t('common.errorForbidden');
if (status === 404) return t('common.errorNotFound');
if (status >= 500) return t('common.errorServer');
if (err?.name === 'AbortError' || err?.name === 'TimeoutError') return t('common.errorTimeout');
return err?.data?.error || err?.message || t('common.errorGeneric');
}
// -------------------------------------------------------- // --------------------------------------------------------
// Globale Fehler-Handler (Error Boundary) // Globale Fehler-Handler (Error Boundary)
// -------------------------------------------------------- // --------------------------------------------------------
@@ -1138,8 +1191,7 @@ window.addEventListener('unhandledrejection', (e) => {
// Auth-Fehler werden bereits von auth:expired behandelt // Auth-Fehler werden bereits von auth:expired behandelt
if (e.reason?.status === 401) return; if (e.reason?.status === 401) return;
console.error('[Oikos] Unbehandeltes Promise-Rejection:', e.reason); console.error('[Oikos] Unbehandeltes Promise-Rejection:', e.reason);
const msg = e.reason?.message || t('common.errorGeneric'); showToast(friendlyError(e.reason), 'danger');
showToast(msg, 'danger');
e.preventDefault(); // Konsolenfehler unterdrücken (bereits geloggt) e.preventDefault(); // Konsolenfehler unterdrücken (bereits geloggt)
}); });
@@ -1189,7 +1241,15 @@ window.addEventListener('locale-changed', () => {
if (moreBtnLabel) moreBtnLabel.textContent = t('nav.more'); if (moreBtnLabel) moreBtnLabel.textContent = t('nav.more');
if (navSidebarItems) { if (navSidebarItems) {
navSidebarItems.replaceChildren(...navItems().map(navItemEl)); const sidebarEls = [];
navItems()
.filter((item) => !item.kitchenGroup)
.forEach((item) => {
sidebarEls.push(navItemEl(item));
if (item.path === '/calendar') sidebarEls.push(sidebarKitchenEl());
});
navSidebarItems.replaceChildren(...sidebarEls);
if (window.lucide) window.lucide.createIcons({ el: navSidebarItems });
} }
if (bottomItems) { if (bottomItems) {
const kitchenBtnEl = bottomItems.querySelector('#kitchen-btn'); const kitchenBtnEl = bottomItems.querySelector('#kitchen-btn');
@@ -1202,7 +1262,7 @@ window.addEventListener('locale-changed', () => {
} }
if (moreSheet) { if (moreSheet) {
const handle = moreSheet.querySelector('.more-sheet__handle'); const handle = moreSheet.querySelector('.more-sheet__handle');
const newMoreItems = navItems().filter((i) => !i.sidebarOnly).slice(PRIMARY_NAV).map(moreItemEl); const newMoreItems = navItems().filter((i) => !i.kitchenGroup).slice(PRIMARY_NAV).map(moreItemEl);
moreSheet.replaceChildren(handle, ...newMoreItems); moreSheet.replaceChildren(handle, ...newMoreItems);
} }
@@ -1294,6 +1354,7 @@ if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
window.oikos = { window.oikos = {
navigate, navigate,
showToast, showToast,
friendlyError,
setThemeColor, setThemeColor,
applyTheme: (value) => { applyTheme: (value) => {
localStorage.setItem('oikos-theme', value); localStorage.setItem('oikos-theme', value);
+7 -3
View File
@@ -127,17 +127,21 @@
} }
.dashboard-metric__title { .dashboard-metric__title {
font-size: var(--text-xs); font-size: var(--text-2xs);
color: var(--color-text-secondary); color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.07em;
font-weight: var(--font-weight-medium);
} }
.dashboard-metric__value { .dashboard-metric__value {
font-size: var(--text-base); font-size: var(--text-xl);
font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-bold);
color: var(--color-text-primary); color: var(--color-text-primary);
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
line-height: var(--line-height-tight);
} }
.dashboard-metric__hint { .dashboard-metric__hint {
+1 -1
View File
@@ -28,7 +28,7 @@
align-items: center; align-items: center;
gap: var(--space-1); gap: var(--space-1);
padding: 0 var(--space-3); padding: 0 var(--space-3);
height: 36px; height: var(--target-base);
border-radius: var(--radius-full); border-radius: var(--radius-full);
border: none; border: none;
background: transparent; background: transparent;
+10 -7
View File
@@ -287,7 +287,7 @@
background-color: var(--color-surface); background-color: var(--color-surface);
z-index: calc(var(--z-nav) + 3); z-index: calc(var(--z-nav) + 3);
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column;
transform: translateY(100%); transform: translateY(100%);
transition: transform 0.25s var(--ease-out); transition: transform 0.25s var(--ease-out);
} }
@@ -300,8 +300,8 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-3); gap: var(--space-3);
padding: var(--space-3) var(--space-4) calc(var(--space-4) + var(--safe-area-inset-bottom)); padding: calc(var(--space-3) + var(--safe-area-inset-top)) var(--space-4) var(--space-3);
border-top: 1px solid var(--color-border-subtle); border-bottom: 1px solid var(--color-border-subtle);
} }
.search-overlay__input { .search-overlay__input {
@@ -343,8 +343,7 @@
.search-overlay__results { .search-overlay__results {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
padding: var(--space-4) var(--space-4) var(--space-2); padding: var(--space-3) var(--space-4) calc(var(--space-4) + var(--safe-area-inset-bottom));
padding-top: calc(var(--space-4) + var(--safe-area-inset-top));
} }
.search-overlay__empty { .search-overlay__empty {
@@ -677,7 +676,7 @@
} }
/* Tooltip für collapsed Sidebar (nur Icons sichtbar bei 10241439px) */ /* Tooltip für collapsed Sidebar (nur Icons sichtbar bei 10241439px) */
@media (min-width: 1024px) and (max-width: 1439px) { @media (min-width: 1024px) and (max-width: 1279px) {
.nav-sidebar .nav-item { .nav-sidebar .nav-item {
overflow: visible; overflow: visible;
} }
@@ -711,7 +710,7 @@
/* ================================================================ /* ================================================================
* Sidebar Expanded (≥ 1280px) - Labels sichtbar * Sidebar Expanded (≥ 1280px) - Labels sichtbar
* ================================================================ */ * ================================================================ */
@media (min-width: 1440px) { @media (min-width: 1280px) {
:root { :root {
--sidebar-width: var(--sidebar-width-expanded); --sidebar-width: var(--sidebar-width-expanded);
} }
@@ -1463,6 +1462,10 @@
text-align: center; text-align: center;
} }
.empty-state__cta {
margin-top: var(--space-2);
}
.empty-state--compact { .empty-state--compact {
padding: var(--space-4) var(--space-3); padding: var(--space-4) var(--space-3);
gap: var(--space-2); gap: var(--space-2);
+1 -1
View File
@@ -59,7 +59,7 @@
background-color: transparent; background-color: transparent;
color: var(--color-text-secondary); color: var(--color-text-secondary);
transition: all var(--transition-fast); transition: all var(--transition-fast);
min-height: 36px; min-height: var(--target-base);
} }
.list-tab:hover:not(.list-tab--active) { .list-tab:hover:not(.list-tab--active) {