From c97d4037a6189a69ccebbc84cb5fc5c023c3f981 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Tue, 29 Aug 2023 13:02:51 -0700 Subject: [PATCH 01/15] update node.js version in readme for prisma 5.0 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 19935ed5..02a44e1e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ A detailed getting started guide can be found at [https://umami.is/docs/](https: ### Requirements -- A server with Node.js version 12 or newer +- A server with Node.js version 16.13 or newer - A database. Umami supports [MySQL](https://www.mysql.com/) and [Postgresql](https://www.postgresql.org/) databases. ### Install Yarn From 69410f4a55ac813867811136a6e6d2b5a2dd20ab Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Tue, 29 Aug 2023 13:56:40 -0700 Subject: [PATCH 02/15] fix yup validation on password change --- src/pages/api/me/password.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/api/me/password.ts b/src/pages/api/me/password.ts index 6f49a182..a601f5d6 100644 --- a/src/pages/api/me/password.ts +++ b/src/pages/api/me/password.ts @@ -23,7 +23,6 @@ export interface UserPasswordRequestBody { const schema = { POST: yup.object().shape({ - id: yup.string().uuid().required(), currentPassword: yup.string().required(), newPassword: yup.string().min(8).required(), }), From e1909364d3fbb21b5bb1d254dfd63dae1d75726b Mon Sep 17 00:00:00 2001 From: essesoul <58624474+essesoul@users.noreply.github.com> Date: Wed, 30 Aug 2023 23:36:39 +0800 Subject: [PATCH 03/15] Update zh-CN.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Chinese translation✍️ --- src/lang/zh-CN.json | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/lang/zh-CN.json b/src/lang/zh-CN.json index 91043dac..bab833c0 100644 --- a/src/lang/zh-CN.json +++ b/src/lang/zh-CN.json @@ -16,19 +16,19 @@ "label.before": "之前", "label.bounce-rate": "跳出率", "label.breakdown": "故障", - "label.browser": "Browser", + "label.browser": "浏览器", "label.browsers": "浏览器", "label.cancel": "取消", "label.change-password": "更新密码", "label.cities": "市/县", - "label.city": "City", + "label.city": "市/县", "label.clear-all": "清除全部", "label.confirm": "确认", "label.confirm-password": "确认密码", "label.contains": "包含", "label.continue": "继续", "label.countries": "国家/地区", - "label.country": "Country", + "label.country": "国家/地区", "label.create-report": "创建报告", "label.create-team": "创建团队", "label.create-user": "创建用户", @@ -37,9 +37,9 @@ "label.custom-range": "自定义时间段", "label.dashboard": "仪表板", "label.data": "统计数据", - "label.date": "Date", + "label.date": "日期", "label.date-range": "时间段", - "label.day": "Day", + "label.day": "日", "label.default-date-range": "默认时间段", "label.delete": "删除", "label.delete-team": "删除团队", @@ -48,7 +48,7 @@ "label.description": "描述", "label.desktop": "台式机", "label.details": "详细信息", - "label.device": "Device", + "label.device": "设备", "label.devices": "设备", "label.dismiss": "关闭", "label.does-not-contain": "不包含", @@ -72,8 +72,8 @@ "label.insights": "见解", "label.is": "等于", "label.is-not": "不等于", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", + "label.is-not-set": "未设置", + "label.is-set": "已设置", "label.join": "加入", "label.join-team": "加入团队", "label.language": "语言", @@ -92,16 +92,16 @@ "label.min": "最小", "label.mobile": "手机", "label.more": "更多", - "label.my-websites": "My websites", + "label.my-websites": "我的网站", "label.name": "名字", "label.new-password": "新密码", "label.none": "无", "label.os": "OS", "label.overview": "概览", "label.owner": "所有者", - "label.page-of": "Page {current} of {total}", + "label.page-of": "总{total}中的第{current}页", "label.page-views": "页面浏览量", - "label.pageTitle": "Page title", + "label.pageTitle": "标题", "label.pages": "网页", "label.password": "密码", "label.powered-by": "由 {name} 提供支持", @@ -110,18 +110,18 @@ "label.query": "查询", "label.query-parameters": "查询参数", "label.realtime": "实时", - "label.referrer": "Referrer", + "label.referrer": "来源", "label.referrers": "来源域名", "label.refresh": "刷新", "label.regenerate": "重新生成", - "label.region": "Region", + "label.region": "州/省", "label.regions": "州/省", "label.remove": "移除", "label.reports": "报告", "label.required": "必填", "label.reset": "重置", "label.reset-website": "重置统计数据", - "label.retention": "Retention", + "label.retention": "保留", "label.role": "角色", "label.run-query": "查询", "label.save": "保存", @@ -138,9 +138,9 @@ "label.team-guest": "团队访客", "label.team-id": "团队 ID", "label.team-member": "团队成员", - "label.team-name": "Team name", + "label.team-name": "团队名称", "label.team-owner": "团队所有者", - "label.team-websites": "Team websites", + "label.team-websites": "团队网站", "label.teams": "团队", "label.theme": "主题", "label.this-month": "本月", @@ -155,19 +155,19 @@ "label.tracking-code": "跟踪代码", "label.true": "是", "label.type": "类型", - "label.unique": "Unique", + "label.unique": "独立", "label.unique-visitors": "独立访客", "label.unknown": "未知", "label.untitled": "未命名", - "label.url": "URL", - "label.urls": "URLs", + "label.url": "网址", + "label.urls": "网址", "label.user": "用户", "label.username": "用户名", "label.users": "用户", "label.value": "值", "label.view": "查看", "label.view-details": "查看更多", - "label.view-only": "View only", + "label.view-only": "仅浏览量", "label.views": "浏览量", "label.visitors": "访客", "label.website": "网站", @@ -183,7 +183,7 @@ "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": "无效域名", From 50b4ac9889c2bc74a4fdd3aabbb719b774acc56e Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Wed, 30 Aug 2023 09:52:24 -0700 Subject: [PATCH 04/15] add optional check for subdivision --- src/lib/detect.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/detect.ts b/src/lib/detect.ts index 86f812bd..d6043506 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -71,7 +71,7 @@ export async function getLocation(ip, req) { return { country, - subdivision1: subdivision1.includes('-') ? subdivision1 : `${country}-${subdivision1}`, + subdivision1: subdivision1?.includes('-') ? subdivision1 : `${country}-${subdivision1}`, city, }; } @@ -84,7 +84,7 @@ export async function getLocation(ip, req) { return { country, - subdivision1: subdivision1.includes('-') ? subdivision1 : `${country}-${subdivision1}`, + subdivision1: subdivision1?.includes('-') ? subdivision1 : `${country}-${subdivision1}`, city, }; } From 33ffa0b3d13a5fe96f25337c9115b120cc4825a8 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 15:23:08 -0700 Subject: [PATCH 05/15] Added paging to dashboard. --- src/components/pages/dashboard/Dashboard.js | 53 +++++++++---------- .../pages/dashboard/DashboardEdit.js | 28 ++++++---- src/pages/api/websites/index.ts | 9 +++- src/queries/admin/report.ts | 1 + src/queries/admin/team.ts | 1 + src/queries/admin/website.ts | 3 +- 6 files changed, 56 insertions(+), 39 deletions(-) diff --git a/src/components/pages/dashboard/Dashboard.js b/src/components/pages/dashboard/Dashboard.js index 8248cc81..2294b8be 100644 --- a/src/components/pages/dashboard/Dashboard.js +++ b/src/components/pages/dashboard/Dashboard.js @@ -1,8 +1,8 @@ -import { useState } from 'react'; -import { Button, Icon, Icons, Text, Flexbox } from 'react-basics'; +import { Button, Icon, Icons, Text } from 'react-basics'; import Link from 'next/link'; import Page from 'components/layout/Page'; import PageHeader from 'components/layout/PageHeader'; +import Pager from 'components/common/Pager'; import WebsiteChartList from 'components/pages/websites/WebsiteChartList'; import DashboardSettingsButton from 'components/pages/dashboard/DashboardSettingsButton'; import DashboardEdit from 'components/pages/dashboard/DashboardEdit'; @@ -11,23 +11,24 @@ import useApi from 'components/hooks/useApi'; import useDashboard from 'store/dashboard'; import useMessages from 'components/hooks/useMessages'; import useLocale from 'components/hooks/useLocale'; +import useApiFilter from 'components/hooks/useApiFilter'; export function Dashboard() { const { formatMessage, labels, messages } = useMessages(); - const dashboard = useDashboard(); - const { showCharts, limit, editing } = dashboard; - const [max, setMax] = useState(limit); - const { get, useQuery } = useApi(); - const { data, isLoading, error } = useQuery(['websites'], () => - get('/websites', { includeTeams: 1 }), - ); - const hasData = data && data?.data.length !== 0; - + const { showCharts, editing } = useDashboard(); const { dir } = useLocale(); - - function handleMore() { - setMax(max + limit); - } + const { get, useQuery } = useApi(); + const { page, handlePageChange } = useApiFilter(); + const pageSize = 10; + const { + data: result, + isLoading, + error, + } = useQuery(['websites', page, pageSize], () => + get('/websites', { includeTeams: 1, page, pageSize }), + ); + const { data, count } = result || {}; + const hasData = data && data?.length !== 0; return ( @@ -48,19 +49,17 @@ export function Dashboard() { )} {hasData && ( <> - {editing && } + {editing && } {!editing && ( - - )} - {max < data.length && ( - - - + <> + + + )} )} diff --git a/src/components/pages/dashboard/DashboardEdit.js b/src/components/pages/dashboard/DashboardEdit.js index 4eb259d6..f628599f 100644 --- a/src/components/pages/dashboard/DashboardEdit.js +++ b/src/components/pages/dashboard/DashboardEdit.js @@ -5,23 +5,33 @@ import { Button } from 'react-basics'; import { firstBy } from 'thenby'; import useDashboard, { saveDashboard } from 'store/dashboard'; import useMessages from 'components/hooks/useMessages'; +import useApi from 'components/hooks/useApi'; import styles from './DashboardEdit.module.css'; +import Page from 'components/layout/Page'; const dragId = 'dashboard-website-ordering'; -export function DashboardEdit({ websites }) { +export function DashboardEdit() { const settings = useDashboard(); const { websiteOrder } = settings; const { formatMessage, labels } = useMessages(); const [order, setOrder] = useState(websiteOrder || []); + const { get, useQuery } = useApi(); + const { + data: result, + isLoading, + error, + } = useQuery(['websites'], () => get('/websites', { includeTeams: 1 })); + const { data: websites } = result || {}; - const ordered = useMemo( - () => - websites + const ordered = useMemo(() => { + if (websites) { + return websites .map(website => ({ ...website, order: order.indexOf(website.id) })) - .sort(firstBy('order')), - [websites, order], - ); + .sort(firstBy('order')); + } + return []; + }, [websites, order]); function handleWebsiteDrag({ destination, source }) { if (!destination || destination.index === source.index) return; @@ -49,7 +59,7 @@ export function DashboardEdit({ websites }) { } return ( - <> +
- +
); } diff --git a/src/pages/api/websites/index.ts b/src/pages/api/websites/index.ts index d724f12f..d6009caf 100644 --- a/src/pages/api/websites/index.ts +++ b/src/pages/api/websites/index.ts @@ -42,8 +42,13 @@ export default async ( } = req.auth; if (req.method === 'GET') { - req.query.id = userId; - req.query.pageSize = 100; + if (!req.query.id) { + req.query.id = userId; + } + + if (!req.query.pageSize) { + req.query.pageSize = 100; + } return userWebsites(req as any, res); } diff --git a/src/queries/admin/report.ts b/src/queries/admin/report.ts index a053ba92..59eb7035 100644 --- a/src/queries/admin/report.ts +++ b/src/queries/admin/report.ts @@ -142,6 +142,7 @@ export async function getReports( ...pageFilters, ...(options?.include && { include: options.include }), }); + const count = await prisma.client.report.count({ where, }); diff --git a/src/queries/admin/team.ts b/src/queries/admin/team.ts index 284b218e..cf731ad4 100644 --- a/src/queries/admin/team.ts +++ b/src/queries/admin/team.ts @@ -135,6 +135,7 @@ export async function getTeams( ...pageFilters, ...(options?.include && { include: options?.include }), }); + const count = await prisma.client.team.count({ where }); return { data: teams, count, ...getParameters }; diff --git a/src/queries/admin/website.ts b/src/queries/admin/website.ts index 3d0c773b..cf4570cf 100644 --- a/src/queries/admin/website.ts +++ b/src/queries/admin/website.ts @@ -107,7 +107,8 @@ export async function getWebsites( ...pageFilters, ...(options?.include && { include: options.include }), }); - const count = await prisma.client.website.count({ where }); + + const count = await prisma.client.website.count({ where: { ...where, deletedAt: null } }); return { data: websites, count, ...getParameters }; } From 61df80112a1396e8826a55b13319e33a925cc277 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 15:43:39 -0700 Subject: [PATCH 06/15] Updated subdivision check. --- src/lib/detect.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/lib/detect.ts b/src/lib/detect.ts index d6043506..b16bab7a 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -57,6 +57,14 @@ export function getDevice(screen, os) { } } +function getRegionCode(country, region) { + if (!country || !region) { + return undefined; + } + + return region.includes('-') ? region : `${country}-${region}`; +} + export async function getLocation(ip, req) { // Ignore local ips if (await isLocalhost(ip)) { @@ -71,7 +79,7 @@ export async function getLocation(ip, req) { return { country, - subdivision1: subdivision1?.includes('-') ? subdivision1 : `${country}-${subdivision1}`, + subdivision1: getRegionCode(country, subdivision1), city, }; } @@ -84,7 +92,7 @@ export async function getLocation(ip, req) { return { country, - subdivision1: subdivision1?.includes('-') ? subdivision1 : `${country}-${subdivision1}`, + subdivision1: getRegionCode(country, subdivision1), city, }; } From 62434a3e0ceb5eb8fd9f32701bb28c0a16a38fb6 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 15:49:26 -0700 Subject: [PATCH 07/15] Bump version v2.6.1. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4fda0a22..9745b780 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umami", - "version": "2.6.0", + "version": "2.6.1", "description": "A simple, fast, privacy-focused alternative to Google Analytics.", "author": "Mike Cao ", "license": "MIT", From fac306328dd75f6a5676addae2c968a0be5a40ee Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 16:13:05 -0700 Subject: [PATCH 08/15] Updated language. --- public/intl/messages/zh-CN.json | 60 ++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/public/intl/messages/zh-CN.json b/public/intl/messages/zh-CN.json index 71234564..ec5c441b 100644 --- a/public/intl/messages/zh-CN.json +++ b/public/intl/messages/zh-CN.json @@ -104,7 +104,7 @@ "label.browser": [ { "type": 0, - "value": "Browser" + "value": "浏览器" } ], "label.browsers": [ @@ -134,7 +134,7 @@ "label.city": [ { "type": 0, - "value": "City" + "value": "市/县" } ], "label.clear-all": [ @@ -176,7 +176,7 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "国家/地区" } ], "label.create-report": [ @@ -230,7 +230,7 @@ "label.date": [ { "type": 0, - "value": "Date" + "value": "日期" } ], "label.date-range": [ @@ -242,7 +242,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "日" } ], "label.default-date-range": [ @@ -296,7 +296,7 @@ "label.device": [ { "type": 0, - "value": "Device" + "value": "设备" } ], "label.devices": [ @@ -440,13 +440,13 @@ "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "未设置" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "已设置" } ], "label.join": [ @@ -576,7 +576,7 @@ "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "我的网站" } ], "label.name": [ @@ -618,7 +618,15 @@ "label.page-of": [ { "type": 0, - "value": "Page " + "value": "总" + }, + { + "type": 1, + "value": "total" + }, + { + "type": 0, + "value": "中的第" }, { "type": 1, @@ -626,11 +634,7 @@ }, { "type": 0, - "value": " of " - }, - { - "type": 1, - "value": "total" + "value": "页" } ], "label.page-views": [ @@ -642,7 +646,7 @@ "label.pageTitle": [ { "type": 0, - "value": "Page title" + "value": "标题" } ], "label.pages": [ @@ -704,7 +708,7 @@ "label.referrer": [ { "type": 0, - "value": "Referrer" + "value": "来源" } ], "label.referrers": [ @@ -728,7 +732,7 @@ "label.region": [ { "type": 0, - "value": "Region" + "value": "州/省" } ], "label.regions": [ @@ -770,7 +774,7 @@ "label.retention": [ { "type": 0, - "value": "Retention" + "value": "保留" } ], "label.role": [ @@ -872,7 +876,7 @@ "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "团队名称" } ], "label.team-owner": [ @@ -884,7 +888,7 @@ "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "团队网站" } ], "label.teams": [ @@ -974,7 +978,7 @@ "label.unique": [ { "type": 0, - "value": "Unique" + "value": "独立" } ], "label.unique-visitors": [ @@ -998,13 +1002,13 @@ "label.url": [ { "type": 0, - "value": "URL" + "value": "网址" } ], "label.urls": [ { "type": 0, - "value": "URLs" + "value": "网址" } ], "label.user": [ @@ -1046,7 +1050,7 @@ "label.view-only": [ { "type": 0, - "value": "View only" + "value": "仅浏览量" } ], "label.views": [ @@ -1190,15 +1194,15 @@ "message.event-log": [ { "type": 1, - "value": "event" + "value": "url" }, { "type": 0, - "value": " on " + "value": "上的" }, { "type": 1, - "value": "url" + "value": "event" } ], "message.go-to-settings": [ From a7ea2027853be35254039df07422d9e89fa0607c Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 16:33:06 -0700 Subject: [PATCH 09/15] Check for payload. --- src/pages/api/send.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/api/send.ts b/src/pages/api/send.ts index a379f261..56a748e1 100644 --- a/src/pages/api/send.ts +++ b/src/pages/api/send.ts @@ -79,6 +79,10 @@ export default async (req: NextApiRequestCollect, res: NextApiResponse) => { const { type, payload } = getJsonBody(req); + if (!type || !payload) { + return badRequest(res); + } + req.yup = schema; await useValidate(req, res); From 620011a837937226b7b25a528a411161c7f10705 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 16:40:32 -0700 Subject: [PATCH 10/15] Removed getJsonBody. --- src/lib/detect.ts | 8 -------- src/lib/session.ts | 6 +++--- src/pages/api/send.ts | 4 ++-- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/lib/detect.ts b/src/lib/detect.ts index b16bab7a..3b2f9021 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -130,11 +130,3 @@ export async function getClientInfo(req: NextApiRequestCollect, { screen }) { return { userAgent, browser, os, ip, country, subdivision1, subdivision2, city, device }; } - -export function getJsonBody(req): T { - if ((req.headers['content-type'] || '').indexOf('text/plain') !== -1) { - return JSON.parse(req.body); - } - - return req.body; -} diff --git a/src/lib/session.ts b/src/lib/session.ts index 85c173c5..0f388db9 100644 --- a/src/lib/session.ts +++ b/src/lib/session.ts @@ -1,7 +1,7 @@ import { isUuid, secret, uuid } from 'lib/crypto'; -import { getClientInfo, getJsonBody } from 'lib/detect'; +import { getClientInfo } from 'lib/detect'; import { parseToken } from 'next-basics'; -import { CollectRequestBody, NextApiRequestCollect } from 'pages/api/send'; +import { NextApiRequestCollect } from 'pages/api/send'; import { createSession } from 'queries'; import cache from './cache'; import clickhouse from './clickhouse'; @@ -22,7 +22,7 @@ export async function findSession(req: NextApiRequestCollect): Promise<{ city: any; ownerId: string; }> { - const { payload } = getJsonBody(req); + const { payload } = req.body; if (!payload) { throw new Error('Invalid payload.'); diff --git a/src/pages/api/send.ts b/src/pages/api/send.ts index 56a748e1..e220711c 100644 --- a/src/pages/api/send.ts +++ b/src/pages/api/send.ts @@ -3,7 +3,7 @@ import ipaddr from 'ipaddr.js'; import isbot from 'isbot'; import { COLLECTION_TYPE, HOSTNAME_REGEX } from 'lib/constants'; import { secret } from 'lib/crypto'; -import { getIpAddress, getJsonBody } from 'lib/detect'; +import { getIpAddress } from 'lib/detect'; import { useCors, useSession, useValidate } from 'lib/middleware'; import { CollectionType, YupRequest } from 'lib/types'; import { NextApiRequest, NextApiResponse } from 'next'; @@ -77,7 +77,7 @@ export default async (req: NextApiRequestCollect, res: NextApiResponse) => { return ok(res); } - const { type, payload } = getJsonBody(req); + const { type, payload } = req.body; if (!type || !payload) { return badRequest(res); From 68ffa823f8a27490b6005a84e44be0d95e2e767c Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 23:53:05 -0700 Subject: [PATCH 11/15] Fixed missing docker middleware. --- Dockerfile | 2 +- src/pages/api/send.ts | 124 +++++++++++++++++++++--------------------- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/Dockerfile b/Dockerfile index bdc678da..e0c7e8c3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,8 +12,8 @@ RUN yarn install --frozen-lockfile FROM node:18-alpine AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules -COPY docker/middleware.js . COPY . . +COPY docker/middleware.js ./src ARG DATABASE_TYPE ARG BASE_PATH diff --git a/src/pages/api/send.ts b/src/pages/api/send.ts index e220711c..00d72104 100644 --- a/src/pages/api/send.ts +++ b/src/pages/api/send.ts @@ -7,7 +7,7 @@ import { getIpAddress } from 'lib/detect'; import { useCors, useSession, useValidate } from 'lib/middleware'; import { CollectionType, YupRequest } from 'lib/types'; import { NextApiRequest, NextApiResponse } from 'next'; -import { badRequest, createToken, forbidden, ok, send } from 'next-basics'; +import { badRequest, createToken, forbidden, methodNotAllowed, ok, send } from 'next-basics'; import { saveEvent, saveSessionData } from 'queries'; import * as yup from 'yup'; @@ -73,75 +73,75 @@ const schema = { export default async (req: NextApiRequestCollect, res: NextApiResponse) => { await useCors(req, res); - if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) { - return ok(res); - } - - const { type, payload } = req.body; - - if (!type || !payload) { - return badRequest(res); - } - - req.yup = schema; - await useValidate(req, res); - - if (await hasBlockedIp(req)) { - return forbidden(res); - } - - const { url, referrer, name: eventName, data: eventData, title: pageTitle } = payload; - - await useSession(req, res); - - const session = req.session; - - if (type === COLLECTION_TYPE.event) { - // eslint-disable-next-line prefer-const - let [urlPath, urlQuery] = url?.split('?') || []; - let [referrerPath, referrerQuery] = referrer?.split('?') || []; - let referrerDomain; - - if (!urlPath) { - urlPath = '/'; + if (req.method === 'POST') { + if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) { + return ok(res); } - if (referrerPath?.startsWith('http')) { - const refUrl = new URL(referrer); - referrerPath = refUrl.pathname; - referrerQuery = refUrl.search.substring(1); - referrerDomain = refUrl.hostname.replace(/www\./, ''); + const { type, payload } = req.body; + + req.yup = schema; + await useValidate(req, res); + + if (await hasBlockedIp(req)) { + return forbidden(res); } - if (process.env.REMOVE_TRAILING_SLASH) { - urlPath = urlPath.replace(/.+\/$/, ''); + const { url, referrer, name: eventName, data: eventData, title: pageTitle } = payload; + + await useSession(req, res); + + const session = req.session; + + if (type === COLLECTION_TYPE.event) { + // eslint-disable-next-line prefer-const + let [urlPath, urlQuery] = url?.split('?') || []; + let [referrerPath, referrerQuery] = referrer?.split('?') || []; + let referrerDomain; + + if (!urlPath) { + urlPath = '/'; + } + + if (referrerPath?.startsWith('http')) { + const refUrl = new URL(referrer); + referrerPath = refUrl.pathname; + referrerQuery = refUrl.search.substring(1); + referrerDomain = refUrl.hostname.replace(/www\./, ''); + } + + if (process.env.REMOVE_TRAILING_SLASH) { + urlPath = urlPath.replace(/.+\/$/, ''); + } + + await saveEvent({ + urlPath, + urlQuery, + referrerPath, + referrerQuery, + referrerDomain, + pageTitle, + eventName, + eventData, + ...session, + sessionId: session.id, + }); } - await saveEvent({ - urlPath, - urlQuery, - referrerPath, - referrerQuery, - referrerDomain, - pageTitle, - eventName, - eventData, - ...session, - sessionId: session.id, - }); + if (type === COLLECTION_TYPE.identify) { + if (!eventData) { + return badRequest(res, 'Data required.'); + } + + await saveSessionData({ ...session, sessionData: eventData, sessionId: session.id }); + } + + const token = createToken(session, secret()); + + return send(res, token); } - if (type === COLLECTION_TYPE.identify) { - if (!eventData) { - return badRequest(res, 'Data required.'); - } - - await saveSessionData({ ...session, sessionData: eventData, sessionId: session.id }); - } - - const token = createToken(session, secret()); - - return send(res, token); + return methodNotAllowed(res); }; async function hasBlockedIp(req: NextApiRequestCollect) { From 5b7cfe83b483b1f6bb83c094a02322867f36c3dd Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 31 Aug 2023 00:08:24 -0700 Subject: [PATCH 12/15] Fixed update notice. --- src/components/common/UpdateNotice.js | 6 ++++-- src/components/common/UpdateNotice.module.css | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/common/UpdateNotice.js b/src/components/common/UpdateNotice.js index e3edc70c..23907948 100644 --- a/src/components/common/UpdateNotice.js +++ b/src/components/common/UpdateNotice.js @@ -1,4 +1,5 @@ import { useEffect, useCallback, useState } from 'react'; +import { createPortal } from 'react-dom'; import { Button, Row, Column } from 'react-basics'; import { setItem } from 'next-basics'; import useStore, { checkVersion } from 'store/version'; @@ -44,7 +45,7 @@ export function UpdateNotice({ user, config }) { return null; } - return ( + return createPortal( {formatMessage(messages.newVersionAvailable, { version: `v${latest}` })} @@ -55,7 +56,8 @@ export function UpdateNotice({ user, config }) { - + , + document.body, ); } diff --git a/src/components/common/UpdateNotice.module.css b/src/components/common/UpdateNotice.module.css index db7a0abd..261a3169 100644 --- a/src/components/common/UpdateNotice.module.css +++ b/src/components/common/UpdateNotice.module.css @@ -2,13 +2,14 @@ position: absolute; max-width: 800px; gap: 20px; - margin: 20px auto; - justify-self: center; + margin: 80px auto; + align-self: center; background: var(--base50); padding: 20px; border: 1px solid var(--base300); border-radius: var(--border-radius); z-index: var(--z-index-popup); + box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.1); } .message { From aa5c84a6efea4a94af4052e8bf915940575b6f86 Mon Sep 17 00:00:00 2001 From: anzepintar Date: Thu, 31 Aug 2023 11:24:28 +0200 Subject: [PATCH 13/15] Update sl-SI.json --- src/lang/sl-SI.json | 306 ++++++++++++++++++++++---------------------- 1 file changed, 153 insertions(+), 153 deletions(-) diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index aae7888d..4e7e4ad9 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -1,211 +1,211 @@ { - "label.access-code": "Access code", + "label.access-code": "Koda za dostop", "label.actions": "Dejanja", - "label.activity-log": "Activity log", - "label.add": "Add", - "label.add-description": "Add description", + "label.activity-log": "Dnevnik dejavnosti", + "label.add": "Dodaj", + "label.add-description": "Dodaj opis", "label.add-website": "Dodaj spletno mesto", "label.admin": "Administrator", - "label.after": "After", - "label.all": "Vse", - "label.all-time": "All time", - "label.analytics": "Analytics", - "label.average": "Average", + "label.after": "Po", + "label.all": "Vsi", + "label.all-time": "Ves čas", + "label.analytics": "Analitika", + "label.average": "Povprečno", "label.average-visit-time": "Povprečni čas obiska", "label.back": "Nazaj", - "label.before": "Before", - "label.bounce-rate": "Zapustna stopnja", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.before": "Pred", + "label.bounce-rate": "Odbojna stopnja", + "label.breakdown": "Razčlenitev", + "label.browser": "Brskalnik", "label.browsers": "Brskalniki", "label.cancel": "Prekliči", "label.change-password": "Zamenjaj geslo", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.confirm": "Confirm", - "label.confirm-password": "Potrditev gesla", - "label.contains": "Contains", - "label.continue": "Continue", + "label.cities": "Mesta", + "label.city": "Mesto", + "label.clear-all": "Počisti vse", + "label.confirm": "Potrdi", + "label.confirm-password": "Potrdi geslo", + "label.contains": "Vsebuje", + "label.continue": "Nadaljuj", "label.countries": "Države", - "label.country": "Country", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", + "label.country": "Država", + "label.create-report": "Ustvari poročilo", + "label.create-team": "Ustvari ekipo", + "label.create-user": "Ustvari uporabnika", + "label.created": "Ustvarjeno", "label.current-password": "Trenutno geslo", - "label.custom-range": "Razpon po meri", + "label.custom-range": "Obdobje po meri", "label.dashboard": "Nadzorna plošča", - "label.data": "Data", - "label.date": "Date", - "label.date-range": "Časovni razpon", - "label.day": "Day", - "label.default-date-range": "Privzeti časovni razpon", + "label.data": "Podatki", + "label.date": "Datum", + "label.date-range": "Časovno obdobje", + "label.day": "Dan", + "label.default-date-range": "Privzeto časovno obdobje", "label.delete": "Izbriši", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-team": "Izbriši ekipo", + "label.delete-user": "Izbriši uporabnika", "label.delete-website": "Izbriši spletno mesto", - "label.description": "Description", + "label.description": "Opis", "label.desktop": "Namizni računalnik", - "label.details": "Details", - "label.device": "Device", + "label.details": "Podrobnosti", + "label.device": "Naprava", "label.devices": "Naprave", - "label.dismiss": "Opusti", - "label.does-not-contain": "Does not contain", + "label.dismiss": "Prezri", + "label.does-not-contain": "Ne vsebuje", "label.domain": "Domena", - "label.dropoff": "Dropoff", + "label.dropoff": "Zapustitev", "label.edit": "Uredi", - "label.edit-dashboard": "Edit dashboard", - "label.enable-share-url": "Omogoči URL za skupno rabo", - "label.event": "Event", - "label.event-data": "Event data", + "label.edit-dashboard": "Uredi nadzorno ploščo", + "label.enable-share-url": "Uredi povezavo za deljenje", + "label.event": "Dogodek", + "label.event-data": "Podatki dogodka", "label.events": "Dogodki", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", - "label.filter-combined": "Skupno", - "label.filter-raw": "Neobdelane meritve", - "label.filters": "Filters", - "label.funnel": "Funnel", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.insights": "Insights", - "label.is": "Is", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.join": "Join", - "label.join-team": "Join team", - "label.language": "Language", - "label.languages": "Languages", + "label.false": "Napačno", + "label.field": "Polje", + "label.fields": "Polja", + "label.filter-combined": "Skupaj", + "label.filter-raw": "Neobdelano", + "label.filters": "Filtri", + "label.funnel": "Prodajni lijak", + "label.greater-than": "Večje od", + "label.greater-than-equals": "Večje ali enako kot", + "label.insights": "Vpogled", + "label.is": "Je", + "label.is-not": "Ni", + "label.is-not-set": "Ni nastavljeno", + "label.is-set": "Je nastavljeno", + "label.join": "Pridruži se", + "label.join-team": "Pridruži se ekipi", + "label.language": "Jezik", + "label.languages": "Jeziki", "label.laptop": "Prenosni računalnik", "label.last-days": "Zadnjih {x} dni", "label.last-hours": "Zadnjih {x} ur", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", + "label.leave": "Zapusti", + "label.leave-team": "Zapusti ekipo", + "label.less-than": "Manjše kot", + "label.less-than-equals": "Manjše ali enako kot", "label.login": "Prijava", "label.logout": "Odjava", - "label.max": "Max", - "label.members": "Members", - "label.min": "Min", - "label.mobile": "Mobilni telefon", + "label.max": "Največ", + "label.members": "Člani", + "label.min": "Najmanj", + "label.mobile": "Mobilne naprave", "label.more": "Več", - "label.my-websites": "My websites", + "label.my-websites": "Moja spletna mesta", "label.name": "Ime", "label.new-password": "Novo geslo", - "label.none": "None", + "label.none": "Brez", "label.os": "OS", - "label.overview": "Overview", - "label.owner": "Owner", - "label.page-of": "Page {current} of {total}", - "label.page-views": "Ogledi strani", - "label.pageTitle": "Page title", + "label.overview": "Pregled", + "label.owner": "Lastnik", + "label.page-of": "Stran {current} od {total}", + "label.page-views": "Obiski strani", + "label.pageTitle": "Naslov strani", "label.pages": "Strani", "label.password": "Geslo", - "label.powered-by": "Zagotavlja {name}", + "label.powered-by": "Poganja {name}", "label.profile": "Profil", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", - "label.realtime": "V realnem času", - "label.referrer": "Referrer", + "label.queries": "Poizvedbe", + "label.query": "Poizvedba", + "label.query-parameters": "Parametri poizvedbe", + "label.realtime": "V živo", + "label.referrer": "Vir", "label.referrers": "Viri", "label.refresh": "Osveži", - "label.regenerate": "Regenerate", - "label.region": "Region", - "label.regions": "Regions", - "label.remove": "Remove", - "label.reports": "Reports", + "label.regenerate": "Ponovno generiraj", + "label.region": "Regija", + "label.regions": "Regije", + "label.remove": "Odstrani", + "label.reports": "Poročila", "label.required": "Zahtevano", "label.reset": "Ponastavi", - "label.reset-website": "Reset statistics", - "label.retention": "Retention", - "label.role": "Role", - "label.run-query": "Run query", + "label.reset-website": "Ponastavi statistiko", + "label.retention": "Ohranjanje uporabnikov", + "label.role": "Vloga", + "label.run-query": "Izvedi poizvedbo", "label.save": "Shrani", - "label.screens": "Screens", - "label.select-date": "Select date", - "label.select-website": "Select website", - "label.sessions": "Sessions", + "label.screens": "Zasloni", + "label.select-date": "Izberi datum", + "label.select-website": "Izberi spletno mesto", + "label.sessions": "Seje", "label.settings": "Nastavitve", - "label.share-url": "Deli URL", + "label.share-url": "Deli povezavo", "label.single-day": "En dan", - "label.sum": "Sum", + "label.sum": "Seštevek", "label.tablet": "Tablični računalnik", - "label.team": "Team", - "label.team-guest": "Team guest", - "label.team-id": "Team ID", - "label.team-member": "Team member", - "label.team-name": "Team name", - "label.team-owner": "Team owner", - "label.team-websites": "Team websites", - "label.teams": "Teams", - "label.theme": "Theme", + "label.team": "Ekipa", + "label.team-guest": "Gost ekipe", + "label.team-id": "ID ekipe", + "label.team-member": "Član ekipe", + "label.team-name": "Ime ekipe", + "label.team-owner": "Lastnik ekipe", + "label.team-websites": "Spletna mesta ekipe", + "label.teams": "Ekipe", + "label.theme": "Tema", "label.this-month": "Ta mesec", "label.this-week": "Ta teden", - "label.this-year": "Letos", + "label.this-year": "To leto", "label.timezone": "Časovni pas", - "label.title": "Title", + "label.title": "Naslov", "label.today": "Danes", - "label.toggle-charts": "Toggle charts", - "label.total": "Total", - "label.total-records": "Total records", + "label.toggle-charts": "Preklopi grafe", + "label.total": "Skupaj", + "label.total-records": "Skupni zapisi", "label.tracking-code": "Koda za sledenje", - "label.true": "True", - "label.type": "Type", - "label.unique": "Unique", + "label.true": "Pravilno", + "label.type": "Vrsta", + "label.unique": "Unikatni", "label.unique-visitors": "Unikatni obiskovalci", "label.unknown": "Neznano", - "label.untitled": "Untitled", - "label.url": "URL", - "label.urls": "URLs", - "label.user": "User", + "label.untitled": "Brez naslova", + "label.url": "Povezava", + "label.urls": "Povezave", + "label.user": "Uporabnik", "label.username": "Uporabniško ime", - "label.users": "Users", - "label.value": "Value", - "label.view": "View", - "label.view-details": "Prikaži podrobnosti", - "label.view-only": "View only", - "label.views": "Ogledi", + "label.users": "Uporabniki", + "label.value": "Vrednost", + "label.view": "Poglej", + "label.view-details": "Poglej podrobnosti", + "label.view-only": "Samo ogledovanje", + "label.views": "Obiski", "label.visitors": "Obiskovalci", - "label.website": "Website", - "label.website-id": "Website ID", - "label.websites": "Spletna mesta", - "label.window": "Window", - "label.yesterday": "Yesterday", - "message.active-users": "{x} trenutni {x, plural, one {obiskovalec} other {obiskovalcev}}", + "label.website": "Spletno mesto", + "label.website-id": "ID spletnega mesta", + "label.websites": "Spletnih mest", + "label.window": "Okno", + "label.yesterday": "Včeraj", + "message.active-users": "{x} trenutni {x, plural, one {visitor} ostali {visitors}}", "message.confirm-delete": "Ste prepričani, da želite izbrisati {target}?", - "message.confirm-leave": "Are you sure you want to leave {target}?", - "message.confirm-reset": "Are your sure you want to reset {target}'s statistics?", - "message.delete-account": "To delete this account, type {confirmation} in the box below to confirm.", - "message.delete-website": "To delete this website, type {confirmation} in the box below to confirm.", - "message.delete-website-warning": "Izbrisani bodo tudi vsi povezani podatki.", - "message.error": "Prišlo je do napake.", - "message.event-log": "{event} on {url}", + "message.confirm-leave": "Ste prepričani, da želite zapustiti {target}?", + "message.confirm-reset": "Ste prepričani, da želite ponastaviti statistiko {target}?", + "message.delete-account": "Za potrditev izbrisa tega računa vnesite {confirmation} v spodnje polje.", + "message.delete-website": "Za potrditev izbrisa tega spletnega mesta vnesite {confirmation} v spodnje polje.", + "message.delete-website-warning": "Izbrisani bodo tudi vsi pripadajoči podatki.", + "message.error": "Nekaj je šlo narobe.", + "message.event-log": "{event} na {url}", "message.go-to-settings": "Pojdi v nastavitve", - "message.incorrect-username-password": "Nepravilno uporabniško ime/geslo", + "message.incorrect-username-password": "Nepravilno uporabniško ime/geslo.", "message.invalid-domain": "Neveljavna domena", - "message.min-password-length": "Minimum length of {n} characters", - "message.new-version-available": "A new version of Umami {version} is available!", + "message.min-password-length": "Najmanjša dolžina je {n} znakov", + "message.new-version-available": "Na voljo je nova verzija programa Umami {version}!", "message.no-data-available": "Podatki niso na voljo.", - "message.no-event-data": "No event data is available.", + "message.no-event-data": "Podatki o dogodku niso na voljo.", "message.no-match-password": "Gesli se ne ujemata", - "message.no-results-found": "No results were found.", - "message.no-team-websites": "This team does not have any websites.", - "message.no-teams": "You have not created any teams.", - "message.no-users": "There are no users.", - "message.no-websites-configured": "Ni nastavljenih spletnih mest.", + "message.no-results-found": "Rezultatov ni bilo mogoče najti.", + "message.no-team-websites": "Ta ekipa nima spletnih mest.", + "message.no-teams": "Niste še ustvarili nobene ekipe.", + "message.no-users": "Ni uporabnikov.", + "message.no-websites-configured": "Nimate nastavljenih nobenih spletnih mest.", "message.page-not-found": "Stran ni bila najdena.", - "message.reset-website": "To reset this website, type {confirmation} in the box below to confirm.", - "message.reset-website-warning": "All statistics for this website will be deleted, but your tracking code will remain intact.", + "message.reset-website": "Za ponastavitev izbrisa tega spletnega mesta vnesite {confirmation} v spodnje polje.", + "message.reset-website-warning": "Vse statistike za to spletno mesto bodo izbrisane, koda za sledenje pa bo ostala nespremenjena.", "message.saved": "Uspešno shranjeno.", - "message.share-url": "To je javno dostopen naslov URL za {target}.", - "message.team-already-member": "You are already a member of the team.", - "message.team-not-found": "Team not found.", - "message.team-websites-info": "Websites can be viewed by anyone on the team.", + "message.share-url": "To je javno dostopna povezava za {target}.", + "message.team-already-member": "Ste že član ekipe.", + "message.team-not-found": "Ekipa ni bila najdena.", + "message.team-websites-info": "Spletne strani si lahko ogleda vsak član ekipe.", "message.tracking-code": "Koda za sledenje", - "message.user-deleted": "User deleted.", + "message.user-deleted": "Uporabnik je izbrisan.", "message.visitor-log": "Obiskovalec iz {country} uporablja {browser} na {os} {device}" } From 338d1c62ea7c978beeb6570793d9be70a214487b Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 31 Aug 2023 14:32:59 -0700 Subject: [PATCH 14/15] Updated language files. --- public/intl/messages/sl-SI.json | 318 ++++++++++++++++---------------- src/lang/sl-SI.json | 2 +- 2 files changed, 160 insertions(+), 160 deletions(-) diff --git a/public/intl/messages/sl-SI.json b/public/intl/messages/sl-SI.json index a3af95cb..ee62a315 100644 --- a/public/intl/messages/sl-SI.json +++ b/public/intl/messages/sl-SI.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Koda za dostop" } ], "label.actions": [ @@ -14,19 +14,19 @@ "label.activity-log": [ { "type": 0, - "value": "Activity log" + "value": "Dnevnik dejavnosti" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "Dodaj" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Dodaj opis" } ], "label.add-website": [ @@ -44,31 +44,31 @@ "label.after": [ { "type": 0, - "value": "After" + "value": "Po" } ], "label.all": [ { "type": 0, - "value": "Vse" + "value": "Vsi" } ], "label.all-time": [ { "type": 0, - "value": "All time" + "value": "Ves čas" } ], "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analitika" } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Povprečno" } ], "label.average-visit-time": [ @@ -86,25 +86,25 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Pred" } ], "label.bounce-rate": [ { "type": 0, - "value": "Zapustna stopnja" + "value": "Odbojna stopnja" } ], "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Razčlenitev" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "Brskalnik" } ], "label.browsers": [ @@ -128,43 +128,43 @@ "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Mesta" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "Mesto" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Počisti vse" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Potrdi" } ], "label.confirm-password": [ { "type": 0, - "value": "Potrditev gesla" + "value": "Potrdi geslo" } ], "label.contains": [ { "type": 0, - "value": "Contains" + "value": "Vsebuje" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "Nadaljuj" } ], "label.countries": [ @@ -176,31 +176,31 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Država" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Ustvari poročilo" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Ustvari ekipo" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Ustvari uporabnika" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Ustvarjeno" } ], "label.current-password": [ @@ -212,7 +212,7 @@ "label.custom-range": [ { "type": 0, - "value": "Razpon po meri" + "value": "Obdobje po meri" } ], "label.dashboard": [ @@ -224,31 +224,31 @@ "label.data": [ { "type": 0, - "value": "Data" + "value": "Podatki" } ], "label.date": [ { "type": 0, - "value": "Date" + "value": "Datum" } ], "label.date-range": [ { "type": 0, - "value": "Časovni razpon" + "value": "Časovno obdobje" } ], "label.day": [ { "type": 0, - "value": "Day" + "value": "Dan" } ], "label.default-date-range": [ { "type": 0, - "value": "Privzeti časovni razpon" + "value": "Privzeto časovno obdobje" } ], "label.delete": [ @@ -260,13 +260,13 @@ "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Izbriši ekipo" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Izbriši uporabnika" } ], "label.delete-website": [ @@ -278,7 +278,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Opis" } ], "label.desktop": [ @@ -290,13 +290,13 @@ "label.details": [ { "type": 0, - "value": "Details" + "value": "Podrobnosti" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "Naprava" } ], "label.devices": [ @@ -308,13 +308,13 @@ "label.dismiss": [ { "type": 0, - "value": "Opusti" + "value": "Prezri" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Ne vsebuje" } ], "label.domain": [ @@ -326,7 +326,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Zapustitev" } ], "label.edit": [ @@ -338,25 +338,25 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Uredi nadzorno ploščo" } ], "label.enable-share-url": [ { "type": 0, - "value": "Omogoči URL za skupno rabo" + "value": "Uredi povezavo za deljenje" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Dogodek" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Podatki dogodka" } ], "label.events": [ @@ -368,109 +368,109 @@ "label.false": [ { "type": 0, - "value": "False" + "value": "Napačno" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Polje" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Polja" } ], "label.filter-combined": [ { "type": 0, - "value": "Skupno" + "value": "Skupaj" } ], "label.filter-raw": [ { "type": 0, - "value": "Neobdelane meritve" + "value": "Neobdelano" } ], "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Filtri" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Prodajni lijak" } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Večje od" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Večje ali enako kot" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Vpogled" } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "Je" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Ni" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Ni nastavljeno" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Je nastavljeno" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Pridruži se" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Pridruži se ekipi" } ], "label.language": [ { "type": 0, - "value": "Language" + "value": "Jezik" } ], "label.languages": [ { "type": 0, - "value": "Languages" + "value": "Jeziki" } ], "label.laptop": [ @@ -510,25 +510,25 @@ "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Zapusti" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Zapusti ekipo" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Manjše kot" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Manjše ali enako kot" } ], "label.login": [ @@ -546,25 +546,25 @@ "label.max": [ { "type": 0, - "value": "Max" + "value": "Največ" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Člani" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "Najmanj" } ], "label.mobile": [ { "type": 0, - "value": "Mobilni telefon" + "value": "Mobilne naprave" } ], "label.more": [ @@ -576,7 +576,7 @@ "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Moja spletna mesta" } ], "label.name": [ @@ -594,7 +594,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Brez" } ], "label.os": [ @@ -606,19 +606,19 @@ "label.overview": [ { "type": 0, - "value": "Overview" + "value": "Pregled" } ], "label.owner": [ { "type": 0, - "value": "Owner" + "value": "Lastnik" } ], "label.page-of": [ { "type": 0, - "value": "Page " + "value": "Stran " }, { "type": 1, @@ -626,7 +626,7 @@ }, { "type": 0, - "value": " of " + "value": " od " }, { "type": 1, @@ -636,13 +636,13 @@ "label.page-views": [ { "type": 0, - "value": "Ogledi strani" + "value": "Obiski strani" } ], "label.pageTitle": [ { "type": 0, - "value": "Page title" + "value": "Naslov strani" } ], "label.pages": [ @@ -660,7 +660,7 @@ "label.powered-by": [ { "type": 0, - "value": "Zagotavlja " + "value": "Poganja " }, { "type": 1, @@ -676,31 +676,31 @@ "label.queries": [ { "type": 0, - "value": "Queries" + "value": "Poizvedbe" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "Poizvedba" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "Parametri poizvedbe" } ], "label.realtime": [ { "type": 0, - "value": "V realnem času" + "value": "V živo" } ], "label.referrer": [ { "type": 0, - "value": "Referrer" + "value": "Vir" } ], "label.referrers": [ @@ -718,31 +718,31 @@ "label.regenerate": [ { "type": 0, - "value": "Regenerate" + "value": "Ponovno generiraj" } ], "label.region": [ { "type": 0, - "value": "Region" + "value": "Regija" } ], "label.regions": [ { "type": 0, - "value": "Regions" + "value": "Regije" } ], "label.remove": [ { "type": 0, - "value": "Remove" + "value": "Odstrani" } ], "label.reports": [ { "type": 0, - "value": "Reports" + "value": "Poročila" } ], "label.required": [ @@ -760,25 +760,25 @@ "label.reset-website": [ { "type": 0, - "value": "Reset statistics" + "value": "Ponastavi statistiko" } ], "label.retention": [ { "type": 0, - "value": "Retention" + "value": "Ohranjanje uporabnikov" } ], "label.role": [ { "type": 0, - "value": "Role" + "value": "Vloga" } ], "label.run-query": [ { "type": 0, - "value": "Run query" + "value": "Izvedi poizvedbo" } ], "label.save": [ @@ -790,25 +790,25 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "Zasloni" } ], "label.select-date": [ { "type": 0, - "value": "Select date" + "value": "Izberi datum" } ], "label.select-website": [ { "type": 0, - "value": "Select website" + "value": "Izberi spletno mesto" } ], "label.sessions": [ { "type": 0, - "value": "Sessions" + "value": "Seje" } ], "label.settings": [ @@ -820,7 +820,7 @@ "label.share-url": [ { "type": 0, - "value": "Deli URL" + "value": "Deli povezavo" } ], "label.single-day": [ @@ -832,7 +832,7 @@ "label.sum": [ { "type": 0, - "value": "Sum" + "value": "Seštevek" } ], "label.tablet": [ @@ -844,55 +844,55 @@ "label.team": [ { "type": 0, - "value": "Team" + "value": "Ekipa" } ], "label.team-guest": [ { "type": 0, - "value": "Team guest" + "value": "Gost ekipe" } ], "label.team-id": [ { "type": 0, - "value": "Team ID" + "value": "ID ekipe" } ], "label.team-member": [ { "type": 0, - "value": "Team member" + "value": "Član ekipe" } ], "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "Ime ekipe" } ], "label.team-owner": [ { "type": 0, - "value": "Team owner" + "value": "Lastnik ekipe" } ], "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "Spletna mesta ekipe" } ], "label.teams": [ { "type": 0, - "value": "Teams" + "value": "Ekipe" } ], "label.theme": [ { "type": 0, - "value": "Theme" + "value": "Tema" } ], "label.this-month": [ @@ -910,7 +910,7 @@ "label.this-year": [ { "type": 0, - "value": "Letos" + "value": "To leto" } ], "label.timezone": [ @@ -922,7 +922,7 @@ "label.title": [ { "type": 0, - "value": "Title" + "value": "Naslov" } ], "label.today": [ @@ -934,19 +934,19 @@ "label.toggle-charts": [ { "type": 0, - "value": "Toggle charts" + "value": "Preklopi grafe" } ], "label.total": [ { "type": 0, - "value": "Total" + "value": "Skupaj" } ], "label.total-records": [ { "type": 0, - "value": "Total records" + "value": "Skupni zapisi" } ], "label.tracking-code": [ @@ -958,19 +958,19 @@ "label.true": [ { "type": 0, - "value": "True" + "value": "Pravilno" } ], "label.type": [ { "type": 0, - "value": "Type" + "value": "Vrsta" } ], "label.unique": [ { "type": 0, - "value": "Unique" + "value": "Unikatni" } ], "label.unique-visitors": [ @@ -988,25 +988,25 @@ "label.untitled": [ { "type": 0, - "value": "Untitled" + "value": "Brez naslova" } ], "label.url": [ { "type": 0, - "value": "URL" + "value": "Povezava" } ], "label.urls": [ { "type": 0, - "value": "URLs" + "value": "Povezave" } ], "label.user": [ { "type": 0, - "value": "User" + "value": "Uporabnik" } ], "label.username": [ @@ -1018,37 +1018,37 @@ "label.users": [ { "type": 0, - "value": "Users" + "value": "Uporabniki" } ], "label.value": [ { "type": 0, - "value": "Value" + "value": "Vrednost" } ], "label.view": [ { "type": 0, - "value": "View" + "value": "Poglej" } ], "label.view-details": [ { "type": 0, - "value": "Prikaži podrobnosti" + "value": "Poglej podrobnosti" } ], "label.view-only": [ { "type": 0, - "value": "View only" + "value": "Samo ogledovanje" } ], "label.views": [ { "type": 0, - "value": "Ogledi" + "value": "Obiski" } ], "label.visitors": [ @@ -1060,31 +1060,31 @@ "label.website": [ { "type": 0, - "value": "Website" + "value": "Spletno mesto" } ], "label.website-id": [ { "type": 0, - "value": "Website ID" + "value": "ID spletnega mesta" } ], "label.websites": [ { "type": 0, - "value": "Spletna mesta" + "value": "Spletnih mest" } ], "label.window": [ { "type": 0, - "value": "Window" + "value": "Okno" } ], "label.yesterday": [ { "type": 0, - "value": "Yesterday" + "value": "Včeraj" } ], "message.active-users": [ @@ -1138,7 +1138,7 @@ "message.confirm-leave": [ { "type": 0, - "value": "Are you sure you want to leave " + "value": "Ste prepričani, da želite zapustiti " }, { "type": 1, @@ -1152,7 +1152,7 @@ "message.confirm-reset": [ { "type": 0, - "value": "Are your sure you want to reset " + "value": "Ste prepričani, da želite ponastaviti statistiko " }, { "type": 1, @@ -1160,13 +1160,13 @@ }, { "type": 0, - "value": "'s statistics?" + "value": "?" } ], "message.delete-account": [ { "type": 0, - "value": "To delete this account, type " + "value": "Za potrditev izbrisa tega računa vnesite " }, { "type": 1, @@ -1174,13 +1174,13 @@ }, { "type": 0, - "value": " in the box below to confirm." + "value": " v spodnje polje." } ], "message.delete-website": [ { "type": 0, - "value": "To delete this website, type " + "value": "Za potrditev izbrisa tega spletnega mesta vnesite " }, { "type": 1, @@ -1188,19 +1188,19 @@ }, { "type": 0, - "value": " in the box below to confirm." + "value": " v spodnje polje." } ], "message.delete-website-warning": [ { "type": 0, - "value": "Izbrisani bodo tudi vsi povezani podatki." + "value": "Izbrisani bodo tudi vsi pripadajoči podatki." } ], "message.error": [ { "type": 0, - "value": "Prišlo je do napake." + "value": "Nekaj je šlo narobe." } ], "message.event-log": [ @@ -1210,7 +1210,7 @@ }, { "type": 0, - "value": " on " + "value": " na " }, { "type": 1, @@ -1226,7 +1226,7 @@ "message.incorrect-username-password": [ { "type": 0, - "value": "Nepravilno uporabniško ime/geslo" + "value": "Nepravilno uporabniško ime/geslo." } ], "message.invalid-domain": [ @@ -1238,7 +1238,7 @@ "message.min-password-length": [ { "type": 0, - "value": "Minimum length of " + "value": "Najmanjša dolžina je " }, { "type": 1, @@ -1246,13 +1246,13 @@ }, { "type": 0, - "value": " characters" + "value": " znakov" } ], "message.new-version-available": [ { "type": 0, - "value": "A new version of Umami " + "value": "Na voljo je nova verzija programa Umami " }, { "type": 1, @@ -1260,7 +1260,7 @@ }, { "type": 0, - "value": " is available!" + "value": "!" } ], "message.no-data-available": [ @@ -1272,7 +1272,7 @@ "message.no-event-data": [ { "type": 0, - "value": "No event data is available." + "value": "Podatki o dogodku niso na voljo." } ], "message.no-match-password": [ @@ -1284,31 +1284,31 @@ "message.no-results-found": [ { "type": 0, - "value": "No results were found." + "value": "Rezultatov ni bilo mogoče najti." } ], "message.no-team-websites": [ { "type": 0, - "value": "This team does not have any websites." + "value": "Ta ekipa nima spletnih mest." } ], "message.no-teams": [ { "type": 0, - "value": "You have not created any teams." + "value": "Niste še ustvarili nobene ekipe." } ], "message.no-users": [ { "type": 0, - "value": "There are no users." + "value": "Ni uporabnikov." } ], "message.no-websites-configured": [ { "type": 0, - "value": "Ni nastavljenih spletnih mest." + "value": "Nimate nastavljenih nobenih spletnih mest." } ], "message.page-not-found": [ @@ -1320,7 +1320,7 @@ "message.reset-website": [ { "type": 0, - "value": "To reset this website, type " + "value": "Za ponastavitev izbrisa tega spletnega mesta vnesite " }, { "type": 1, @@ -1328,13 +1328,13 @@ }, { "type": 0, - "value": " in the box below to confirm." + "value": " v spodnje polje." } ], "message.reset-website-warning": [ { "type": 0, - "value": "All statistics for this website will be deleted, but your tracking code will remain intact." + "value": "Vse statistike za to spletno mesto bodo izbrisane, koda za sledenje pa bo ostala nespremenjena." } ], "message.saved": [ @@ -1346,7 +1346,7 @@ "message.share-url": [ { "type": 0, - "value": "To je javno dostopen naslov URL za " + "value": "To je javno dostopna povezava za " }, { "type": 1, @@ -1360,19 +1360,19 @@ "message.team-already-member": [ { "type": 0, - "value": "You are already a member of the team." + "value": "Ste že član ekipe." } ], "message.team-not-found": [ { "type": 0, - "value": "Team not found." + "value": "Ekipa ni bila najdena." } ], "message.team-websites-info": [ { "type": 0, - "value": "Websites can be viewed by anyone on the team." + "value": "Spletne strani si lahko ogleda vsak član ekipe." } ], "message.tracking-code": [ @@ -1384,7 +1384,7 @@ "message.user-deleted": [ { "type": 0, - "value": "User deleted." + "value": "Uporabnik je izbrisan." } ], "message.visitor-log": [ diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index 4e7e4ad9..440b9fca 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -175,7 +175,7 @@ "label.websites": "Spletnih mest", "label.window": "Okno", "label.yesterday": "Včeraj", - "message.active-users": "{x} trenutni {x, plural, one {visitor} ostali {visitors}}", + "message.active-users": "{x} trenutni {x, plural, one {obiskovalec} other {obiskovalcev}}", "message.confirm-delete": "Ste prepričani, da želite izbrisati {target}?", "message.confirm-leave": "Ste prepričani, da želite zapustiti {target}?", "message.confirm-reset": "Ste prepričani, da želite ponastaviti statistiko {target}?", From b652ef3f7391ebdb5c1c7d947da5fa3d92401a2d Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 31 Aug 2023 14:33:39 -0700 Subject: [PATCH 15/15] Bump version v2.6.2. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9745b780..9759b2b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umami", - "version": "2.6.1", + "version": "2.6.2", "description": "A simple, fast, privacy-focused alternative to Google Analytics.", "author": "Mike Cao ", "license": "MIT",