diff --git a/.github/ISSUE_TEMPLATE/1.bug_report.yml b/.github/ISSUE_TEMPLATE/1.bug_report.yml new file mode 100644 index 00000000..db8be210 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1.bug_report.yml @@ -0,0 +1,32 @@ +name: "🐛 Bug Report" +description: Create a bug report for Umami. +body: + - type: textarea + attributes: + label: Describe the Bug + description: A clear and concise description of what the bug is. + validations: + required: true + - type: dropdown + attributes: + label: Database + description: What database are you using? + options: + - PostgreSQL + - MySQL + - Umami Cloud + validations: + required: true + - type: textarea + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell + - type: input + attributes: + label: Which browser are you using? (if relevant) + description: 'For example: Chrome, Edge, Firefox, etc' + - type: input + attributes: + label: How are you deploying your application? (if relevant) + description: 'For example: Vercel, Railway, Docker, etc' \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/2.feature_request.yml b/.github/ISSUE_TEMPLATE/2.feature_request.yml new file mode 100644 index 00000000..3034767b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2.feature_request.yml @@ -0,0 +1,10 @@ +name: "✨ Feature Request" +description: Create a feature or enhancement request for Umami. +labels: ['enhancement'] +body: + - type: textarea + attributes: + label: Describe the feature or enhancement + description: A clear and concise description of what the feature or enhancement is. + validations: + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..92132929 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,6 @@ + +blank_issues_enabled: false +contact_links: + - name: "🤔 Ask a question" + url: https://github.com/umami-software/umami/discussions + about: Ask questions and discuss with other community members. \ No newline at end of file diff --git a/components/metrics/MetricsTable.js b/components/metrics/MetricsTable.js index 3ad7f434..3bb313cd 100644 --- a/components/metrics/MetricsTable.js +++ b/components/metrics/MetricsTable.js @@ -73,7 +73,10 @@ export function MetricsTable({ const filteredData = useMemo(() => { if (data) { - let items = percentFilter(dataFilter ? dataFilter(data, filterOptions) : data); + const dataWithoutNullValues = data.filter(val => val.x !== null); + let items = percentFilter( + dataFilter ? dataFilter(dataWithoutNullValues, filterOptions) : dataWithoutNullValues, + ); if (limit) { items = items.filter((e, i) => i < limit); } diff --git a/db/clickhouse/schema.sql b/db/clickhouse/schema.sql index 77176413..8f48b434 100644 --- a/db/clickhouse/schema.sql +++ b/db/clickhouse/schema.sql @@ -58,7 +58,10 @@ CREATE TABLE umami.website_event_queue ( --event event_type UInt32, event_name String, - created_at DateTime('UTC') + created_at DateTime('UTC'), + --virtual columns + _error String, + _raw_message String ) ENGINE = Kafka SETTINGS kafka_broker_list = 'domain:9092,domain:9093,domain:9094', -- input broker list @@ -66,7 +69,7 @@ SETTINGS kafka_broker_list = 'domain:9092,domain:9093,domain:9094', -- input bro kafka_group_name = 'event_consumer_group', kafka_format = 'JSONEachRow', kafka_max_block_size = 1048576, - kafka_skip_broken_messages = 100; + kafka_handle_error_mode = 'stream' CREATE MATERIALIZED VIEW umami.website_event_queue_mv TO umami.website_event AS SELECT website_id, @@ -93,6 +96,19 @@ SELECT website_id, created_at FROM umami.website_event_queue; +CREATE MATERIALIZED VIEW umami.website_event_errors_mv +( + error String, + raw String +) +ENGINE = MergeTree +ORDER BY (error, raw) +SETTINGS index_granularity = 8192 AS +SELECT _error AS error, + _raw_message AS raw +FROM umami.website_event_queue +WHERE length(_error) > 0 + CREATE TABLE umami.event_data ( website_id UUID, @@ -122,7 +138,10 @@ CREATE TABLE umami.event_data_queue ( event_numeric_value Nullable(Decimal64(4)), --922337203685477.5625 event_date_value Nullable(DateTime('UTC')), event_data_type UInt32, - created_at DateTime('UTC') + created_at DateTime('UTC'), + --virtual columns + _error String, + _raw_message String ) ENGINE = Kafka SETTINGS kafka_broker_list = 'domain:9092,domain:9093,domain:9094', -- input broker list @@ -130,7 +149,7 @@ SETTINGS kafka_broker_list = 'domain:9092,domain:9093,domain:9094', -- input bro kafka_group_name = 'event_data_consumer_group', kafka_format = 'JSONEachRow', kafka_max_block_size = 1048576, - kafka_skip_broken_messages = 100; + kafka_handle_error_mode = 'stream' CREATE MATERIALIZED VIEW umami.event_data_queue_mv TO umami.event_data AS SELECT website_id, @@ -144,4 +163,17 @@ SELECT website_id, event_date_value, event_data_type, created_at -FROM umami.event_data_queue; \ No newline at end of file +FROM umami.event_data_queue; + +CREATE MATERIALIZED VIEW umami.event_data_errors_mv +( + error String, + raw String +) +ENGINE = MergeTree +ORDER BY (error, raw) +SETTINGS index_granularity = 8192 AS +SELECT _error AS error, + _raw_message AS raw +FROM umami.event_data_queue +WHERE length(_error) > 0 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index bd63c68b..b8da9373 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,8 @@ services: DATABASE_TYPE: postgresql APP_SECRET: replace-me-with-a-random-string depends_on: - - db + db: + condition: service_healthy restart: always db: image: postgres:15-alpine @@ -19,8 +20,12 @@ services: POSTGRES_USER: umami POSTGRES_PASSWORD: umami volumes: - - ./sql/schema.postgresql.sql:/docker-entrypoint-initdb.d/schema.postgresql.sql:ro - umami-db-data:/var/lib/postgresql/data restart: always + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 5s + retries: 5 volumes: umami-db-data: diff --git a/lang-ignore.json b/lang-ignore.json index d4707cda..4a0f9d41 100644 --- a/lang-ignore.json +++ b/lang-ignore.json @@ -1,16 +1,32 @@ { "cs-CZ": ["label.reset", "metrics.device.tablet"], - "de-DE": [ - "label.administrator", - "label.name", + "de-CH": [ + "label.admin", + "label.analytics", + "label.desktop", + "label.details", "label.domain", - "label.theme", - "metrics.device.desktop", - "metrics.device.laptop", - "metrics.device.tablet", - "metrics.referrers", - "metrics.utm", - "metrics.utm_medium" + "label.laptop", + "label.tablet", + "label.name", + "label.sessions", + "label.team", + "label.team-id", + "label.teams" + ], + "de-DE": [ + "label.admin", + "label.analytics", + "label.desktop", + "label.details", + "label.domain", + "label.laptop", + "label.tablet", + "label.name", + "label.sessions", + "label.team", + "label.team-id", + "label.teams" ], "en-GB": "*", "fr-FR": ["metrics.actions", "metrics.pages"], @@ -22,12 +38,15 @@ ], "nb-NO": ["label.administrator", "label.dashboard"], "nl-NL": [ - "label.administrator", - "label.websites", - "metrics.browsers", - "metrics.device.desktop", - "metrics.device.laptop", - "metrics.device.tablet" + "label.analytics", + "label.browsers", + "label.laptop", + "label.tablet", + "label.team", + "label.team-id", + "label.teams", + "label.website-id", + "label.websites" ], "it-IT": [ "label.password", @@ -37,9 +56,5 @@ "metrics.device.tablet", "metrics.filter.raw" ], - "pt-PT": [ - "label.websites", - "metrics.device.desktop", - "metrics.device.tablet" - ] + "pt-PT": ["label.websites", "metrics.device.desktop", "metrics.device.tablet"] } diff --git a/lang/de-CH.json b/lang/de-CH.json index 03980e5c..f8602bc3 100644 --- a/lang/de-CH.json +++ b/lang/de-CH.json @@ -1,7 +1,7 @@ { - "label.access-code": "Access code", + "label.access-code": "Zuegangscode", "label.actions": "Aktione", - "label.activity-log": "Activity log", + "label.activity-log": "Aktivitätsverlauf", "label.add-website": "Websiite hinzuefüege", "label.admin": "Administrator", "label.all": "Alli", @@ -13,24 +13,24 @@ "label.browsers": "Browser", "label.cancel": "Abbreche", "label.change-password": "Passwort ändere", - "label.cities": "Cities", - "label.clear-all": "Clear all", - "label.confirm": "Confirm", + "label.cities": "Städt", + "label.clear-all": "Alles lösche", + "label.confirm": "Bestätige", "label.confirm-password": "Passwort widerhole", - "label.continue": "Continue", + "label.continue": "Wiiter", "label.countries": "Länder", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", + "label.create-team": "Team erstelle", + "label.create-user": "Benutzer erstelle", + "label.created": "Erstellt", "label.current-password": "Jetzigs Passwort", "label.custom-range": "Benutzerdefinierte Bereich", "label.dashboard": "Übersicht", - "label.data": "Data", + "label.data": "Datä", "label.date-range": "Datumsbereich", "label.default-date-range": "Vorigstellte Datumsbereich", "label.delete": "Lösche", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-team": "Team lösche", + "label.delete-user": "Benutzer lösche", "label.delete-website": "Websiite lösche", "label.desktop": "Desktop", "label.details": "Details", @@ -43,104 +43,104 @@ "label.events": "Ereigniss", "label.filter-combined": "Kombiniert", "label.filter-raw": "Rohdate", - "label.join": "Join", - "label.join-team": "Join team", + "label.join": "Biträte", + "label.join-team": "Team biträte", "label.language": "Sprach", "label.languages": "Sprache", "label.laptop": "Laptop", "label.last-days": "Letzti {x} Täg", "label.last-hours": "Letzti {x} Stunde", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.login": "Login", + "label.leave": "Verlah", + "label.leave-team": "Team verlah", + "label.login": "Aamelde", "label.logout": "Abmelde", - "label.members": "Members", + "label.members": "Mitglieder", "label.mobile": "Handy", "label.more": "Meh", "label.name": "Name", "label.new-password": "Neus Passwort", "label.none": "Keis", - "label.operating-systems": "Betriebssystem", + "label.operating-systems": "Betriibssystem", "label.owner": "Bsitzer", "label.page-views": "Siitenufrüef", "label.pages": "Siite", "label.password": "Passwort", "label.powered-by": "Betribe dur {name}", "label.profile": "Profil", - "label.queries": "Queries", + "label.queries": "Abfrage", "label.query-parameters": "Abfragparameter", "label.realtime": "Echtzit", "label.referrers": "Referrer", "label.refresh": "Aktualisiere", - "label.regenerate": "Regenerate", - "label.regions": "Regions", - "label.remove": "Remove", + "label.regenerate": "Erneuere", + "label.regions": "Regionä", + "label.remove": "Entferne", "label.required": "Erforderlich", "label.reset": "Zruggsetze", "label.reset-website": "Statistik zruggsetze", - "label.role": "Role", + "label.role": "Rollä", "label.save": "Speichere", "label.screens": "Bildschirmuflösige", - "label.select-website": "Select website", + "label.select-website": "Websiite uuswähle", "label.sessions": "Sessions", "label.settings": "Istellige", "label.share-url": "Freigab-URL", "label.single-day": "Ein Tag", "label.tablet": "Tablet", "label.team": "Team", - "label.team-guest": "Team guest", + "label.team-guest": "Team Gast", "label.team-id": "Team ID", - "label.team-member": "Team member", - "label.team-owner": "Team owner", + "label.team-member": "Team Mitglied", + "label.team-owner": "Team Bsitzer", "label.teams": "Teams", "label.theme": "Thema", "label.this-month": "De Monet", "label.this-week": "Die Wuche", "label.this-year": "Das Jahr", - "label.timezone": "Zitzone", - "label.title": "Title", + "label.timezone": "Ziitzone", + "label.title": "Titel", "label.today": "Hüt", "label.toggle-charts": "Schaubilder umschalte", "label.tracking-code": "Tracking Code", "label.unique-visitors": "Eidütigi Bsuecher", "label.unknown": "Unbekannt", - "label.user": "User", + "label.user": "Benutzer", "label.username": "Benutzername", - "label.users": "Users", - "label.view": "View", + "label.users": "Benutzer", + "label.view": "Azeige", "label.view-details": "Details azeige", "label.views": "Ufrüef", "label.visitors": "Bsuecher", - "label.website-id": "Website ID", + "label.website-id": "Websiite ID", "label.websites": "Websiite", "label.yesterday": "Gester", "message.active-users": "{x} {x, plural, one {aktive Bsuecher} other {aktivi Bsuecher}}", "message.confirm-delete": "Sind Sie sich sicher, {target} zlösche?", - "message.confirm-leave": "Are you sure you want to leave {target}?", + "message.confirm-leave": "Sind Sie sich sicher, {target} zverlah?", "message.confirm-reset": "Sind Sie sicher, dass Sie dStatistike vo {target} zruggsetze wend?", "message.delete-website": "Websiite lösche", "message.delete-website-warning": "Alli dezueghörige Date werdet ebefalls glöscht.", "message.error": "Es isch en Fehler uftrete.", - "message.event-log": "{event} on {url}", + "message.event-log": "{event} uf {url}", "message.go-to-settings": "Zu de Istellige", "message.incorrect-username-password": "Falschs Passwort oder Benutzername.", "message.invalid-domain": "Ungültigi Domain", - "message.min-password-length": "Minimum length of {n} characters", + "message.min-password-length": "Miminamli längi vo {n} Zeiche", "message.no-data-available": "Kei Date vorhande.", "message.no-match-password": "Passwörter stimmed ned überi", - "message.no-teams": "You have not created any teams.", - "message.no-users": "There are no users.", + "message.no-teams": "Bisher sind no kei Teams erstellt worde.", + "message.no-users": "Da gits kei Benutzer", "message.page-not-found": "Siite ned gfunde.", "message.reset-website": "Statistik zruggsetze", "message.reset-website-warning": "Alli Date für die Websiite werdet glöscht, nur de Tracking Code blibt bestah.", "message.saved": "Erfolgrich gspeichert.", - "message.share-url": "Das isch die öffentlichi URL zum Teile für {target}.", - "message.team-already-member": "You are already a member of the team.", - "message.team-not-found": "Team not found.", + "message.share-url": "Ihri Websiitestatistik isch under de folgende URL öffentlich zuegänglich:", + "message.team-already-member": "Sie sind bereits es Mitglied vo dem Team.", + "message.team-not-found": "Team nöd gfunde.", "message.tracking-code": "Tracking Code", - "message.user-deleted": "User deleted.", + "message.user-deleted": "Benutzer glöscht.", "message.visitor-log": "Bsuecher us {country} benutzt {browser} uf {os} {device}", - "messages.no-team-websites": "This team does not have any websites.", + "messages.no-team-websites": "Dem Team sind kei Websiite zuegordnet.", "messages.no-websites-configured": "Es isch kei Websiite vorhande.", - "messages.team-websites-info": "Websites can be viewed by anyone on the team." + "messages.team-websites-info": "Websiite chönd vo jedem im Team agluegt werde" } diff --git a/lang/de-DE.json b/lang/de-DE.json index 0190d13c..b3611d5b 100644 --- a/lang/de-DE.json +++ b/lang/de-DE.json @@ -19,8 +19,8 @@ "label.confirm-password": "Passwort wiederholen", "label.continue": "Weiter", "label.countries": "Länder", - "label.create-team": "Erstelle Team", - "label.create-user": "Erstelle Nutzer", + "label.create-team": "Team erstellen", + "label.create-user": "Benutzer erstellen", "label.created": "Erstellt", "label.current-password": "Derzeitiges Passwort", "label.custom-range": "Benutzerdefinierter Bereich", @@ -29,8 +29,8 @@ "label.date-range": "Datumsbereich", "label.default-date-range": "Voreingestellter Datumsbereich", "label.delete": "Löschen", - "label.delete-team": "Lösche Team", - "label.delete-user": "Lösche Nutzer", + "label.delete-team": "Team löschen", + "label.delete-user": "Benutzer löschen", "label.delete-website": "Webseite löschen", "label.desktop": "Desktop", "label.details": "Details", @@ -48,8 +48,8 @@ "label.language": "Sprache", "label.languages": "Sprachen", "label.laptop": "Laptop", - "label.last-days": "Letzten {x} Tage", - "label.last-hours": "Letzten {x} Stunden", + "label.last-days": "Letzte {x} Tage", + "label.last-hours": "Letzte {x} Stunden", "label.leave": "Verlassen", "label.leave-team": "Team verlassen", "label.login": "Anmelden", @@ -73,7 +73,7 @@ "label.referrers": "Referrer", "label.refresh": "Aktualisieren", "label.regenerate": "Erneuern", - "label.regions": "Regions", + "label.regions": "Regionen", "label.remove": "Entfernen", "label.required": "Erforderlich", "label.reset": "Zurücksetzen", @@ -101,17 +101,17 @@ "label.title": "Titel", "label.today": "Heute", "label.toggle-charts": "Schaubilder umschalten", - "label.tracking-code": "Tracking Kennung", + "label.tracking-code": "Tracking Code", "label.unique-visitors": "Eindeutige Besucher", "label.unknown": "Unbekannt", - "label.user": "User", + "label.user": "Benutzer", "label.username": "Benutzername", - "label.users": "Users", - "label.view": "View", + "label.users": "Benutzer", + "label.view": "Anzeigen", "label.view-details": "Details anzeigen", "label.views": "Aufrufe", "label.visitors": "Besucher", - "label.website-id": "Website ID", + "label.website-id": "Webseite ID", "label.websites": "Webseiten", "label.yesterday": "Gestern", "message.active-users": "{x} {x, plural, one {aktiver Besucher} other {aktive Besucher}}", @@ -121,7 +121,7 @@ "message.delete-website": "Webseite löschen", "message.delete-website-warning": "Alle zugehörigen Daten werden ebenfalls gelöscht.", "message.error": "Es ist ein Fehler aufgetreten.", - "message.event-log": "{event} on {url}", + "message.event-log": "{event} auf {url}", "message.go-to-settings": "Zu den Einstellungen", "message.incorrect-username-password": "Falsches Passwort oder Benutzername.", "message.invalid-domain": "Ungültige Domain", @@ -129,16 +129,16 @@ "message.no-data-available": "Keine Daten vorhanden.", "message.no-match-password": "Passwörter stimmen nicht überein", "message.no-teams": "Bisher wurden keine Teams erstellt.", - "message.no-users": "Hier gibt es keine Nutzer.", + "message.no-users": "Hier gibt es keine Benutzer.", "message.page-not-found": "Seite nicht gefunden.", "message.reset-website": "Statistik zurücksetzen", "message.reset-website-warning": "Alle Daten für diese Webseite werden gelöscht, jedoch bleibt der Tracking Code bestehen.", "message.saved": "Erfolgreich gespeichert.", - "message.share-url": "Dies ist die öffentliche URL zum Teilen für {target}.", + "message.share-url": "Ihre Webseitenstatistik ist unter der folgenden URL öffentlich zugänglich:", "message.team-already-member": "Sie sind bereits Mitglied des Teams.", "message.team-not-found": "Team nicht gefunden.", - "message.tracking-code": "Tracking Kennung", - "message.user-deleted": "Nutzer gelöscht.", + "message.tracking-code": "Tracking Code", + "message.user-deleted": "Benutzer gelöscht.", "message.visitor-log": "Besucher aus {country} benutzt {browser} auf {os} {device}", "messages.no-team-websites": "Diesem Team sind keine Websites zugeordnet.", "messages.no-websites-configured": "Es ist keine Webseite vorhanden.", diff --git a/lang/mn-MN.json b/lang/mn-MN.json index 9e3b4499..b15076ad 100644 --- a/lang/mn-MN.json +++ b/lang/mn-MN.json @@ -1,7 +1,7 @@ { - "label.access-code": "Access code", + "label.access-code": "Хандалтын код", "label.actions": "Үйлдлүүд", - "label.activity-log": "Activity log", + "label.activity-log": "Үйл ажиллагааны бүртгэл", "label.add-website": "Веб нэмэх", "label.admin": "Админ", "label.all": "Бүх", @@ -13,27 +13,27 @@ "label.browsers": "Хөтөч", "label.cancel": "Цуцлах", "label.change-password": "Нууц үг солих", - "label.cities": "Cities", - "label.clear-all": "Clear all", - "label.confirm": "Confirm", + "label.cities": "Хотууд", + "label.clear-all": "Бүгдийг арилгах", + "label.confirm": "Батлах", "label.confirm-password": "Шинэ нууц үгээ давтах", - "label.continue": "Continue", + "label.continue": "Үргэлжлүүлэх", "label.countries": "Улс", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", + "label.create-team": "Баг үүсгэх", + "label.create-user": "Хэрэглэгч үүсгэх", + "label.created": "Үүсгэсэн", "label.current-password": "Ашиглаж буй нууц үг", "label.custom-range": "Дурын хугацаа", "label.dashboard": "Хянах самбар", - "label.data": "Data", - "label.date-range": "Хугацааны мужид", + "label.data": "Өгөгдөл", + "label.date-range": "Хугацааны муж", "label.default-date-range": "Өгөгдмөл хугацааны муж", "label.delete": "Устгах", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-team": "Баг устгах", + "label.delete-user": "Хэрэглэгч устгах", "label.delete-website": "Веб устгах", "label.desktop": "Суурин компьютер", - "label.details": "Details", + "label.details": "Мэдээлэл", "label.devices": "Төхөөрөмж", "label.dismiss": "Үл хэргэсэх", "label.domain": "Домэйн", @@ -43,18 +43,18 @@ "label.events": "Үйлдэл", "label.filter-combined": "Нэгтгэсэн", "label.filter-raw": "Түүхий", - "label.join": "Join", - "label.join-team": "Join team", + "label.join": "Нэгдэх", + "label.join-team": "Багт нэгдэх", "label.language": "Хэл", "label.languages": "Хэл", "label.laptop": "Зөөврийн компьютер", "label.last-days": "Сүүлийн {x} хоног", "label.last-hours": "Сүүлийн {x} цаг", - "label.leave": "Leave", - "label.leave-team": "Leave team", + "label.leave": "Гарах", + "label.leave-team": "Багаас гарах", "label.login": "Нэвтрэх", "label.logout": "Гарах", - "label.members": "Members", + "label.members": "Гишүүд", "label.mobile": "Утас", "label.more": "Цааш", "label.name": "Нэр", @@ -67,80 +67,80 @@ "label.password": "Нууц үг", "label.powered-by": "{name} дээр суурилсан", "label.profile": "Бүртгэл", - "label.queries": "Queries", + "label.queries": "Query-нүүд", "label.query-parameters": "Query параметр", "label.realtime": "Яг одоо", "label.referrers": "Чиглүүлэгч", "label.refresh": "Сэргээх", - "label.regenerate": "Regenerate", - "label.regions": "Regions", - "label.remove": "Remove", + "label.regenerate": "Дахин үүсгэх", + "label.regions": "Бүсүүд", + "label.remove": "Устгах", "label.required": "Шаардлагатай", - "label.reset": "Хуучин хэвд нь оруулах", + "label.reset": "Дахин эхлүүлэх", "label.reset-website": "Тоон үзүүлэлтийг дахин эхлүүлэх", - "label.role": "Role", + "label.role": "Эрх", "label.save": "Хадгалах", "label.screens": "Дэлгэц", - "label.select-website": "Select website", + "label.select-website": "Веб сонгох", "label.sessions": "Sessions", "label.settings": "Тохиргоо", "label.share-url": "Хуваалцах холбоос", "label.single-day": "Нэг өдөр", "label.tablet": "Таблет", - "label.team": "Team", - "label.team-guest": "Team guest", - "label.team-id": "Team ID", - "label.team-member": "Team member", - "label.team-owner": "Team owner", - "label.teams": "Teams", + "label.team": "Баг", + "label.team-guest": "Багийн зочин", + "label.team-id": "Багийн ID", + "label.team-member": "Багийн гишүүн", + "label.team-owner": "Багийн эзэмшигч", + "label.teams": "Багууд", "label.theme": "Загвар", "label.this-month": "Энэ сар", "label.this-week": "Энэ долоо хоног", "label.this-year": "Энэ жил", "label.timezone": "Цагийн бүс", - "label.title": "Title", + "label.title": "Гарчиг", "label.today": "Өнөөдөр", "label.toggle-charts": "Графикийг харуулах/нуух", "label.tracking-code": "Мөрдөх код", "label.unique-visitors": "Зочин", "label.unknown": "Тодорхойгүй", - "label.user": "User", + "label.user": "Хэрэглэгч", "label.username": "Хэрэглэгчийн нэр", - "label.users": "Users", - "label.view": "View", + "label.users": "Хэрэглэгчид", + "label.view": "Харах", "label.view-details": "Дэлгэрүүлж харах", "label.views": "Үзсэн", "label.visitors": "Зочин", - "label.website-id": "Website ID", + "label.website-id": "Вебийн ID", "label.websites": "Вебүүд", "label.yesterday": "Өчигдөр", "message.active-users": "одоо {x} {x, plural, one {зочин} other {зочин}} байна", "message.confirm-delete": "Та {target}-г устгахдаа итгэлтэй байна уу?", - "message.confirm-leave": "Are you sure you want to leave {target}?", + "message.confirm-leave": "Та {target}-с гарахдаа итгэлтэй байна уу?", "message.confirm-reset": "Та {target}-н тоон үзүүлэлтүүдийг устгахдаа итгэлтэй байна уу?", - "message.delete-website": "Веб устгах", - "message.delete-website-warning": "Үүнтэй холбоотой бүх өгөгдөл устах болно.", + "message.delete-website": "Веб устгахын тулд доорх хэсэгт {confirmation} гэж бичиж, баталгаажуулна уу.", + "message.delete-website-warning": "Энэ вебтэй холбоотой бүх өгөгдөл устах болно.", "message.error": "Ямар нэг зүйл буруу боллоо.", - "message.event-log": "{event} on {url}", + "message.event-log": "{url}-д {event}", "message.go-to-settings": "Тохиргоо руу очих", "message.incorrect-username-password": "Буруу хэрэглэгчийн нэр/нууц үг.", "message.invalid-domain": "Буруу домэйн", - "message.min-password-length": "Minimum length of {n} characters", + "message.min-password-length": "Хамгийн багадаа {n} тэмдэгт", "message.no-data-available": "Өгөгдөл алга.", - "message.no-match-password": "Нууц үг тохирохгүй байна", - "message.no-teams": "You have not created any teams.", - "message.no-users": "There are no users.", + "message.no-match-password": "Нууц үг тохирохгүй байна.", + "message.no-teams": "Та ямар ч баг үүсгээгүй байна.", + "message.no-users": "Хэрэглэгч байхгүй байна.", "message.page-not-found": "Хуудас олдсонгүй.", - "message.reset-website": "Тоон үзүүлэлтийг дахин эхлүүлэх", + "message.reset-website": "Тоон үзүүлэлийг дахин эхлүүлэхийн тулд доорх хэсэгт {confirmation} гэж бичиж, баталгаажуулна уу.", "message.reset-website-warning": "Энэ вебийн бүх тоон үзүүлэлтүүдийг устгах болно. Гэхдээ мөрдөх код хэвэндээ үлдэнэ.", - "message.saved": "Амжилттай хадгаллаа.", - "message.share-url": "{target}-г нийтэд хуваалцах холбоос.", - "message.team-already-member": "You are already a member of the team.", - "message.team-not-found": "Team not found.", - "message.tracking-code": "Мөрдөх код", - "message.user-deleted": "User deleted.", + "message.saved": "Хадгалсан.", + "message.share-url": "Таны вебийн тоон үзүүлэлтүүд доорх URL дээр нийтэд харагдах болно:", + "message.team-already-member": "Та аль хэдийн энэ багийн гишүүн болсон байна.", + "message.team-not-found": "Баг олдсонгүй.", + "message.tracking-code": "Энэ вебийн хандалтуудыг мөрдөхийн тулд доорх кодыг HTML-нхээ
... хэсэгт байрлуулна уу.", + "message.user-deleted": "Хэрэглэгч устсан.", "message.visitor-log": "{country} улсаас {os} {device} дээр {browser} хөтөч ашиглан орсон", - "messages.no-team-websites": "This team does not have any websites.", + "messages.no-team-websites": "Энэ багт ямар ч веб алга.", "messages.no-websites-configured": "Та ямар нэгэн веб тохируулаагүй байна.", - "messages.team-websites-info": "Websites can be viewed by anyone on the team." + "messages.team-websites-info": "Вебийг багийн бүх гишүүд үзэж болно." } diff --git a/lang/nl-NL.json b/lang/nl-NL.json index bac675f9..b86ff423 100644 --- a/lang/nl-NL.json +++ b/lang/nl-NL.json @@ -1,9 +1,9 @@ { - "label.access-code": "Access code", + "label.access-code": "Toegangscode", "label.actions": "Acties", - "label.activity-log": "Activity log", - "label.add-website": "Website toevoegen", - "label.admin": "Administrator", + "label.activity-log": "Activiteiten logboek", + "label.add-website": "Website koppelen", + "label.admin": "Beheerder", "label.all": "Alles", "label.all-time": "Onbeperkt", "label.analytics": "Analytics", @@ -13,48 +13,48 @@ "label.browsers": "Browsers", "label.cancel": "Annuleren", "label.change-password": "Wachtwoord wijzigen", - "label.cities": "Cities", - "label.clear-all": "Clear all", - "label.confirm": "Confirm", + "label.cities": "Steden", + "label.clear-all": "Filters wissen", + "label.confirm": "Bevestigen", "label.confirm-password": "Wachtwoord bevestigen", - "label.continue": "Continue", + "label.continue": "Doorgaan", "label.countries": "Landen", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", + "label.create-team": "Team aanmaken", + "label.create-user": "Gebruiker maken", + "label.created": "Gemaakt", "label.current-password": "Huidig wachtwoord", "label.custom-range": "Aangepast bereik", "label.dashboard": "Overzicht", - "label.data": "Data", + "label.data": "Gegevens", "label.date-range": "Datumbereik", "label.default-date-range": "Standaard bereik", "label.delete": "Verwijderen", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-team": "Team verwijderen", + "label.delete-user": "Verwijder gebruiker", "label.delete-website": "Website verwijderen", - "label.desktop": "Desktop", - "label.details": "Details", + "label.desktop": "Computer", + "label.details": "Informatie", "label.devices": "Apparaten", "label.dismiss": "Negeren", "label.domain": "Domein", "label.edit": "Bewerken", - "label.edit-dashboard": "Edit dashboard", + "label.edit-dashboard": "Dashboard aanpassen", "label.enable-share-url": "Sta delen via openbare URL toe", "label.events": "Gebeurtenissen", "label.filter-combined": "Gecombineerd", "label.filter-raw": "Ruw", - "label.join": "Join", - "label.join-team": "Join team", + "label.join": "Lid worden", + "label.join-team": "Word lid van een team", "label.language": "Taal", - "label.languages": "Languages", + "label.languages": "Talen", "label.laptop": "Laptop", "label.last-days": "Laatste {x} dagen", "label.last-hours": "Laatste {x} uur", - "label.leave": "Leave", - "label.leave-team": "Leave team", + "label.leave": "Verlaten", + "label.leave-team": "Verlaat team", "label.login": "Inloggen", "label.logout": "Uitloggen", - "label.members": "Members", + "label.members": "Gebruikers", "label.mobile": "Mobiel", "label.more": "Toon meer", "label.name": "Naam", @@ -67,80 +67,80 @@ "label.password": "Wachtwoord", "label.powered-by": "mogelijk gemaakt door {name}", "label.profile": "Profiel", - "label.queries": "Queries", - "label.query-parameters": "Query parameters", + "label.queries": "Parameters", + "label.query-parameters": "URL-parameters", "label.realtime": "Actueel", "label.referrers": "Verwijzers", "label.refresh": "Vernieuwen", - "label.regenerate": "Regenerate", - "label.regions": "Regions", - "label.remove": "Remove", + "label.regenerate": "Opnieuw genereren", + "label.regions": "Regio's", + "label.remove": "Verwijderen", "label.required": "Verplicht", - "label.reset": "Resetten", + "label.reset": "Opnieuw instellen", "label.reset-website": "Statistieken opnieuw instellen", - "label.role": "Role", + "label.role": "Gebruikersrol", "label.save": "Opslaan", "label.screens": "Schermen", - "label.select-website": "Select website", - "label.sessions": "Sessions", + "label.select-website": "Website selecteren", + "label.sessions": "Sessies", "label.settings": "Instellingen", "label.share-url": "URL delen", "label.single-day": "Enkele dag", "label.tablet": "Tablet", "label.team": "Team", - "label.team-guest": "Team guest", + "label.team-guest": "Team gast", "label.team-id": "Team ID", - "label.team-member": "Team member", - "label.team-owner": "Team owner", + "label.team-member": "Teamlid", + "label.team-owner": "Teameigenaar", "label.teams": "Teams", "label.theme": "Thema", "label.this-month": "Deze maand", "label.this-week": "Deze week", "label.this-year": "Dit jaar", "label.timezone": "Tijdzone", - "label.title": "Title", + "label.title": "Titel", "label.today": "Vandaag", "label.toggle-charts": "Grafieken tonen/verbergen", "label.tracking-code": "Volgcode", "label.unique-visitors": "Unieke bezoekers", "label.unknown": "Onbekend", - "label.user": "User", + "label.user": "Gebruiker", "label.username": "Gebruikersnaam", - "label.users": "Users", - "label.view": "View", + "label.users": "Gebruikers", + "label.view": "Weergave", "label.view-details": "Meer details", "label.views": "Weergaven", "label.visitors": "Bezoekers", "label.website-id": "Website ID", "label.websites": "Websites", - "label.yesterday": "Yesterday", + "label.yesterday": "Gisteren", "message.active-users": "{x} actieve {x, plural, one {bezoeker} other {bezoekers}}", "message.confirm-delete": "Weet je zeker dat je {target} wilt verwijderen?", - "message.confirm-leave": "Are you sure you want to leave {target}?", + "message.confirm-leave": "Weet je zeker dat je {target} wilt verlaten?", "message.confirm-reset": "Weet je zeker dat je de statistieken van {target} opnieuw wilt instellen?", "message.delete-website": "Website verwijderen", "message.delete-website-warning": "Alle verwante gegezens zullen ook verwijderd worden.", "message.error": "Er is iets misgegaan.", - "message.event-log": "{event} on {url}", + "message.event-log": "{event} op {url}", "message.go-to-settings": "Naar instellingen", "message.incorrect-username-password": "Incorrecte gebruikersnaam/wachtwoord.", "message.invalid-domain": "Ongeldig domein", - "message.min-password-length": "Minimum length of {n} characters", + "message.min-password-length": "Minimale lengte van {n} tekens", "message.no-data-available": "Geen gegevens beschikbaar.", "message.no-match-password": "Wachtwoorden komen niet overeen", - "message.no-teams": "You have not created any teams.", - "message.no-users": "There are no users.", + "message.no-teams": "Er zijn nog geen teams aangemaakt.", + "message.no-users": "Er zijn geen gebruikers.", "message.page-not-found": "Pagina niet gevonden.", "message.reset-website": "Statistieken opnieuw instellen", "message.reset-website-warning": "Alle bijhorende statistieken van deze website worden verwijderd, maar jouw volgcode blijft gelden.", "message.saved": "Opslaan succesvol.", "message.share-url": "Met deze URL kan {target} openbaar gedeeld worden.", - "message.team-already-member": "You are already a member of the team.", - "message.team-not-found": "Team not found.", + "message.team-already-member": "Je bent al lid van het team.", + "message.team-not-found": "Team niet gevonden.", "message.tracking-code": "Volgcode", - "message.user-deleted": "User deleted.", + "message.user-deleted": "Gebruiker verwijderd.", "message.visitor-log": "Bezoeker uit {country} met {browser} op een {os} {device}", - "messages.no-team-websites": "This team does not have any websites.", + "messages.no-team-websites": "Er zijn geen websites gekoppeld aan dit team.", "messages.no-websites-configured": "Je hebt geen websites ingesteld.", - "messages.team-websites-info": "Websites can be viewed by anyone on the team." + "messages.team-websites-info": "Websites kunnen door iedereen in het team worden bekeken." } diff --git a/lang/pt-BR.json b/lang/pt-BR.json index f02b7fb9..590cb33c 100644 --- a/lang/pt-BR.json +++ b/lang/pt-BR.json @@ -1,27 +1,27 @@ { - "label.access-code": "Access code", + "label.access-code": "Código de acesso", "label.actions": "Ações", - "label.activity-log": "Activity log", + "label.activity-log": "Log de atividade", "label.add-website": "Adicionar site", "label.admin": "Administrador", "label.all": "Todos", "label.all-time": "Todo o período", - "label.analytics": "Analytics", + "label.analytics": "Estatísticas", "label.average-visit-time": "Tempo médio da visita", "label.back": "Voltar", "label.bounce-rate": "Taxa de rejeição", "label.browsers": "Navegadores", "label.cancel": "Cancelar", "label.change-password": "Alterar a senha", - "label.cities": "Cities", - "label.clear-all": "Clear all", - "label.confirm": "Confirm", + "label.cities": "Cidades", + "label.clear-all": "Limpar tudo", + "label.confirm": "Confirmar", "label.confirm-password": "Confirme a nova senha", - "label.continue": "Continue", + "label.continue": "Continuar", "label.countries": "Países", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", + "label.create-team": "Criar time", + "label.create-user": "Criar usuário", + "label.created": "Criado", "label.current-password": "Senha atual", "label.custom-range": "Intervalo personalizado", "label.dashboard": "Painel", @@ -29,37 +29,37 @@ "label.date-range": "Intervalo de datas", "label.default-date-range": "Intervalo de datas predefinido", "label.delete": "Remover", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-team": "Remover time", + "label.delete-user": "Remover usuário", "label.delete-website": "Remover site", "label.desktop": "Computador", - "label.details": "Details", + "label.details": "Detalhes", "label.devices": "Dispositivos", "label.dismiss": "Dispensar", "label.domain": "Domínio", "label.edit": "Editar", - "label.edit-dashboard": "Edit dashboard", + "label.edit-dashboard": "Editar painel", "label.enable-share-url": "Ativar link de compartilhamento", "label.events": "Eventos", "label.filter-combined": "Combinado", "label.filter-raw": "Dados brutos", - "label.join": "Join", - "label.join-team": "Join team", + "label.join": "Entrar", + "label.join-team": "Entrar no time", "label.language": "Idioma", "label.languages": "Idiomas", "label.laptop": "Notebook", "label.last-days": "Últimos {x} dias", "label.last-hours": "Últimas {x} horas", - "label.leave": "Leave", - "label.leave-team": "Leave team", + "label.leave": "Sair", + "label.leave-team": "Sair do time", "label.login": "Iniciar sessão", "label.logout": "Sair", - "label.members": "Members", + "label.members": "Membros", "label.mobile": "Celular", "label.more": "Mais", "label.name": "Nome", "label.new-password": "Nova senha", - "label.none": "None", + "label.none": "Nenhum", "label.operating-systems": "Sistemas operacionais", "label.owner": "Proprietário", "label.page-views": "Visualizações de página", @@ -67,80 +67,80 @@ "label.password": "Senha", "label.powered-by": "Distribuído por {name}", "label.profile": "Perfil", - "label.queries": "Queries", + "label.queries": "Parâmetros", "label.query-parameters": "Parâmetros de Consulta", "label.realtime": "Tempo real", "label.referrers": "Referências", "label.refresh": "Atualizar", - "label.regenerate": "Regenerate", - "label.regions": "Regions", - "label.remove": "Remove", + "label.regenerate": "Regerar", + "label.regions": "Regiões", + "label.remove": "Remover", "label.required": "Obrigatório", "label.reset": "Redefinir", "label.reset-website": "Redefinir estatísticas", - "label.role": "Role", + "label.role": "Papel", "label.save": "Salvar", "label.screens": "Telas", - "label.select-website": "Select website", - "label.sessions": "Sessions", + "label.select-website": "Selecionar site", + "label.sessions": "Sessões", "label.settings": "Configurações", "label.share-url": "Link de compartilhamento", "label.single-day": "Dia específico", "label.tablet": "Tablet", - "label.team": "Team", - "label.team-guest": "Team guest", - "label.team-id": "Team ID", - "label.team-member": "Team member", - "label.team-owner": "Team owner", - "label.teams": "Teams", + "label.team": "Time", + "label.team-guest": "Convidado", + "label.team-id": "ID do Time", + "label.team-member": "Membro", + "label.team-owner": "Proprietário", + "label.teams": "Times", "label.theme": "Tema", "label.this-month": "Este mês", "label.this-week": "Esta semana", "label.this-year": "Este ano", "label.timezone": "Fuso horário", - "label.title": "Title", + "label.title": "Título", "label.today": "Hoje", "label.toggle-charts": "Mostrar/Esconder gráficos", "label.tracking-code": "Código de rastreamento", "label.unique-visitors": "Visitantes únicos", "label.unknown": "Desconhecido", - "label.user": "User", + "label.user": "Usuário", "label.username": "Nome de usuário", - "label.users": "Users", - "label.view": "View", + "label.users": "Usuários", + "label.view": "Ver", "label.view-details": "Ver detalhes", "label.views": "Visualizações", "label.visitors": "Visitantes", - "label.website-id": "Website ID", + "label.website-id": "ID do Site", "label.websites": "Sites", "label.yesterday": "Ontem", "message.active-users": "{x} {x, plural, one {visitante} other {visitantes}} neste momento", "message.confirm-delete": "Deseja realmente remover {target}?", - "message.confirm-leave": "Are you sure you want to leave {target}?", + "message.confirm-leave": "Você tem certeza que deseja sair de {target}?", "message.confirm-reset": "Você tem certeza que deseja redefinir as estatísticas de {target}?", "message.delete-website": "Remover site", "message.delete-website-warning": "Todos os dados associados também serão eliminados.", "message.error": "Ocorreu um erro.", - "message.event-log": "{event} on {url}", + "message.event-log": "{event} em {url}", "message.go-to-settings": "Ir para as configurações", "message.incorrect-username-password": "O nome de usuário e/ou senha está incorreto.", "message.invalid-domain": "Domínio inválido", - "message.min-password-length": "Minimum length of {n} characters", + "message.min-password-length": "Quantidade mínima de {n} caracteres", "message.no-data-available": "Sem dados disponíveis.", "message.no-match-password": "As senhas não correspondem", - "message.no-teams": "You have not created any teams.", - "message.no-users": "There are no users.", + "message.no-teams": "Você não criou nenhum time.", + "message.no-users": "Não há nenhum usuário.", "message.page-not-found": "Página não encontrada.", "message.reset-website": "Redefinir estatísticas", "message.reset-website-warning": "Todas as estatísticas deste site serão removidas, mas seu código de rastreamento permanecerá intacto.", "message.saved": "Salvo com sucesso.", "message.share-url": "Este é o link público de compartilhamento para {target}.", - "message.team-already-member": "You are already a member of the team.", - "message.team-not-found": "Team not found.", + "message.team-already-member": "Você já um membro do time.", + "message.team-not-found": "Time não encontrado.", "message.tracking-code": "Código de rastreamento", - "message.user-deleted": "User deleted.", + "message.user-deleted": "Usuário removido.", "message.visitor-log": "Visitante de {country} usando {browser} no {device} {os}", - "messages.no-team-websites": "This team does not have any websites.", + "messages.no-team-websites": "Este time não possui nenhum site.", "messages.no-websites-configured": "Nenhum site foi configurado ainda.", - "messages.team-websites-info": "Websites can be viewed by anyone on the team." + "messages.team-websites-info": "Os sites podem ser visualizados por qualquer membro da equipe." } diff --git a/lib/cache.ts b/lib/cache.ts index 2aad7ed8..e63a53bb 100644 --- a/lib/cache.ts +++ b/lib/cache.ts @@ -2,35 +2,7 @@ import { User, Website } from '@prisma/client'; import redis from '@umami/redis-client'; import { getSession, getUser, getWebsite } from '../queries'; -const DELETED = 'DELETED'; - -async function fetchObject(key, query) { - const obj = await redis.get(key); - - if (obj === DELETED) { - return null; - } - - if (!obj) { - return query().then(async data => { - if (data) { - await redis.set(key, data); - } - - return data; - }); - } - - return obj; -} - -async function storeObject(key, data) { - return redis.set(key, data); -} - -async function deleteObject(key, soft = false) { - return soft ? redis.set(key, DELETED) : redis.del(key); -} +const { fetchObject, storeObject, deleteObject } = redis; async function fetchWebsite(id): Promise