From 71e4f8f49bb468989e34405f449000697b032bfe Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 12 Feb 2025 23:34:27 -0800 Subject: [PATCH 001/399] Start using react-zen. --- package.json | 10 +- src/app/(main)/App.tsx | 23 +- src/app/(main)/NavBar.module.css | 18 +- src/app/(main)/NavBar.tsx | 117 +- src/app/(main)/UpdateNotice.module.css | 38 - src/app/(main)/UpdateNotice.tsx | 22 +- src/app/(main)/boards/BoardsPage.tsx | 3 + src/app/(main)/boards/page.tsx | 10 + src/app/(main)/layout.module.css | 22 - src/app/(main)/layout.tsx | 16 +- src/app/(main)/websites/[websiteId]/page.tsx | 2 +- src/app/Providers.tsx | 22 +- src/app/layout.tsx | 4 +- src/components/common/Pager.tsx | 10 +- src/components/input/LanguageButton.tsx | 54 +- src/components/input/ProfileButton.tsx | 47 +- src/components/input/TeamsButton.tsx | 97 +- src/components/input/ThemeButton.module.css | 14 - src/components/input/ThemeButton.tsx | 38 - src/components/layout/Page.tsx | 4 +- src/styles/global.css | 48 + src/styles/index.css | 106 -- src/styles/variables.css | 12 +- yarn.lock | 1744 ++++++++++++++++-- 24 files changed, 1872 insertions(+), 609 deletions(-) delete mode 100644 src/app/(main)/UpdateNotice.module.css create mode 100644 src/app/(main)/boards/BoardsPage.tsx create mode 100644 src/app/(main)/boards/page.tsx delete mode 100644 src/app/(main)/layout.module.css delete mode 100644 src/components/input/ThemeButton.module.css delete mode 100644 src/components/input/ThemeButton.tsx create mode 100644 src/styles/global.css delete mode 100644 src/styles/index.css diff --git a/package.json b/package.json index b3c3a60f..2667c607 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "@react-spring/web": "^9.7.3", "@tanstack/react-query": "^5.28.6", "@umami/prisma-client": "^0.14.0", + "@umami/react-zen": "^0.50.0", "@umami/redis-client": "^0.26.0", "bcryptjs": "^2.4.3", "chalk": "^4.1.1", @@ -111,7 +112,7 @@ "react-basics": "^0.126.0", "react-dom": "^19.0.0", "react-error-boundary": "^4.0.4", - "react-intl": "^6.5.5", + "react-intl": "^7.1.6", "react-simple-maps": "^2.3.0", "react-use-measure": "^2.0.4", "react-window": "^1.8.6", @@ -126,6 +127,7 @@ "devDependencies": { "@formatjs/cli": "^4.2.29", "@netlify/plugin-nextjs": "^5.8.1", + "@react-spring/types": "^9.7.5", "@rollup/plugin-alias": "^5.0.0", "@rollup/plugin-commonjs": "^25.0.4", "@rollup/plugin-json": "^6.0.0", @@ -135,9 +137,9 @@ "@svgr/webpack": "^8.1.0", "@types/cypress": "^1.1.3", "@types/jest": "^29.5.14", - "@types/node": "^22.10.5", - "@types/react": "^19.0.4", - "@types/react-dom": "^19.0.2", + "@types/node": "^22.13.1", + "@types/react": "^19.0.8", + "@types/react-dom": "^19.0.3", "@types/react-intl": "^3.0.0", "@types/react-window": "^1.8.8", "@typescript-eslint/eslint-plugin": "^6.7.3", diff --git a/src/app/(main)/App.tsx b/src/app/(main)/App.tsx index 4cbb1c80..2d3fd0bd 100644 --- a/src/app/(main)/App.tsx +++ b/src/app/(main)/App.tsx @@ -1,9 +1,11 @@ 'use client'; -import { Loading } from 'react-basics'; +import { Grid, Loading } from '@umami/react-zen'; import Script from 'next/script'; import { usePathname } from 'next/navigation'; -import { useLogin, useConfig } from '@/components/hooks'; import UpdateNotice from './UpdateNotice'; +import NavBar from '@/app/(main)/NavBar'; +import Page from '@/components/layout/Page'; +import { useLogin, useConfig } from '@/components/hooks'; export function App({ children }) { const { user, isLoading, error } = useLogin(); @@ -27,13 +29,16 @@ export function App({ children }) { } return ( - <> - {children} - - {process.env.NODE_ENV === 'production' && !pathname.includes('/share/') && ( - `; return ( - <> -

{formatMessage(messages.trackingCode)}

- - + + {formatMessage(messages.trackingCode)} + + ); } diff --git a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx index 444f0524..d0a17b7f 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx @@ -5,22 +5,24 @@ import { Share, Edit } from '@/components/icons'; import { Favicon } from '@/components/common/Favicon'; import { ActiveUsers } from '@/components/metrics/ActiveUsers'; import { WebsiteShareForm } from '@/app/(main)/settings/websites/[websiteId]/WebsiteShareForm'; -import { useMessages } from '@/components/hooks'; +import { useMessages, useNavigation } from '@/components/hooks'; +import { LinkButton } from '@/components/common/LinkButton'; export function WebsiteHeader() { const website = useWebsite(); + const { renderUrl } = useNavigation(); return ( } showBorder={false}> - + ); diff --git a/src/components/hooks/useDateRange.ts b/src/components/hooks/useDateRange.ts index 9cc1ccad..6a6e16d4 100644 --- a/src/components/hooks/useDateRange.ts +++ b/src/components/hooks/useDateRange.ts @@ -1,55 +1,53 @@ -import { getMinimumUnit, parseDateRange } from '@/lib/date'; +import { getMinimumUnit, parseDateRange, getOffsetDateRange } from '@/lib/date'; import { setItem } from '@/lib/storage'; -import { DATE_RANGE_CONFIG, DEFAULT_DATE_COMPARE, DEFAULT_DATE_RANGE } from '@/lib/constants'; +import { DATE_RANGE_CONFIG, DEFAULT_DATE_COMPARE, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants'; import { setWebsiteDateCompare, setWebsiteDateRange, useWebsites } from '@/store/websites'; -import { setDateRange, useApp } from '@/store/app'; -import { DateRange } from '@/lib/types'; +import { setDateRangeValue, useApp } from '@/store/app'; import { useLocale } from './useLocale'; import { useApi } from './useApi'; import { useNavigation } from './useNavigation'; +import { useMemo } from 'react'; export function useDateRange(websiteId?: string) { const { get } = useApi(); const { locale } = useLocale(); const { - query: { date }, + query: { date, offset = 0 }, } = useNavigation(); const websiteConfig = useWebsites(state => state[websiteId]?.dateRange); - const globalConfig = useApp(state => state.dateRange); - const dateRange = parseDateRange( - date || websiteConfig || globalConfig || DEFAULT_DATE_RANGE, + const globalConfig = useApp(state => state.dateRangeValue); + const dateRangeObject = parseDateRange( + date || websiteConfig?.value || globalConfig || DEFAULT_DATE_RANGE_VALUE, locale, ); + const dateRange = useMemo( + () => (offset ? getOffsetDateRange(dateRangeObject, +offset) : dateRangeObject), + [date, offset], + ); const dateCompare = useWebsites(state => state[websiteId]?.dateCompare || DEFAULT_DATE_COMPARE); - const saveDateRange = async (value: DateRange | string) => { + const saveDateRange = async (value: string) => { if (websiteId) { - let dateRange: DateRange | string = value; + if (value === 'all') { + const result: any = await get(`/websites/${websiteId}/daterange`); + const { mindate, maxdate } = result; - if (typeof value === 'string') { - if (value === 'all') { - const result: any = await get(`/websites/${websiteId}/daterange`); - const { mindate, maxdate } = result; + const startDate = new Date(mindate); + const endDate = new Date(maxdate); + const unit = getMinimumUnit(startDate, endDate); - const startDate = new Date(mindate); - const endDate = new Date(maxdate); - const unit = getMinimumUnit(startDate, endDate); - - dateRange = { - startDate, - endDate, - unit, - value, - }; - } else { - dateRange = parseDateRange(value, locale); - } + setWebsiteDateRange(websiteId, { + startDate, + endDate, + unit, + value, + }); + } else { + setWebsiteDateRange(websiteId, parseDateRange(value, locale)); } - - setWebsiteDateRange(websiteId, dateRange as DateRange); } else { setItem(DATE_RANGE_CONFIG, value); - setDateRange(value); + setDateRangeValue(value); } }; diff --git a/src/components/input/DateFilter.tsx b/src/components/input/DateFilter.tsx index 15b3edd3..72be6c6d 100644 --- a/src/components/input/DateFilter.tsx +++ b/src/components/input/DateFilter.tsx @@ -11,6 +11,7 @@ export interface DateFilterProps { endDate: Date; onChange?: (value: string) => void; showAllTime?: boolean; + renderDate?: boolean; } export function DateFilter({ @@ -18,7 +19,8 @@ export function DateFilter({ startDate, endDate, onChange, - showAllTime = false, + showAllTime, + renderDate, }: DateFilterProps) { const { formatMessage, labels } = useMessages(); const [showPicker, setShowPicker] = useState(false); @@ -89,7 +91,7 @@ export function DateFilter({ }; const renderValue = ({ defaultChildren }) => { - return value?.startsWith('range') ? ( + return value?.startsWith('range') || renderDate ? ( ) : ( defaultChildren diff --git a/src/components/input/WebsiteDateFilter.tsx b/src/components/input/WebsiteDateFilter.tsx index 6842f2d5..afb58631 100644 --- a/src/components/input/WebsiteDateFilter.tsx +++ b/src/components/input/WebsiteDateFilter.tsx @@ -11,7 +11,6 @@ import { import { isAfter } from 'date-fns'; import { Chevron, Close, Compare } from '@/components/icons'; import { useDateRange, useMessages, useNavigation } from '@/components/hooks'; -import { getOffsetDateRange } from '@/lib/date'; import { DateFilter } from './DateFilter'; export function WebsiteDateFilter({ @@ -26,13 +25,13 @@ export function WebsiteDateFilter({ showButtons?: boolean; allowCompare?: boolean; }) { - const { dateRange, saveDateRange } = useDateRange(websiteId); - const { value, startDate, endDate, offset } = dateRange; + const { dateRange } = useDateRange(websiteId); + const { value, startDate, endDate } = dateRange; const { formatMessage, labels } = useMessages(); const { router, updateParams, - query: { compare }, + query: { compare, offset = 0 }, } = useNavigation(); const isAllTime = value === 'all'; const isCustomRange = value.startsWith('range'); @@ -40,13 +39,11 @@ export function WebsiteDateFilter({ const disableForward = value === 'all' || isAfter(endDate, new Date()); const handleChange = (date: string) => { - router.push(updateParams({ date })); - saveDateRange(date); + router.push(updateParams({ date, offset: undefined })); }; const handleIncrement = (increment: number) => { - router.push(updateParams({ offset: offset + increment })); - saveDateRange(getOffsetDateRange(dateRange, increment)); + router.push(updateParams({ offset: +offset + increment })); }; const handleSelect = (compare: any) => { @@ -79,6 +76,7 @@ export function WebsiteDateFilter({ endDate={endDate} onChange={handleChange} showAllTime={showAllTime} + renderDate={+offset !== 0} /> {!isAllTime && compare && ( diff --git a/src/components/messages.ts b/src/components/messages.ts index ab3779d3..a35d79ce 100644 --- a/src/components/messages.ts +++ b/src/components/messages.ts @@ -330,6 +330,7 @@ export const labels = defineMessages({ conversion: { id: 'label.conversion', defaultMessage: 'Conversion' }, firstClick: { id: 'label.first-click', defaultMessage: 'First click' }, lastClick: { id: 'label.last-click', defaultMessage: 'Last click' }, + online: { id: 'label.online', defaultMessage: 'Online' }, }); export const messages = defineMessages({ diff --git a/src/components/metrics/ActiveUsers.tsx b/src/components/metrics/ActiveUsers.tsx index 024f6856..0627020e 100644 --- a/src/components/metrics/ActiveUsers.tsx +++ b/src/components/metrics/ActiveUsers.tsx @@ -11,7 +11,7 @@ export function ActiveUsers({ value?: number; refetchInterval?: number; }) { - const { formatMessage, messages } = useMessages(); + const { formatMessage, labels } = useMessages(); const { data } = useActyiveUsersQuery(websiteId, { refetchInterval }); const count = useMemo(() => { @@ -28,8 +28,8 @@ export function ActiveUsers({ return ( - - {formatMessage(messages.numberOfUsers, { x: count })} + + {count} {formatMessage(labels.online)} ); diff --git a/src/index.ts b/src/index.ts index 6988166b..2a077a12 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,7 +27,7 @@ export * from '@/app/(main)/settings/teams/TeamsTable'; export * from '@/app/(main)/settings/teams/WebsiteTags'; export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteShareForm'; -export * from '@/app/(main)/settings/websites/[websiteId]/TrackingCode'; +export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteTrackingCode'; export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteData'; export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteDeleteForm'; export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteEditForm'; diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 19006492..4a79843c 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -16,7 +16,7 @@ export const FAVICON_URL = 'https://icons.duckduckgo.com/ip3/{{domain}}.ico'; export const DEFAULT_LOCALE = process.env.defaultLocale || 'en-US'; export const DEFAULT_THEME = 'light'; export const DEFAULT_ANIMATION_DURATION = 300; -export const DEFAULT_DATE_RANGE = '24hour'; +export const DEFAULT_DATE_RANGE_VALUE = '24hour'; export const DEFAULT_WEBSITE_LIMIT = 10; export const DEFAULT_RESET_DATE = '2000-01-01'; export const DEFAULT_PAGE_SIZE = 10; diff --git a/src/lib/date.ts b/src/lib/date.ts index 6c0d77fc..79d9952e 100644 --- a/src/lib/date.ts +++ b/src/lib/date.ts @@ -126,9 +126,9 @@ export function parseDateValue(value: string) { return { num: +num, unit }; } -export function parseDateRange(value: string | object, locale = 'en-US'): DateRange { +export function parseDateRange(value: string, locale = 'en-US'): DateRange { if (typeof value !== 'string') { - return value as DateRange; + return null; } if (value === 'all') { @@ -151,14 +151,13 @@ export function parseDateRange(value: string | object, locale = 'en-US'): DateRa endDate, value, ...parseDateValue(value), - offset: 0, unit, }; } const now = new Date(); const dateLocale = getDateLocale(locale); - const { num, unit } = parseDateValue(value); + const { num = 1, unit } = parseDateValue(value); switch (unit) { case 'hour': @@ -211,10 +210,14 @@ export function parseDateRange(value: string | object, locale = 'en-US'): DateRa } } -export function getOffsetDateRange(dateRange: DateRange, increment: number) { - const { startDate, endDate, unit, num, offset, value } = dateRange; +export function getOffsetDateRange(dateRange: DateRange, offset: number) { + if (offset === 0) { + return dateRange; + } - const change = num * increment; + const { startDate, endDate, unit, num, value } = dateRange; + + const change = num * offset; const { add } = DATE_FUNCTIONS[unit]; const { unit: originalUnit } = parseDateValue(value) || {}; @@ -224,28 +227,24 @@ export function getOffsetDateRange(dateRange: DateRange, increment: number) { ...dateRange, startDate: addDays(startDate, change), endDate: addDays(endDate, change), - offset: offset + increment, }; case 'week': return { ...dateRange, startDate: addWeeks(startDate, change), endDate: addWeeks(endDate, change), - offset: offset + increment, }; case 'month': return { ...dateRange, startDate: addMonths(startDate, change), endDate: addMonths(endDate, change), - offset: offset + increment, }; case 'year': return { ...dateRange, startDate: addYears(startDate, change), endDate: addYears(endDate, change), - offset: offset + increment, }; default: return { @@ -254,7 +253,6 @@ export function getOffsetDateRange(dateRange: DateRange, increment: number) { value, unit, num, - offset: offset + increment, }; } } diff --git a/src/queries/sql/getActiveVisitors.ts b/src/queries/sql/getActiveVisitors.ts index e0225f3a..9dc52a50 100644 --- a/src/queries/sql/getActiveVisitors.ts +++ b/src/queries/sql/getActiveVisitors.ts @@ -12,6 +12,7 @@ export async function getActiveVisitors(...args: [websiteId: string]) { async function relationalQuery(websiteId: string) { const { rawQuery } = prisma; + const startDate = subMinutes(new Date(), 5); const result = await rawQuery( ` @@ -20,7 +21,7 @@ async function relationalQuery(websiteId: string) { where website_id = {{websiteId::uuid}} and created_at >= {{startDate}} `, - { websiteId, startDate: subMinutes(new Date(), 5) }, + { websiteId, startDate }, ); return result[0] ?? null; @@ -28,6 +29,7 @@ async function relationalQuery(websiteId: string) { async function clickhouseQuery(websiteId: string): Promise<{ x: number }> { const { rawQuery } = clickhouse; + const startDate = subMinutes(new Date(), 5); const result = await rawQuery( ` @@ -37,7 +39,7 @@ async function clickhouseQuery(websiteId: string): Promise<{ x: number }> { where website_id = {websiteId:UUID} and created_at >= {startDate:DateTime64} `, - { websiteId, startDate: subMinutes(new Date(), 5) }, + { websiteId, startDate }, ); return result[0] ?? null; diff --git a/src/store/app.ts b/src/store/app.ts index 7713d495..56bd589e 100644 --- a/src/store/app.ts +++ b/src/store/app.ts @@ -1,7 +1,7 @@ import { create } from 'zustand'; import { DATE_RANGE_CONFIG, - DEFAULT_DATE_RANGE, + DEFAULT_DATE_RANGE_VALUE, DEFAULT_LOCALE, DEFAULT_THEME, LOCALE_CONFIG, @@ -23,7 +23,7 @@ const initialState = { locale: getItem(LOCALE_CONFIG) || DEFAULT_LOCALE, theme: getItem(THEME_CONFIG) || getDefaultTheme() || DEFAULT_THEME, timezone: getItem(TIMEZONE_CONFIG) || getTimezone(), - dateRange: getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE, + dateRangeValue: getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE_VALUE, shareToken: null, user: null, config: null, @@ -51,8 +51,8 @@ export function setConfig(config: object) { store.setState({ config }); } -export function setDateRange(dateRange: string | object) { - store.setState({ dateRange }); +export function setDateRangeValue(dateRangeValue: string) { + store.setState({ dateRangeValue }); } export const useApp = store; From 5171bdaf472dcd24268bd065adcb70561407d91a Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 25 Jun 2025 22:53:07 -0700 Subject: [PATCH 105/399] Use getRequestDateRange in all routes. --- .../sessions/SessionProperties.module.css | 25 ----------- .../sessions/SessionProperties.tsx | 21 ++++----- .../sessions/SessionsTable.module.css | 5 --- .../[websiteId]/sessions/SessionsTable.tsx | 3 +- .../sessions/SessionsWeekly.module.css | 43 ------------------- .../[websiteId]/sessions/SessionsWeekly.tsx | 16 +++++-- src/app/api/users/[userId]/usage/route.ts | 7 +-- .../[websiteId]/event-data/events/route.ts | 8 ++-- .../[websiteId]/event-data/fields/route.ts | 7 +-- .../event-data/properties/route.ts | 8 ++-- .../[websiteId]/event-data/stats/route.ts | 7 +-- .../[websiteId]/event-data/values/route.ts | 8 ++-- .../api/websites/[websiteId]/events/route.ts | 7 +-- .../[websiteId]/events/series/route.ts | 2 +- .../session-data/properties/route.ts | 8 ++-- .../[websiteId]/session-data/values/route.ts | 8 ++-- .../sessions/[sessionId]/activity/route.ts | 7 +-- .../websites/[websiteId]/sessions/route.ts | 7 +-- .../[websiteId]/sessions/weekly/route.ts | 8 ++-- src/lib/date.ts | 6 ++- src/lib/request.ts | 34 ++++++--------- 21 files changed, 72 insertions(+), 173 deletions(-) delete mode 100644 src/app/(main)/websites/[websiteId]/sessions/SessionProperties.module.css delete mode 100644 src/app/(main)/websites/[websiteId]/sessions/SessionsTable.module.css delete mode 100644 src/app/(main)/websites/[websiteId]/sessions/SessionsWeekly.module.css diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.module.css b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.module.css deleted file mode 100644 index 479d0994..00000000 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.module.css +++ /dev/null @@ -1,25 +0,0 @@ -.container { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(420px, 1fr)); - gap: 60px; - margin-bottom: 40px; -} - -.table { - align-self: flex-start; -} - -.link:hover { - cursor: pointer; - color: var(--primary-color); -} - -.title { - text-align: center; - font-weight: bold; - margin: 20px 0; -} - -.chart { - min-height: 620px; -} diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx index 7fbb63ea..03e5759a 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx @@ -1,4 +1,4 @@ -import { DataColumn, DataTable } from '@umami/react-zen'; +import { Grid, DataColumn, DataTable } from '@umami/react-zen'; import { useSessionDataPropertiesQuery, useSessionDataValuesQuery, @@ -8,12 +8,11 @@ import { LoadingPanel } from '@/components/common/LoadingPanel'; import { PieChart } from '@/components/charts/PieChart'; import { useState } from 'react'; import { CHART_COLORS } from '@/lib/constants'; -import styles from './SessionProperties.module.css'; export function SessionProperties({ websiteId }: { websiteId: string }) { const [propertyName, setPropertyName] = useState(''); const { formatMessage, labels } = useMessages(); - const { data, isLoading, isFetched, error } = useSessionDataPropertiesQuery(websiteId); + const { data, isLoading, isFetching, error } = useSessionDataPropertiesQuery(websiteId); const { data: values } = useSessionDataValuesQuery(websiteId, propertyName); const chartData = propertyName && values @@ -30,25 +29,23 @@ export function SessionProperties({ websiteId }: { websiteId: string }) { : null; return ( - -
- + + + {(row: any) => ( -
setPropertyName(row.propertyName)}> - {row.propertyName} -
+
setPropertyName(row.propertyName)}>{row.propertyName}
)}
{propertyName && ( -
-
{propertyName}
+
+
{propertyName}
)} -
+
); } diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.module.css b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.module.css deleted file mode 100644 index 140ad0bb..00000000 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.module.css +++ /dev/null @@ -1,5 +0,0 @@ -.link { - display: flex; - align-items: center; - gap: 20px; -} diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx index 1d7ed0c0..901d5473 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx @@ -2,7 +2,6 @@ import Link from 'next/link'; import { DataColumn, DataTable } from '@umami/react-zen'; import { useFormat, useMessages, useTimezone } from '@/components/hooks'; import { Avatar } from '@/components/common/Avatar'; -import styles from './SessionsTable.module.css'; import { TypeIcon } from '@/components/common/TypeIcon'; export function SessionsTable({ data = [] }: { data: any[]; showDomain?: boolean }) { @@ -14,7 +13,7 @@ export function SessionsTable({ data = [] }: { data: any[]; showDomain?: boolean {(row: any) => ( - + )} diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsWeekly.module.css b/src/app/(main)/websites/[websiteId]/sessions/SessionsWeekly.module.css deleted file mode 100644 index 58ab4c2d..00000000 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsWeekly.module.css +++ /dev/null @@ -1,43 +0,0 @@ -.week { - display: flex; - justify-content: space-between; - position: relative; -} - -.header { - text-align: center; - font-weight: 700; - margin-bottom: 10px; -} - -.day { - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: flex-start; - gap: 1px; - position: relative; -} - -.cell { - display: flex; - background-color: var(--base-color-2); - width: 20px; - height: 20px; - margin: auto; - border-radius: 100%; - align-items: flex-start; -} - -.hour { - font-weight: 700; - color: var(--font-color); - height: 20px; -} - -.block { - background-color: var(--primary-color); - width: 20px; - height: 20px; - border-radius: 100%; -} diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsWeekly.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsWeekly.tsx index 78c5ccdc..d4a45ad3 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsWeekly.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsWeekly.tsx @@ -14,7 +14,7 @@ export function SessionsWeekly({ websiteId }: { websiteId: string }) { .fill(weekStartsOn) .map((d, i) => (d + i) % 7); - const [, max] = data + const [, max = 1] = data ? data.reduce((arr: number[], hours: number[], index: number) => { const min = Math.min(...hours); const max = Math.max(...hours); @@ -69,17 +69,25 @@ export function SessionsWeekly({ websiteId }: { websiteId: string }) { key={index} gap="1" > - + {format(getDayOfWeekAsDate(index), 'EEE', { locale: dateLocale })} {day?.map((count: number, j) => { - const pct = count / max; + const pct = max ? count / max : 0; return ( - + }) { const schema = z.object({ @@ -22,10 +22,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ user } const { userId } = await params; - const { startAt, endAt } = query; - - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); + const { startDate, endDate } = await getRequestDateRange(query); const websites = await getAllUserWebsitesIncludingTeamOwner(userId); diff --git a/src/app/api/websites/[websiteId]/event-data/events/route.ts b/src/app/api/websites/[websiteId]/event-data/events/route.ts index aec7b471..f4b950c4 100644 --- a/src/app/api/websites/[websiteId]/event-data/events/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/events/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest } from '@/lib/request'; +import { getRequestDateRange, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getEventDataEvents } from '@/queries/sql/events/getEventDataEvents'; @@ -20,15 +20,13 @@ export async function GET( } const { websiteId } = await params; - const { startAt, endAt, event } = query; + const { event } = query; + const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getEventDataEvents(websiteId, { startDate, endDate, diff --git a/src/app/api/websites/[websiteId]/event-data/fields/route.ts b/src/app/api/websites/[websiteId]/event-data/fields/route.ts index 60101e45..fa31ca69 100644 --- a/src/app/api/websites/[websiteId]/event-data/fields/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/fields/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest } from '@/lib/request'; +import { getRequestDateRange, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getEventDataFields } from '@/queries'; @@ -20,15 +20,12 @@ export async function GET( } const { websiteId } = await params; - const { startAt, endAt } = query; + const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getEventDataFields(websiteId, { startDate, endDate, diff --git a/src/app/api/websites/[websiteId]/event-data/properties/route.ts b/src/app/api/websites/[websiteId]/event-data/properties/route.ts index fe085f74..2fa7a335 100644 --- a/src/app/api/websites/[websiteId]/event-data/properties/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/properties/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest } from '@/lib/request'; +import { getRequestDateRange, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getEventDataProperties } from '@/queries'; @@ -21,15 +21,13 @@ export async function GET( } const { websiteId } = await params; - const { startAt, endAt, propertyName } = query; + const { propertyName } = query; + const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getEventDataProperties(websiteId, { startDate, endDate, propertyName }); return json(data); diff --git a/src/app/api/websites/[websiteId]/event-data/stats/route.ts b/src/app/api/websites/[websiteId]/event-data/stats/route.ts index 6928aa1e..ccc45b75 100644 --- a/src/app/api/websites/[websiteId]/event-data/stats/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/stats/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest } from '@/lib/request'; +import { getRequestDateRange, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getEventDataStats } from '@/queries'; @@ -21,15 +21,12 @@ export async function GET( } const { websiteId } = await params; - const { startAt, endAt } = query; + const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getEventDataStats(websiteId, { startDate, endDate }); return json(data); diff --git a/src/app/api/websites/[websiteId]/event-data/values/route.ts b/src/app/api/websites/[websiteId]/event-data/values/route.ts index 2a912439..c25dc014 100644 --- a/src/app/api/websites/[websiteId]/event-data/values/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/values/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest } from '@/lib/request'; +import { getRequestDateRange, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getEventDataValues } from '@/queries'; @@ -22,15 +22,13 @@ export async function GET( } const { websiteId } = await params; - const { startAt, endAt, eventName, propertyName } = query; + const { eventName, propertyName } = query; + const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getEventDataValues(websiteId, { startDate, endDate, diff --git a/src/app/api/websites/[websiteId]/events/route.ts b/src/app/api/websites/[websiteId]/events/route.ts index 66eaba2c..fb3db328 100644 --- a/src/app/api/websites/[websiteId]/events/route.ts +++ b/src/app/api/websites/[websiteId]/events/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest } from '@/lib/request'; +import { getRequestDateRange, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { pagingParams } from '@/lib/schema'; @@ -22,15 +22,12 @@ export async function GET( } const { websiteId } = await params; - const { startAt, endAt } = query; + const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getWebsiteEvents(websiteId, { startDate, endDate }, query); return json(data); diff --git a/src/app/api/websites/[websiteId]/events/series/route.ts b/src/app/api/websites/[websiteId]/events/series/route.ts index da4b0d4f..43bd23a7 100644 --- a/src/app/api/websites/[websiteId]/events/series/route.ts +++ b/src/app/api/websites/[websiteId]/events/series/route.ts @@ -12,7 +12,7 @@ export async function GET( const schema = z.object({ startAt: z.coerce.number().int(), endAt: z.coerce.number().int(), - unit: unitParam, + unit: unitParam.optional(), timezone: timezoneParam, ...filterParams, }); diff --git a/src/app/api/websites/[websiteId]/session-data/properties/route.ts b/src/app/api/websites/[websiteId]/session-data/properties/route.ts index a6d9e2a4..901dcdf5 100644 --- a/src/app/api/websites/[websiteId]/session-data/properties/route.ts +++ b/src/app/api/websites/[websiteId]/session-data/properties/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest } from '@/lib/request'; +import { getRequestDateRange, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getSessionDataProperties } from '@/queries'; @@ -20,16 +20,14 @@ export async function GET( return error(); } - const { startAt, endAt, propertyName } = query; const { websiteId } = await params; + const { propertyName } = query; + const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getSessionDataProperties(websiteId, { startDate, endDate, propertyName }); return json(data); diff --git a/src/app/api/websites/[websiteId]/session-data/values/route.ts b/src/app/api/websites/[websiteId]/session-data/values/route.ts index d950da34..0730a70b 100644 --- a/src/app/api/websites/[websiteId]/session-data/values/route.ts +++ b/src/app/api/websites/[websiteId]/session-data/values/route.ts @@ -1,5 +1,5 @@ import { canViewWebsite } from '@/lib/auth'; -import { parseRequest } from '@/lib/request'; +import { getRequestDateRange, parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; import { getSessionDataValues } from '@/queries'; import { z } from 'zod'; @@ -20,16 +20,14 @@ export async function GET( return error(); } - const { startAt, endAt, propertyName } = query; + const { propertyName } = query; const { websiteId } = await params; + const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getSessionDataValues(websiteId, { startDate, endDate, diff --git a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts index aac40c38..831d0064 100644 --- a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest } from '@/lib/request'; +import { parseRequest, getRequestDateRange } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getSessionActivity } from '@/queries'; @@ -20,15 +20,12 @@ export async function GET( } const { websiteId, sessionId } = await params; - const { startAt, endAt } = query; + const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getSessionActivity(websiteId, sessionId, startDate, endDate); return json(data); diff --git a/src/app/api/websites/[websiteId]/sessions/route.ts b/src/app/api/websites/[websiteId]/sessions/route.ts index 5a14f00f..6f8a671e 100644 --- a/src/app/api/websites/[websiteId]/sessions/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest } from '@/lib/request'; +import { getRequestDateRange, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { pagingParams } from '@/lib/schema'; @@ -21,16 +21,13 @@ export async function GET( return error(); } + const { startDate, endDate } = await getRequestDateRange(query); const { websiteId } = await params; - const { startAt, endAt } = query; if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getWebsiteSessions(websiteId, { startDate, endDate }, query); return json(data); diff --git a/src/app/api/websites/[websiteId]/sessions/weekly/route.ts b/src/app/api/websites/[websiteId]/sessions/weekly/route.ts index 20be378d..a8216123 100644 --- a/src/app/api/websites/[websiteId]/sessions/weekly/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/weekly/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest } from '@/lib/request'; +import { getRequestDateRange, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { pagingParams, timezoneParam } from '@/lib/schema'; @@ -23,15 +23,13 @@ export async function GET( } const { websiteId } = await params; - const { startAt, endAt, timezone } = query; + const { timezone } = query; + const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const startDate = new Date(+startAt); - const endDate = new Date(+endAt); - const data = await getWebsiteSessionsWeekly(websiteId, { startDate, endDate, timezone }); return json(data); diff --git a/src/lib/date.ts b/src/lib/date.ts index 79d9952e..f740791a 100644 --- a/src/lib/date.ts +++ b/src/lib/date.ts @@ -310,7 +310,11 @@ export function getDayOfWeekAsDate(dayOfWeek: number) { return currentDate; } -export function formatDate(date: string | number | Date, dateFormat: string, locale = 'en-US') { +export function formatDate( + date: string | number | Date, + dateFormat: string = 'PPpp', + locale = 'en-US', +) { return format(typeof date === 'string' ? new Date(date) : date, dateFormat, { locale: getDateLocale(locale), }); diff --git a/src/lib/request.ts b/src/lib/request.ts index 2481ae9f..0f07fa87 100644 --- a/src/lib/request.ts +++ b/src/lib/request.ts @@ -1,9 +1,8 @@ import { z } from 'zod/v4'; import { FILTER_COLUMNS } from '@/lib/constants'; import { badRequest, unauthorized } from '@/lib/response'; -import { getAllowedUnits, getMinimumUnit } from '@/lib/date'; +import { getAllowedUnits, getCompareDate, getMinimumUnit } from '@/lib/date'; import { checkAuth } from '@/lib/auth'; -import { getWebsiteDateRange } from '@/queries'; export async function parseRequest( request: Request, @@ -48,31 +47,26 @@ export async function getJsonBody(request: Request) { } } -export async function getRequestDateRange(query: Record) { - const { websiteId, startAt, endAt, unit } = query; - - // All-time - if (+startAt === 0 && +endAt === 1) { - const result = await getWebsiteDateRange(websiteId as string); - const { min, max } = result[0]; - const startDate = new Date(min); - const endDate = new Date(max); - - return { - startDate, - endDate, - unit: getMinimumUnit(startDate, endDate), - }; - } +export async function getRequestDateRange(query: Record) { + const { startAt, endAt, unit, compare } = query; const startDate = new Date(+startAt); const endDate = new Date(+endAt); - const minUnit = getMinimumUnit(startDate, endDate); + + const { startDate: compareStartDate, endDate: compareEndDate } = getCompareDate( + compare, + startDate, + endDate, + ); return { startDate, endDate, - unit: (getAllowedUnits(startDate, endDate).includes(unit as string) ? unit : minUnit) as string, + compareStartDate, + compareEndDate, + unit: getAllowedUnits(startDate, endDate).includes(unit) + ? unit + : getMinimumUnit(startDate, endDate), }; } From 0692134ea55220b432972799fc35edbc49bacd87 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 26 Jun 2025 13:59:46 -0700 Subject: [PATCH 106/399] AI generated translations. --- public/intl/messages/am-ET.json | 2 +- public/intl/messages/ar-SA.json | 124 +++++----- public/intl/messages/be-BY.json | 122 +++++----- public/intl/messages/bg-BG.json | 156 ++++++------- public/intl/messages/bn-BD.json | 278 +++++++++++----------- public/intl/messages/bs-BA.json | 186 +++++++-------- public/intl/messages/ca-ES.json | 112 ++++----- public/intl/messages/cs-CZ.json | 256 ++++++++++----------- public/intl/messages/da-DK.json | 350 ++++++++++++++-------------- public/intl/messages/de-CH.json | 112 ++++----- public/intl/messages/de-DE.json | 104 ++++----- public/intl/messages/el-GR.json | 2 +- public/intl/messages/en-GB.json | 2 +- public/intl/messages/en-US.json | 2 +- public/intl/messages/es-ES.json | 148 ++++++------ public/intl/messages/fa-IR.json | 118 +++++----- public/intl/messages/fi-FI.json | 318 +++++++++++++------------- public/intl/messages/fo-FO.json | 394 ++++++++++++++++---------------- public/intl/messages/fr-FR.json | 76 +++--- public/intl/messages/ga-ES.json | 140 ++++++------ public/intl/messages/he-IL.json | 328 +++++++++++++------------- public/intl/messages/hi-IN.json | 378 +++++++++++++++--------------- public/intl/messages/hr-HR.json | 326 +++++++++++++------------- public/intl/messages/hu-HU.json | 322 +++++++++++++------------- public/intl/messages/id-ID.json | 136 +++++------ public/intl/messages/it-IT.json | 292 +++++++++++------------ public/intl/messages/ja-JP.json | 116 +++++----- public/intl/messages/km-KH.json | 150 ++++++------ public/intl/messages/ko-KR.json | 116 +++++----- public/intl/messages/lt-LT.json | 242 ++++++++++---------- public/intl/messages/mn-MN.json | 116 +++++----- public/intl/messages/ms-MY.json | 2 +- public/intl/messages/my-MM.json | 2 +- public/intl/messages/nb-NO.json | 122 +++++----- public/intl/messages/nl-NL.json | 164 ++++++------- public/intl/messages/pl-PL.json | 130 +++++------ public/intl/messages/pt-BR.json | 148 ++++++------ public/intl/messages/pt-PT.json | 294 ++++++++++++------------ public/intl/messages/ro-RO.json | 110 ++++----- public/intl/messages/ru-RU.json | 110 ++++----- public/intl/messages/si-LK.json | 2 +- public/intl/messages/sk-SK.json | 294 ++++++++++++------------ public/intl/messages/sl-SI.json | 178 +++++++-------- public/intl/messages/sv-SE.json | 176 +++++++------- public/intl/messages/ta-IN.json | 2 +- public/intl/messages/th-TH.json | 2 +- public/intl/messages/tr-TR.json | 154 ++++++------- public/intl/messages/uk-UA.json | 162 ++++++------- public/intl/messages/ur-PK.json | 2 +- public/intl/messages/vi-VN.json | 318 +++++++++++++------------- public/intl/messages/zh-CN.json | 118 +++++----- public/intl/messages/zh-TW.json | 28 +-- src/lang/am-ET.json | 337 --------------------------- src/lang/ar-SA.json | 120 +++++----- src/lang/be-BY.json | 120 +++++----- src/lang/bg-BG.json | 154 ++++++------- src/lang/bn-BD.json | 266 ++++++++++----------- src/lang/bs-BA.json | 182 +++++++-------- src/lang/ca-ES.json | 110 ++++----- src/lang/cs-CZ.json | 250 ++++++++++---------- src/lang/da-DK.json | 342 +++++++++++++-------------- src/lang/de-CH.json | 110 ++++----- src/lang/de-DE.json | 102 ++++----- src/lang/el-GR.json | 2 +- src/lang/en-GB.json | 2 +- src/lang/en-US.json | 2 +- src/lang/es-ES.json | 144 ++++++------ src/lang/fa-IR.json | 116 +++++----- src/lang/fi-FI.json | 310 ++++++++++++------------- src/lang/fo-FO.json | 388 +++++++++++++++---------------- src/lang/fr-FR.json | 74 +++--- src/lang/ga-ES.json | 138 +++++------ src/lang/he-IL.json | 318 +++++++++++++------------- src/lang/hi-IN.json | 372 +++++++++++++++--------------- src/lang/hr-HR.json | 318 +++++++++++++------------- src/lang/hu-HU.json | 314 ++++++++++++------------- src/lang/id-ID.json | 132 +++++------ src/lang/it-IT.json | 288 +++++++++++------------ src/lang/ja-JP.json | 114 ++++----- src/lang/km-KH.json | 135 +++++------ src/lang/ko-KR.json | 114 ++++----- src/lang/lt-LT.json | 238 +++++++++---------- src/lang/mn-MN.json | 114 ++++----- src/lang/ms-MY.json | 2 +- src/lang/my-MM.json | 2 +- src/lang/nb-NO.json | 120 +++++----- src/lang/nl-NL.json | 160 ++++++------- src/lang/pl-PL.json | 128 +++++------ src/lang/pt-BR.json | 146 ++++++------ src/lang/pt-PT.json | 290 +++++++++++------------ src/lang/ro-RO.json | 108 ++++----- src/lang/ru-RU.json | 108 ++++----- src/lang/si-LK.json | 2 +- src/lang/sk-SK.json | 290 +++++++++++------------ src/lang/sl-SI.json | 174 +++++++------- src/lang/sv-SE.json | 172 +++++++------- src/lang/ta-IN.json | 2 +- src/lang/th-TH.json | 2 +- src/lang/tr-TR.json | 152 ++++++------ src/lang/uk-UA.json | 160 ++++++------- src/lang/ur-PK.json | 2 +- src/lang/vi-VN.json | 312 ++++++++++++------------- src/lang/zh-CN.json | 116 +++++----- src/lang/zh-TW.json | 26 +-- 104 files changed, 7960 insertions(+), 8282 deletions(-) delete mode 100644 src/lang/am-ET.json diff --git a/public/intl/messages/am-ET.json b/public/intl/messages/am-ET.json index d971adf3..1fe020ea 100644 --- a/public/intl/messages/am-ET.json +++ b/public/intl/messages/am-ET.json @@ -251,7 +251,7 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, "value": "Conversion rate" diff --git a/public/intl/messages/ar-SA.json b/public/intl/messages/ar-SA.json index c138f8ce..57635e0f 100644 --- a/public/intl/messages/ar-SA.json +++ b/public/intl/messages/ar-SA.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "أضف لوحة" } ], "label.add-description": [ @@ -92,7 +92,7 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "تطبيق" } ], "label.attribution": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "لوحات" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "حملات" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "قنوات" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "مجموعة" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "قارن التواريخ" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "المحتوى" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "تحويل" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "معدل التحويل" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "خطوة التحويل" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "العملة" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "مباشر" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "معرّف مميز" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "لا يتضمن" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "غير موجود" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "اسم الحدث" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "موجود" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "توسيع" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "النقرة الأولى" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "قمعات" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "مجمع" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "اسم المضيف" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "يتضمن" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "رؤية معمقة" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "غير صحيح" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "صحيح" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "رحلات المستخدم" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "النقرة الأخيرة" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "روابط" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "وسيط" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "نموذج" } ], "label.more": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "غير معرّف" + "value": "لا شيء" } ], "label.number-of-records": [ @@ -993,7 +993,7 @@ "value": [ { "type": 0, - "value": "record" + "value": "سجل" } ] }, @@ -1001,7 +1001,7 @@ "value": [ { "type": 0, - "value": "records" + "value": "سجلات" } ] } @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "بحث عضوي" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "تسوق عضوي" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "اجتماعي عضوي" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "فيديو عضوي" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "أخرى" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "صفحة" } ], "label.page-of": [ @@ -1104,37 +1104,37 @@ "label.pages": [ { "type": 0, - "value": "الصفحات" + "value": "صفحات" } ], "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "إعلانات مدفوعة" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "بحث مدفوع" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "تسوق مدفوع" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "اجتماعي مدفوع" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "فيديو مدفوع" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "المسار" + "value": "مسار" } ], "label.paths": [ { "type": 0, - "value": "المسارات" + "value": "مسارات" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "بكسلات" } ], "label.powered-by": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "الخصائص" + "value": "خصائص" } ], "label.property": [ { "type": 0, - "value": "الخاصية" + "value": "خاصية" } ], "label.queries": [ @@ -1222,7 +1222,7 @@ "label.query-parameters": [ { "type": 0, - "value": "متغيرات الرابط" + "value": "معاملات الاستعلام" } ], "label.realtime": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "إحالة" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "متبقي" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "اختر تصفية" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "بيانات الجلسة" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "مشاركة" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "مصادر" } ], "label.start-step": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "إعدادات الفريق" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "مصطلحات" } ], "label.theme": [ diff --git a/public/intl/messages/be-BY.json b/public/intl/messages/be-BY.json index f9633cdc..366993a5 100644 --- a/public/intl/messages/be-BY.json +++ b/public/intl/messages/be-BY.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Дадаць дошку" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Партнёр" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Ужыць" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Атрыбуцыя" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Глядзіце, як карыстальнікі ўзаемадзейнічаюць з вашым маркетынгам і што прыводзіць да канверсій." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Дошкі" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Кампаніі" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Каналы" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Кагорта" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Параўнаць даты" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Змест" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Канверсія" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Канверсійная стаўка" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Крок канверсіі" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Валюта" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Прама" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Унікальны ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Не ўключае" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Не існуе" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Назва падзеі" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Існуе" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Разгарнуць" } ], "label.false": [ @@ -614,13 +614,13 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Першы клік" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Першы раз убачана" } ], "label.funnel": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Варонкі" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Групаваны" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Імя хаста" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Уключае" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Інсайт" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Ложна" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Праўда" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Маршруты" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Апошні клік" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Спасылкі" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Сярэдні" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Мадэль" } ], "label.more": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Арганічны пошук" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Арганічныя пакупкі" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Арганічныя сацыяльныя сеткі" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Арганічнае відэа" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Іншае" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Старонка" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Платная рэклама" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Платаны пошук" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Платныя пакупкі" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Платныя сацыяльныя сеткі" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Платнае відэа" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Шлях" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Шляхи" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Пікселі" } ], "label.powered-by": [ @@ -1198,7 +1198,7 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Уласцівасці" } ], "label.property": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Рэферал" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Засталося" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Выбраць фільтр" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Сесія" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Дадзеныя сесіі" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Падзяліцца" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Крыніцы" } ], "label.start-step": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Налады каманды" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Тэрміны" } ], "label.theme": [ diff --git a/public/intl/messages/bg-BG.json b/public/intl/messages/bg-BG.json index a1bfb350..28a3ae76 100644 --- a/public/intl/messages/bg-BG.json +++ b/public/intl/messages/bg-BG.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Добави дъска" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Партньор" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Приложи" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Атрибуция" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Вижте как потребителите взаимодействат с вашия маркетинг и какво води до конверсии." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Дъски" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Кампании" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Канали" } ], "label.cities": [ @@ -200,19 +200,19 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Кохорта" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Сравни" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Сравни дати" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Съдържание" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Конверсия" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Процент на конверсия" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Стъпка на конверсия" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Брой" } ], "label.countries": [ @@ -320,13 +320,13 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Валута" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Текущ" } ], "label.current-password": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Директно" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Уникален ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Не включва" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Не съществува" } ], "label.domain": [ @@ -506,7 +506,7 @@ "label.email": [ { "type": 0, - "value": "Email" + "value": "Имейл" } ], "label.enable-share-url": [ @@ -518,13 +518,13 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Крайна стъпка" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "URL на вход" } ], "label.event": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Име на събитие" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Съществува" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Разшири" } ], "label.false": [ @@ -614,13 +614,13 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Първо кликване" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Първо видяно" } ], "label.funnel": [ @@ -638,25 +638,25 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Фунии" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Цел" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Цели" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Следете целите си за прегледи на страници и събития." } ], "label.greater-than": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Групирано" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Име на хост" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Включва" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Прозрение" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Грешно" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Вярно" } ], "label.join": [ @@ -758,19 +758,19 @@ "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Пътешествие" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Разберете как потребителите навигират във вашия уебсайт." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Пътешествия" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Последно кликване" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Връзки" } ], "label.login": [ @@ -896,7 +896,7 @@ "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Мениджър" } ], "label.max": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Среден" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Модел" } ], "label.more": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Органично търсене" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Органично пазаруване" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Органични социални мрежи" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Органично видео" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Друго" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Страница" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Платени реклами" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Платено търсене" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Платено пазаруване" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Платени социални мрежи" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Платено видео" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Път" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Пътища" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Пиксели" } ], "label.powered-by": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Свойства" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Свойство" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Реферал" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Оставащи" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Избери филтър" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Сесия" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Данни за сесия" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Сподели" } ], "label.share-url": [ @@ -1450,13 +1450,13 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Източници" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "Начална стъпка" } ], "label.steps": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Етикет" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Етикети" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Мениджър на екип" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Настройки на екипа" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Термини" } ], "label.theme": [ diff --git a/public/intl/messages/bn-BD.json b/public/intl/messages/bn-BD.json index 4707245b..0f1bbdda 100644 --- a/public/intl/messages/bn-BD.json +++ b/public/intl/messages/bn-BD.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "বোর্ড যুক্ত করুন" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "সহযোগী" } ], "label.after": [ @@ -86,31 +86,31 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "বিশ্লেষণ" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "প্রয়োগ করুন" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "অ্যাট্রিবিউশন" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "দেখুন ব্যবহারকারীরা কীভাবে আপনার মার্কেটিংয়ের সাথে যুক্ত হয় এবং কীভাবে রূপান্তর ঘটে।" } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "গড়" } ], "label.back": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "বোর্ডসমূহ" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "প্রচারণা" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "চ্যানেলসমূহ" } ], "label.cities": [ @@ -200,19 +200,19 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "কোহর্ট" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "তুলনা করুন" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "তারিখ তুলনা করুন" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "বিষয়বস্তু" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "রূপান্তর" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "রূপান্তর হার" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "রূপান্তর ধাপ" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "গণনা" } ], "label.countries": [ @@ -314,19 +314,19 @@ "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "তৈরি করেছেন" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "মুদ্রা" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "বর্তমান" } ], "label.current-password": [ @@ -350,13 +350,13 @@ "label.data": [ { "type": 0, - "value": "Data" + "value": "ডেটা" } ], "label.date": [ { "type": 0, - "value": "Date" + "value": "তারিখ" } ], "label.date-range": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "দিন" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "রিপোর্ট মুছুন" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "দল মুছুন" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "ব্যবহারকারী মুছুন" } ], "label.delete-website": [ @@ -410,7 +410,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "বর্ণনা" } ], "label.desktop": [ @@ -422,13 +422,13 @@ "label.details": [ { "type": 0, - "value": "Details" + "value": "বিস্তারিত" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "ডিভাইস" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "সরাসরি" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "স্বতন্ত্র আইডি" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "ধারণ করে না" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "অন্তর্ভুক্ত নয়" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "অস্তিত্ব নেই" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "ছেড়ে যাওয়া" } ], "label.edit": [ @@ -494,13 +494,13 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "ড্যাশবোর্ড সম্পাদনা করুন" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "সদস্য সম্পাদনা করুন" } ], "label.email": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "শেষ ধাপ" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "প্রবেশ URL" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "ইভেন্ট" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "ইভেন্ট ডেটা" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "ইভেন্টের নাম" } ], "label.events": [ @@ -554,43 +554,43 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "অস্তিত্ব আছে" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "প্রস্থান URL" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "বিস্তৃত করুন" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "মিথ্যা" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "ক্ষেত্র" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "ক্ষেত্রসমূহ" } ], "label.filter": [ { "type": 0, - "value": "Filter" + "value": "ফিল্টার" } ], "label.filter-combined": [ @@ -608,91 +608,91 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "ফিল্টারসমূহ" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "প্রথম ক্লিক" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "প্রথম দেখা" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "ফানেল" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "ব্যবহারকারীদের রূপান্তর ও ছেড়ে যাওয়ার হার বুঝুন।" } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "ফানেলসমূহ" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "লক্ষ্য" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "লক্ষ্যসমূহ" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "পৃষ্ঠাদর্শন ও ইভেন্টের লক্ষ্য ট্র্যাক করুন।" } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "এর চেয়ে বেশি" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "এর চেয়ে বেশি বা সমান" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "গ্রুপ করা" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "হোস্টনেম" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "অন্তর্ভুক্ত" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "অন্তর্দৃষ্টি" } ], "label.insights": [ @@ -710,67 +710,67 @@ "label.is": [ { "type": 0, - "value": "Is" + "value": "হয়" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "মিথ্যা" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "নয়" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "নির্ধারিত নয়" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "নির্ধারিত" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "সত্য" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "যোগ দিন" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "দলে যোগ দিন" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "যাত্রা" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "ব্যবহারকারীরা কীভাবে আপনার ওয়েবসাইটে নেভিগেট করে তা বুঝুন।" } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "যাত্রাসমূহ" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "শেষ ক্লিক" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "শেষ " }, { "type": 1, @@ -836,43 +836,43 @@ }, { "type": 0, - "value": " months" + "value": " মাস" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "শেষ দেখা" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "ত্যাগ করুন" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "দল ত্যাগ করুন" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "এর চেয়ে কম" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "এর চেয়ে কম বা সমান" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "লিঙ্কসমূহ" } ], "label.login": [ @@ -890,43 +890,43 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "পরিচালনা করুন" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "পরিচালক" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "সর্বাধিক" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "মাঝারি" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "সদস্য" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "সদস্যগণ" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "সর্বনিম্ন" } ], "label.mobile": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "মডেল" } ], "label.more": [ @@ -950,13 +950,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "আমার অ্যাকাউন্ট" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "আমার ওয়েবসাইটসমূহ" } ], "label.name": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "অর্গানিক সার্চ" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "অর্গানিক শপিং" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "অর্গানিক সোশ্যাল" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "অর্গানিক ভিডিও" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "অন্যান্য" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "পৃষ্ঠা" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "পেইড বিজ্ঞাপন" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "পেইড সার্চ" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "পেইড শপিং" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "পেইড সোশ্যাল" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "পেইড ভিডিও" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "পথ" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "পথসমূহ" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "পিক্সেল" } ], "label.powered-by": [ @@ -1174,19 +1174,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "পূর্ববর্তী" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "পূর্ববর্তী সময়কাল" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "গত বছর" } ], "label.profile": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "বৈশিষ্ট্যসমূহ" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "বৈশিষ্ট্য" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "রেফারেল" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "বাকি আছে" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "আয়" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "সময়ের সাথে সাথে আপনার আয় দেখুন।" } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "ফিল্টার নির্বাচন করুন" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "সেশন" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "সেশন ডেটা" } ], "label.sessions": [ @@ -1426,13 +1426,21 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "শেয়ার করুন" } ], "label.share-url": [ { "type": 0, - "value": "ইউআরএল শেয়ার করুন" + "value": "এটি " + }, + { + "type": 1, + "value": "target" + }, + { + "type": 0, + "value": " এর জন্য প্রকাশ্যে শেয়ার করার ইউআরএল।" } ], "label.single-day": [ @@ -1450,7 +1458,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "উৎসসমূহ" } ], "label.start-step": [ @@ -1480,55 +1488,55 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "ট্যাগ" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "ট্যাগসমূহ" } ], "label.team": [ { "type": 0, - "value": "Team" + "value": "দল" } ], "label.team-id": [ { "type": 0, - "value": "Team ID" + "value": "দল আইডি" } ], "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "দল ব্যবস্থাপক" } ], "label.team-member": [ { "type": 0, - "value": "Team member" + "value": "দলের সদস্য" } ], "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "দলের নাম" } ], "label.team-owner": [ { "type": 0, - "value": "Team owner" + "value": "দলের মালিক" } ], "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "দলের সেটিংস" } ], "label.team-view-only": [ @@ -1552,7 +1560,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "শর্তাবলী" } ], "label.theme": [ diff --git a/public/intl/messages/bs-BA.json b/public/intl/messages/bs-BA.json index 6b5fa0c7..b0a4b87e 100644 --- a/public/intl/messages/bs-BA.json +++ b/public/intl/messages/bs-BA.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Dodaj ploču" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partner" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Primijeni" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atribucija" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Pogledajte kako korisnici komuniciraju s vašim marketingom i šta dovodi do konverzija." } ], "label.average": [ @@ -128,13 +128,13 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Ploče" } ], "label.bounce-rate": [ { "type": 0, - "value": "Bounce rate" + "value": "Stopa napuštanja" } ], "label.breakdown": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampanje" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanali" } ], "label.cities": [ @@ -200,19 +200,19 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohorta" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Uporedi" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Uporedi datume" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Sadržaj" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konverzija" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Stopa konverzije" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Korak konverzije" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Broj" } ], "label.countries": [ @@ -320,13 +320,13 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Valuta" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Trenutno" } ], "label.current-password": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Direktno" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Jedinstveni ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Ne uključuje" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Ne postoji" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Odlazak" } ], "label.edit": [ @@ -506,7 +506,7 @@ "label.email": [ { "type": 0, - "value": "Email" + "value": "E-mail" } ], "label.enable-share-url": [ @@ -518,13 +518,13 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Završni korak" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "URL ulaza" } ], "label.event": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Naziv događaja" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Postoji" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Proširi" } ], "label.false": [ @@ -614,13 +614,13 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Prvi klik" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Prvi put viđeno" } ], "label.funnel": [ @@ -638,25 +638,25 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Lijevci" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Cilj" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Ciljevi" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Pratite svoje ciljeve za prikaze stranica i događaje." } ], "label.greater-than": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Grupisano" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Naziv hosta" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Uključuje" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Uvid" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Nije tačno" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Tačno" } ], "label.join": [ @@ -758,19 +758,19 @@ "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Putovanje" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Saznajte kako korisnici navigiraju vašom web stranicom." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Putovanja" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Zadnji klik" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Linkovi" } ], "label.login": [ @@ -896,7 +896,7 @@ "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Menadžer" } ], "label.max": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Srednje" } ], "label.member": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Nijedno" } ], "label.number-of-records": [ @@ -993,7 +993,7 @@ "value": [ { "type": 0, - "value": "record" + "value": "zapis" } ] }, @@ -1001,7 +1001,7 @@ "value": [ { "type": 0, - "value": "records" + "value": "zapisa" } ] } @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organska pretraga" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organska kupovina" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organske društvene mreže" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organski video" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Drugo" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Stranica" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Plaćeni oglasi" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Plaćena pretraga" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Plaćena kupovina" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Plaćene društvene mreže" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Plaćeni video" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Putanja" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Putanje" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pikseli" } ], "label.powered-by": [ @@ -1198,31 +1198,31 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Svojstva" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Svojstvo" } ], "label.queries": [ { "type": 0, - "value": "Queryji" + "value": "Upiti" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "Upit" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parametri" + "value": "Parametri upita" } ], "label.realtime": [ @@ -1234,25 +1234,25 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Preporuka" } ], "label.referrer": [ { "type": 0, - "value": "Referrer" + "value": "Preporučilac" } ], "label.referrers": [ { "type": 0, - "value": "Referrers" + "value": "Preporučioci" } ], "label.refresh": [ { "type": 0, - "value": "Refresh" + "value": "Osvježi" } ], "label.regenerate": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Preostalo" } ], "label.remove": [ @@ -1300,7 +1300,7 @@ "label.required": [ { "type": 0, - "value": "Required" + "value": "Obavezno" } ], "label.reset": [ @@ -1318,7 +1318,7 @@ "label.retention": [ { "type": 0, - "value": "Retention" + "value": "Zadržavanje" } ], "label.retention-description": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Prihod" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Pogledajte svoje prihode tokom vremena." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Odaberi filter" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Sesija" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Podaci o sesiji" } ], "label.sessions": [ @@ -1426,13 +1426,13 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Podijeli" } ], "label.share-url": [ { "type": 0, - "value": "Share URL" + "value": "URL za dijeljenje" } ], "label.single-day": [ @@ -1450,13 +1450,13 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Izvori" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "Početni korak" } ], "label.steps": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Oznaka" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Oznake" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Menadžer tima" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Postavke tima" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Pojmovi" } ], "label.theme": [ diff --git a/public/intl/messages/ca-ES.json b/public/intl/messages/ca-ES.json index 57764fd3..7c75c0be 100644 --- a/public/intl/messages/ca-ES.json +++ b/public/intl/messages/ca-ES.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Afegir tauler" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Afiliat" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Aplica" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atribució" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Vegeu com els usuaris interactuen amb el vostre màrqueting i què impulsa les conversions." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Taulers" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Campanyes" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Canals" } ], "label.cities": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Comparar dates" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Contingut" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Conversió" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Taxa de conversió" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Pas de conversió" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Moneda" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Directe" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "ID distintiu" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "No inclou" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "No existeix" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Nom de l'esdeveniment" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existeix" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Expandeix" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Primer clic" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Embuts" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Agrupat" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Nom de host" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Inclou" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Visió" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "És fals" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "És cert" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Trajectes" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Últim clic" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Enllaços" } ], "label.login": [ @@ -896,7 +896,7 @@ "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Responsable" } ], "label.max": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Mitjà" } ], "label.member": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Cerca orgànica" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Compra orgànica" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Social orgànic" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Vídeo orgànic" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Altres" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Pàgina" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Anuncis de pagament" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Cerca de pagament" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Compra de pagament" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Social de pagament" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Vídeo de pagament" } ], "label.password": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Referència" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Restant" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Seleccionar filtre" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Dades de sessió" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Comparteix" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Fonts" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Etiqueta" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Etiquetes" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Configuració de l'equip" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Termes" } ], "label.theme": [ diff --git a/public/intl/messages/cs-CZ.json b/public/intl/messages/cs-CZ.json index ba653caf..d1873ffb 100644 --- a/public/intl/messages/cs-CZ.json +++ b/public/intl/messages/cs-CZ.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Přidat nástěnku" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partner" } ], "label.after": [ @@ -86,25 +86,25 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analytika" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Použít" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atribuce" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Podívejte se, jak uživatelé interagují s vaším marketingem a co vede ke konverzím." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Nástěnky" } ], "label.bounce-rate": [ @@ -140,7 +140,7 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Rozpis" } ], "label.browser": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampaně" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanály" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohorta" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Porovnat data" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Obsah" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konverze" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Míra konverze" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Krok konverze" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Měna" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Přímý" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Jedinečné ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Nezahrnuje" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Neexistuje" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Opuštění" } ], "label.edit": [ @@ -506,7 +506,7 @@ "label.email": [ { "type": 0, - "value": "Email" + "value": "E-mail" } ], "label.enable-share-url": [ @@ -518,7 +518,7 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Konečný krok" } ], "label.entry": [ @@ -536,13 +536,13 @@ "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Data události" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Název události" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existuje" } ], "label.exit": [ @@ -566,13 +566,13 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Rozbalit" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Nepravda" } ], "label.field": [ @@ -584,7 +584,7 @@ "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Pole" } ], "label.filter": [ @@ -614,19 +614,19 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "První kliknutí" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Poprvé viděno" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Trychtýř" } ], "label.funnel-description": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Trychtýře" } ], "label.goal": [ @@ -662,115 +662,115 @@ "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Větší než" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Větší nebo rovno" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Seskupeno" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Název hostitele" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Zahrnuje" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Pohled" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Pohledy" } ], "label.insights-description": [ { "type": 0, - "value": "Dive deeper into your data by using segments and filters." + "value": "Ponořte se hlouběji do svých dat pomocí segmentů a filtrů." } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "Je" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Nepravda" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Není" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Není nastaveno" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Nastaveno" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Pravda" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Připojit se" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Připojit se k týmu" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Cesta" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Zjistěte, jak uživatelé procházejí vaším webem." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Cesty" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Poslední kliknutí" } ], "label.last-days": [ @@ -860,19 +860,19 @@ "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Méně než" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Méně nebo rovno" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "Odkazy" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Střední" } ], "label.member": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Žádný" } ], "label.number-of-records": [ @@ -993,7 +993,7 @@ "value": [ { "type": 0, - "value": "record" + "value": "záznam" } ] }, @@ -1001,7 +1001,7 @@ "value": [ { "type": 0, - "value": "records" + "value": "záznamů" } ] } @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organické vyhledávání" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organický nákup" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organická sociální síť" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organické video" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Jiné" } ], "label.overview": [ @@ -1068,13 +1068,13 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Stránka" } ], "label.page-of": [ { "type": 0, - "value": "Page " + "value": "Stránka " }, { "type": 1, @@ -1082,7 +1082,7 @@ }, { "type": 0, - "value": " of " + "value": " z " }, { "type": 1, @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Placené reklamy" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Placené vyhledávání" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Placený nákup" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Placená sociální síť" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Placené video" } ], "label.password": [ @@ -1158,7 +1158,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pixely" } ], "label.powered-by": [ @@ -1198,31 +1198,31 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Vlastnosti" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Vlastnost" } ], "label.queries": [ { "type": 0, - "value": "Queries" + "value": "Dotazy" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "Dotaz" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "Parametry dotazu" } ], "label.realtime": [ @@ -1234,19 +1234,19 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Doporučení" } ], "label.referrer": [ { "type": 0, - "value": "Referrer" + "value": "Odkazující" } ], "label.referrers": [ { "type": 0, - "value": "Odkazy" + "value": "Odkazující" } ], "label.refresh": [ @@ -1258,7 +1258,7 @@ "label.regenerate": [ { "type": 0, - "value": "Regenerate" + "value": "Regenerovat" } ], "label.region": [ @@ -1270,73 +1270,73 @@ "label.regions": [ { "type": 0, - "value": "Regions" + "value": "Regiony" } ], "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Zbývá" } ], "label.remove": [ { "type": 0, - "value": "Remove" + "value": "Odstranit" } ], "label.remove-member": [ { "type": 0, - "value": "Remove member" + "value": "Odstranit člena" } ], "label.reports": [ { "type": 0, - "value": "Reports" + "value": "Hlášení" } ], "label.required": [ { "type": 0, - "value": "Vyžadováno" + "value": "Povinné" } ], "label.reset": [ { "type": 0, - "value": "Reset" + "value": "Resetovat" } ], "label.reset-website": [ { "type": 0, - "value": "Reset statistics" + "value": "Resetovat statistiky" } ], "label.retention": [ { "type": 0, - "value": "Retention" + "value": "Udržení" } ], "label.retention-description": [ { "type": 0, - "value": "Measure your website stickiness by tracking how often users return." + "value": "Měřte přilnavost svého webu sledováním, jak často se uživatelé vracejí." } ], "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Příjem" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Podívejte se na své příjmy v průběhu času." } ], "label.role": [ @@ -1348,7 +1348,7 @@ "label.run-query": [ { "type": 0, - "value": "Run query" + "value": "Spustit dotaz" } ], "label.save": [ @@ -1360,61 +1360,61 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "Obrazovky" } ], "label.search": [ { "type": 0, - "value": "Search" + "value": "Hledat" } ], "label.select": [ { "type": 0, - "value": "Select" + "value": "Vybrat" } ], "label.select-date": [ { "type": 0, - "value": "Select date" + "value": "Vybrat datum" } ], "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Vybrat filtr" } ], "label.select-role": [ { "type": 0, - "value": "Select role" + "value": "Vybrat roli" } ], "label.select-website": [ { "type": 0, - "value": "Select website" + "value": "Vybrat web" } ], "label.session": [ { "type": 0, - "value": "Session" + "value": "Relace" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Data relace" } ], "label.sessions": [ { "type": 0, - "value": "Sessions" + "value": "Relace" } ], "label.settings": [ @@ -1426,13 +1426,13 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Sdílet" } ], "label.share-url": [ { "type": 0, - "value": "Sdílet URL" + "value": "URL pro sdílení" } ], "label.single-day": [ @@ -1450,25 +1450,25 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Zdroje" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "Počáteční krok" } ], "label.steps": [ { "type": 0, - "value": "Steps" + "value": "Kroky" } ], "label.sum": [ { "type": 0, - "value": "Sum" + "value": "Součet" } ], "label.tablet": [ @@ -1480,85 +1480,85 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Štítek" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Štítky" } ], "label.team": [ { "type": 0, - "value": "Team" + "value": "Tým" } ], "label.team-id": [ { "type": 0, - "value": "Team ID" + "value": "ID týmu" } ], "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Manažer týmu" } ], "label.team-member": [ { "type": 0, - "value": "Team member" + "value": "Člen týmu" } ], "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "Název týmu" } ], "label.team-owner": [ { "type": 0, - "value": "Team owner" + "value": "Vlastník týmu" } ], "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Nastavení týmu" } ], "label.team-view-only": [ { "type": 0, - "value": "Team view only" + "value": "Pouze pro zobrazení týmu" } ], "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "Weby týmu" } ], "label.teams": [ { "type": 0, - "value": "Teams" + "value": "Týmy" } ], "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Termíny" } ], "label.theme": [ { "type": 0, - "value": "Theme" + "value": "Téma" } ], "label.this-month": [ diff --git a/public/intl/messages/da-DK.json b/public/intl/messages/da-DK.json index 1671733b..8d33490c 100644 --- a/public/intl/messages/da-DK.json +++ b/public/intl/messages/da-DK.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Adgangskode" } ], "label.actions": [ @@ -14,37 +14,37 @@ "label.activity": [ { "type": 0, - "value": "Activity log" + "value": "Aktivitetslog" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "Tilføj" } ], "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Tilføj tavle" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Tilføj beskrivelse" } ], "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Tilføj medlem" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Tilføj trin" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partner" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "Efter" } ], "label.all": [ @@ -86,31 +86,31 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analyser" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Anvend" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Attribuering" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Se, hvordan brugere interagerer med din markedsføring, og hvad der driver konverteringer." } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Gennemsnit" } ], "label.back": [ @@ -122,13 +122,13 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Før" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Tavler" } ], "label.bounce-rate": [ @@ -140,7 +140,7 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Opdeling" } ], "label.browser": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampagner" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanaler" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Byer" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "By" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Ryd alt" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohorte" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Sammenlign" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Sammenlign datoer" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Bekræft" } ], "label.confirm-password": [ @@ -236,37 +236,37 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Indhold" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "Fortsæt" } ], "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konvertering" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Konverteringsrate" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Konverteringstrin" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Antal" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Land" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "Opret" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Opret rapport" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Opret team" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Opret bruger" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Oprettet" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Oprettet af" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Valuta" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Nuværende" } ], "label.current-password": [ @@ -356,7 +356,7 @@ "label.date": [ { "type": 0, - "value": "Date" + "value": "Dato" } ], "label.date-range": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Dag" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Slet rapport" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Slet team" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Slet bruger" } ], "label.delete-website": [ @@ -410,25 +410,25 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Beskrivelse" } ], "label.desktop": [ { "type": 0, - "value": "Desktop" + "value": "Skrivebord" } ], "label.details": [ { "type": 0, - "value": "Details" + "value": "Detaljer" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "Enhed" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Direkte" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Unikt ID" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Indeholder ikke" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Inkluderer ikke" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Findes ikke" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Frafald" } ], "label.edit": [ @@ -494,19 +494,19 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Rediger betjeningspanel" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Rediger medlem" } ], "label.email": [ { "type": 0, - "value": "Email" + "value": "E-mail" } ], "label.enable-share-url": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Sluttrin" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "Indgangs-URL" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Hændelse" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Hændelsesdata" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Hændelsesnavn" } ], "label.events": [ @@ -554,37 +554,37 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Findes" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "Udgangs-URL" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Udvid" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Falsk" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Felt" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Felter" } ], "label.filter": [ @@ -608,169 +608,169 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Filtre" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Første klik" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Først set" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Tragt" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "Forstå brugernes konverterings- og frafaldsrate." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Tragte" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Mål" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Mål" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Følg dine mål for sidevisninger og hændelser." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Større end" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Større end eller lig med" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Gruperet" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Værtsnavn" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Inkluderer" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Indsigt" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Indsigter" } ], "label.insights-description": [ { "type": 0, - "value": "Dive deeper into your data by using segments and filters." + "value": "Dyk dybere ned i dine data ved at bruge segmenter og filtre." } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "Er" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Er falsk" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Er ikke" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Er ikke sat" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Er sat" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Er sandt" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Deltag" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Deltag i team" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Rejse" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Forstå hvordan brugere navigerer på din hjemmeside." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Rejser" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Sidste klik" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Sidste " }, { "type": 1, @@ -836,37 +836,37 @@ }, { "type": 0, - "value": " months" + "value": " måneder" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Sidst set" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Forlad" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Forlad team" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Mindre end" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Mindre end eller lig med" } ], "label.links": [ @@ -890,19 +890,19 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "Administrer" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Leder" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "Maks" } ], "label.medium": [ @@ -914,13 +914,13 @@ "label.member": [ { "type": 0, - "value": "Member" + "value": "Medlem" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Medlemmer" } ], "label.min": [ @@ -950,13 +950,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "Min konto" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Mine hjemmesider" } ], "label.name": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Ingen" } ], "label.number-of-records": [ @@ -993,7 +993,7 @@ "value": [ { "type": 0, - "value": "record" + "value": "post" } ] }, @@ -1001,7 +1001,7 @@ "value": [ { "type": 0, - "value": "records" + "value": "poster" } ] } @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organisk søgning" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organisk shopping" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organisk social" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organisk video" } ], "label.os": [ @@ -1050,13 +1050,13 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Andet" } ], "label.overview": [ { "type": 0, - "value": "Overview" + "value": "Oversigt" } ], "label.owner": [ @@ -1068,13 +1068,13 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Side" } ], "label.page-of": [ { "type": 0, - "value": "Page " + "value": "Side " }, { "type": 1, @@ -1082,7 +1082,7 @@ }, { "type": 0, - "value": " of " + "value": " af " }, { "type": 1, @@ -1098,7 +1098,7 @@ "label.pageTitle": [ { "type": 0, - "value": "Page title" + "value": "Sidetitel" } ], "label.pages": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Betalte annoncer" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Betalt søgning" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Betalt shopping" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Betalt social" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Betalt video" } ], "label.password": [ @@ -1146,13 +1146,13 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Sti" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Stier" } ], "label.pixels": [ @@ -1198,31 +1198,31 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Egenskaber" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Egenskab" } ], "label.queries": [ { "type": 0, - "value": "Queries" + "value": "Forespørgsler" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "Forespørgsel" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "Forespørgselsparametre" } ], "label.realtime": [ @@ -1234,13 +1234,13 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Henvisning" } ], "label.referrer": [ { "type": 0, - "value": "Referrer" + "value": "Henviser" } ], "label.referrers": [ @@ -1258,7 +1258,7 @@ "label.regenerate": [ { "type": 0, - "value": "Regenerate" + "value": "Gendan" } ], "label.region": [ @@ -1270,31 +1270,31 @@ "label.regions": [ { "type": 0, - "value": "Regions" + "value": "Regioner" } ], "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Tilbageværende" } ], "label.remove": [ { "type": 0, - "value": "Remove" + "value": "Fjern" } ], "label.remove-member": [ { "type": 0, - "value": "Remove member" + "value": "Fjern medlem" } ], "label.reports": [ { "type": 0, - "value": "Reports" + "value": "Rapporter" } ], "label.required": [ @@ -1312,43 +1312,43 @@ "label.reset-website": [ { "type": 0, - "value": "Nulstil statistikker" + "value": "Nulstil statistik" } ], "label.retention": [ { "type": 0, - "value": "Retention" + "value": "Fastholdelse" } ], "label.retention-description": [ { "type": 0, - "value": "Measure your website stickiness by tracking how often users return." + "value": "Mål hvor ofte brugere vender tilbage til din hjemmeside." } ], "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Indtægt" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Se din indtægt over tid." } ], "label.role": [ { "type": 0, - "value": "Role" + "value": "Rolle" } ], "label.run-query": [ { "type": 0, - "value": "Run query" + "value": "Kør forespørgsel" } ], "label.save": [ @@ -1360,43 +1360,43 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "Skærme" } ], "label.search": [ { "type": 0, - "value": "Search" + "value": "Søg" } ], "label.select": [ { "type": 0, - "value": "Select" + "value": "Vælg" } ], "label.select-date": [ { "type": 0, - "value": "Select date" + "value": "Vælg dato" } ], "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Vælg filter" } ], "label.select-role": [ { "type": 0, - "value": "Select role" + "value": "Vælg rolle" } ], "label.select-website": [ { "type": 0, - "value": "Select website" + "value": "Vælg hjemmeside" } ], "label.session": [ @@ -1408,13 +1408,13 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Sessionsdata" } ], "label.sessions": [ { "type": 0, - "value": "Sessions" + "value": "Sessioner" } ], "label.settings": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Del" } ], "label.share-url": [ @@ -1450,19 +1450,19 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Kilder" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "Starttrin" } ], "label.steps": [ { "type": 0, - "value": "Steps" + "value": "Trin" } ], "label.sum": [ @@ -1504,43 +1504,43 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Teamleder" } ], "label.team-member": [ { "type": 0, - "value": "Team member" + "value": "Teammedlem" } ], "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "Teamnavn" } ], "label.team-owner": [ { "type": 0, - "value": "Team owner" + "value": "Teamejer" } ], "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Teamindstillinger" } ], "label.team-view-only": [ { "type": 0, - "value": "Team view only" + "value": "Kun visning af team" } ], "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "Teamets hjemmesider" } ], "label.teams": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Vilkår" } ], "label.theme": [ diff --git a/public/intl/messages/de-CH.json b/public/intl/messages/de-CH.json index dd1745d8..7f5daed9 100644 --- a/public/intl/messages/de-CH.json +++ b/public/intl/messages/de-CH.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Board hinzuefüege" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partnerprogramm" } ], "label.after": [ @@ -86,25 +86,25 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analytik" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Aawände" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Zuordnig" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Lueg wie d'Benutzer mit dim Marketing interagiere und was zu Umwandlige führt." } ], "label.average": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampagne" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanäle" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Gruppe" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Datum vergleiche" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Inhalt" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Umwandlig" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Umwandligsrate" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Umwandligsschritt" } ], "label.count": [ @@ -314,13 +314,13 @@ "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Erstellt vo" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Währung" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Direkt" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Eindeutigi ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Isch nid debii" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Existiert nid" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Ereignissname" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existiert" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Uusklappe" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Erste Klick" } ], "label.first-seen": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Gruppiert" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Hostnam" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Isch debii" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Iiblick" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Isch falsch" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Isch wahr" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Reise" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Letzte Klick" } ], "label.last-days": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organischi Suechi" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organischi Iikauf" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organischi Social Media" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organischi Video" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Anderi" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Siite" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Bezahlti Werbung" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Bezahlti Suechi" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Bezahlti Iikauf" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Bezahlti Social Media" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Bezahlti Video" } ], "label.password": [ @@ -1158,7 +1158,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pixel" } ], "label.powered-by": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Eigeschafte" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Eigeschafte" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Empfehlig" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Verblibe" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Filter uuswähle" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Sitzigsdate" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Teile" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Quälle" } ], "label.start-step": [ @@ -1486,7 +1486,7 @@ "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Stichwort" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Team Istellige" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Bedingige" } ], "label.theme": [ diff --git a/public/intl/messages/de-DE.json b/public/intl/messages/de-DE.json index fc2925ad..f948baae 100644 --- a/public/intl/messages/de-DE.json +++ b/public/intl/messages/de-DE.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Board hinzufügen" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partnerprogramm" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Anwenden" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Zuordnung" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Sehen Sie, wie Nutzer mit Ihrem Marketing interagieren und was zu Konversionen führt." } ], "label.average": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampagnen" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanäle" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Gruppe" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Daten vergleichen" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Inhalt" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Konversionsrate" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Konversionsschritt" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Währung" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Direkt" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Eindeutige ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Nicht enthalten" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Existiert nicht" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Ereignisname" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existiert" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Erweitern" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Erster Klick" } ], "label.first-seen": [ @@ -674,7 +674,7 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Gruppiert" } ], "label.hostname": [ @@ -686,13 +686,13 @@ "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Enthält" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Einblick" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Ist falsch" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Ist wahr" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Reisen" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Letzter Klick" } ], "label.last-days": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organische Suche" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organisches Shopping" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organisches Social Media" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organisches Video" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Andere" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Seite" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Bezahlte Anzeigen" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Bezahlte Suche" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Bezahltes Shopping" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Bezahltes Social Media" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Bezahltes Video" } ], "label.password": [ @@ -1158,7 +1158,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pixel" } ], "label.powered-by": [ @@ -1204,7 +1204,7 @@ "label.property": [ { "type": 0, - "value": "Eigentum" + "value": "Eigenschaft" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Empfehlung" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Verbleibend" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Filter auswählen" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Sitzungsdaten" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Teilen" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Quellen" } ], "label.start-step": [ @@ -1486,7 +1486,7 @@ "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Stichworte" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Team-Einstellungen" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Bedingungen" } ], "label.theme": [ diff --git a/public/intl/messages/el-GR.json b/public/intl/messages/el-GR.json index 1fb6cc2a..134d06fe 100644 --- a/public/intl/messages/el-GR.json +++ b/public/intl/messages/el-GR.json @@ -251,7 +251,7 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, "value": "Conversion rate" diff --git a/public/intl/messages/en-GB.json b/public/intl/messages/en-GB.json index 4cfd762c..12d854af 100644 --- a/public/intl/messages/en-GB.json +++ b/public/intl/messages/en-GB.json @@ -251,7 +251,7 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, "value": "Conversion rate" diff --git a/public/intl/messages/en-US.json b/public/intl/messages/en-US.json index da7cb479..b04d63ec 100644 --- a/public/intl/messages/en-US.json +++ b/public/intl/messages/en-US.json @@ -251,7 +251,7 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, "value": "Conversion rate" diff --git a/public/intl/messages/es-ES.json b/public/intl/messages/es-ES.json index d7fb1f17..3c875dc2 100644 --- a/public/intl/messages/es-ES.json +++ b/public/intl/messages/es-ES.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Añadir tablero" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Afiliado" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Aplicar" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atribución" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Vea cómo los usuarios interactúan con su marketing y qué impulsa las conversiones." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Tableros" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Campañas" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Canales" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Cohorte" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Comparar fechas" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Contenido" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Conversión" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Tasa de conversión" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Paso de conversión" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Moneda" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Directo" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "ID distinto" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "No incluye" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "No existe" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Nombre del evento" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existe" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Expandir" } ], "label.false": [ @@ -614,13 +614,13 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Primer clic" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Primera vez visto" } ], "label.funnel": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Embudos" } ], "label.goal": [ @@ -674,31 +674,31 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Agrupado" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Nombre de host" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Incluye" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Perspectiva" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Perspectivas" } ], "label.insights-description": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Es falso" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Es verdadero" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Viajes" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Último clic" } ], "label.last-days": [ @@ -842,7 +842,7 @@ "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Última vez visto" } ], "label.leave": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Enlaces" } ], "label.login": [ @@ -896,19 +896,19 @@ "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Gerente" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "Máximo" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Medio" } ], "label.member": [ @@ -926,7 +926,7 @@ "label.min": [ { "type": 0, - "value": "Min" + "value": "Mínimo" } ], "label.mobile": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Modelo" } ], "label.more": [ @@ -993,7 +993,7 @@ "value": [ { "type": 0, - "value": "record" + "value": "registro" } ] }, @@ -1001,7 +1001,7 @@ "value": [ { "type": 0, - "value": "records" + "value": "registros" } ] } @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Búsqueda orgánica" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Compras orgánicas" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Social orgánico" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Video orgánico" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Otro" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Página" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Anuncios pagados" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Búsqueda pagada" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Compras pagadas" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Social pagado" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Video pagado" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Ruta" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Rutas" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Píxeles" } ], "label.powered-by": [ @@ -1198,7 +1198,7 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Propiedades" } ], "label.property": [ @@ -1222,7 +1222,7 @@ "label.query-parameters": [ { "type": 0, - "value": "Parámetros de petición" + "value": "Parámetros de consulta" } ], "label.realtime": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Referencia" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Restante" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Ingresos" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Consulte sus ingresos a lo largo del tiempo." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Seleccionar filtro" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Sesión" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Datos de sesión" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Compartir" } ], "label.share-url": [ @@ -1450,13 +1450,13 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Fuentes" } ], "label.start-step": [ { "type": 0, - "value": "Paso inical" + "value": "Paso inicial" } ], "label.steps": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Etiqueta" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Etiquetas" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Configuración del equipo" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Términos" } ], "label.theme": [ diff --git a/public/intl/messages/fa-IR.json b/public/intl/messages/fa-IR.json index bf3628f6..fa071712 100644 --- a/public/intl/messages/fa-IR.json +++ b/public/intl/messages/fa-IR.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "افزودن برد" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "همکار فروش" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "اعمال" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "انتساب" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "ببینید کاربران چگونه با بازاریابی شما تعامل دارند و چه چیزی باعث تبدیل می‌شود." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "بردها" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "کمپین‌ها" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "کانال‌ها" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "گروه" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "مقایسه تاریخ‌ها" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "محتوا" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "تبدیل" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "نرخ تبدیل" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "گام تبدیل" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "واحد پول" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "مستقیم" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "شناسه یکتا" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "شامل نمی‌شود" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "وجود ندارد" } ], "label.domain": [ @@ -506,7 +506,7 @@ "label.email": [ { "type": 0, - "value": "Email" + "value": "ایمیل" } ], "label.enable-share-url": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "نام رویداد" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "وجود دارد" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "گسترش" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "اولین کلیک" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "قیف‌ها" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "گروه‌بندی شده" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "نام میزبان" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "شامل می‌شود" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "بینش" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "نادرست است" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "درست است" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "مسیرها" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "آخرین کلیک" } ], "label.last-days": [ @@ -860,7 +860,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "لینک‌ها" } ], "label.login": [ @@ -896,7 +896,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "متوسط" } ], "label.member": [ @@ -926,7 +926,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "مدل" } ], "label.more": [ @@ -1008,25 +1008,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "جستجوی ارگانیک" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "خرید ارگانیک" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "شبکه اجتماعی ارگانیک" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "ویدیوی ارگانیک" } ], "label.os": [ @@ -1038,7 +1038,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "سایر" } ], "label.overview": [ @@ -1056,7 +1056,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "صفحه" } ], "label.page-of": [ @@ -1098,31 +1098,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "تبلیغات پولی" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "جستجوی پولی" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "خرید پولی" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "شبکه اجتماعی پولی" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "ویدیوی پولی" } ], "label.password": [ @@ -1146,7 +1146,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "پیکسل‌ها" } ], "label.powered-by": [ @@ -1222,7 +1222,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "ارجاع" } ], "label.referrer": [ @@ -1264,7 +1264,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "باقی‌مانده" } ], "label.remove": [ @@ -1372,7 +1372,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "انتخاب فیلتر" } ], "label.select-role": [ @@ -1396,7 +1396,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "داده‌های نشست" } ], "label.sessions": [ @@ -1414,7 +1414,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "اشتراک‌گذاری" } ], "label.share-url": [ @@ -1438,7 +1438,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "منابع" } ], "label.start-step": [ @@ -1468,13 +1468,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "برچسب" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "برچسب‌ها" } ], "label.team": [ @@ -1516,7 +1516,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "تنظیمات تیم" } ], "label.team-view-only": [ @@ -1540,7 +1540,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "شرایط" } ], "label.theme": [ diff --git a/public/intl/messages/fi-FI.json b/public/intl/messages/fi-FI.json index 06d63bd2..232ba4e4 100644 --- a/public/intl/messages/fi-FI.json +++ b/public/intl/messages/fi-FI.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Pääsykoodi" } ], "label.actions": [ @@ -14,37 +14,37 @@ "label.activity": [ { "type": 0, - "value": "Activity log" + "value": "Toimintaloki" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "Lisää" } ], "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Lisää taulu" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Lisää kuvaus" } ], "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Lisää jäsen" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Lisää vaihe" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Kumppani" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "Jälkeen" } ], "label.all": [ @@ -86,31 +86,31 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analytiikka" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Käytä" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Attribuutio" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Katso, miten käyttäjät ovat vuorovaikutuksessa markkinointisi kanssa ja mikä johtaa konversioihin." } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Keskiarvo" } ], "label.back": [ @@ -122,13 +122,13 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Ennen" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Taulut" } ], "label.bounce-rate": [ @@ -140,13 +140,13 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Erittele" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "Selain" } ], "label.browsers": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampanjat" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanavat" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Kaupungit" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "Kaupunki" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Tyhjennä kaikki" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohortti" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Vertaa" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Vertaa päivämääriä" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Vahvista" } ], "label.confirm-password": [ @@ -236,37 +236,37 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Sisältö" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "Jatka" } ], "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konversio" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Konversioprosentti" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Konversiovaihe" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Lukumäärä" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Maa" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "Luo" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Luo raportti" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Luo tiimi" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Luo käyttäjä" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Luotu" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Luonut" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Valuutta" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Nykyinen" } ], "label.current-password": [ @@ -356,7 +356,7 @@ "label.date": [ { "type": 0, - "value": "Date" + "value": "Päivämäärä" } ], "label.date-range": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Päivä" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Poista raportti" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Poista tiimi" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Poista käyttäjä" } ], "label.delete-website": [ @@ -410,7 +410,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Kuvaus" } ], "label.desktop": [ @@ -422,13 +422,13 @@ "label.details": [ { "type": 0, - "value": "Details" + "value": "Tiedot" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "Laite" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Suora" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Yksilöllinen ID" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Ei sisällä" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Ei sisällä" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Ei ole olemassa" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Poistuminen" } ], "label.edit": [ @@ -494,19 +494,19 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Muokkaa ohjauspaneelia" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Muokkaa jäsentä" } ], "label.email": [ { "type": 0, - "value": "Email" + "value": "Sähköposti" } ], "label.enable-share-url": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Loppuvaihe" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "Tulo-URL" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Tapahtuma" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Tapahtumatiedot" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Tapahtuman nimi" } ], "label.events": [ @@ -554,37 +554,37 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "On olemassa" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "Poistumis-URL" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Laajenna" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Epätosi" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Kenttä" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Kentät" } ], "label.filter": [ @@ -608,169 +608,169 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Suodattimet" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Ensimmäinen klikkaus" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Ensimmäinen havainto" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Suppilo" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "Ymmärrä käyttäjien konversio- ja poistumisprosentti." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Suppilot" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Tavoite" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Tavoitteet" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Seuraa sivun katselujen ja tapahtumien tavoitteitasi." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Suurempi kuin" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Suurempi tai yhtä suuri kuin" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Ryhmitelty" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Isäntänimi" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Sisältää" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Oivallus" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Oivallukset" } ], "label.insights-description": [ { "type": 0, - "value": "Dive deeper into your data by using segments and filters." + "value": "Sukella syvemmälle tietoihisi käyttämällä segmenttejä ja suodattimia." } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "On" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "On epätosi" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Ei ole" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Ei asetettu" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Asetettu" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "On tosi" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Liity" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Liity tiimiin" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Polku" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Ymmärrä, miten käyttäjät navigoivat sivustollasi." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Polut" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Viimeinen klikkaus" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Viimeiset " }, { "type": 1, @@ -836,43 +836,43 @@ }, { "type": 0, - "value": " months" + "value": " kuukautta" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Viimeksi nähty" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Poistu" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Poistu tiimistä" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Vähemmän kuin" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Vähemmän tai yhtä suuri kuin" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "Linkit" } ], "label.login": [ @@ -890,43 +890,43 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "Hallinnoi" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Päällikkö" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "Maksimi" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Keskitaso" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "Jäsen" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Jäsenet" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "Minimi" } ], "label.mobile": [ @@ -950,13 +950,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "Oma tili" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Omat verkkosivut" } ], "label.name": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Ei mitään" } ], "label.number-of-records": [ @@ -993,7 +993,7 @@ "value": [ { "type": 0, - "value": "record" + "value": "tietue" } ] }, @@ -1001,7 +1001,7 @@ "value": [ { "type": 0, - "value": "records" + "value": "tietuetta" } ] } @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Orgaaninen haku" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Orgaaninen ostaminen" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Orgaaninen sosiaalinen" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Orgaaninen video" } ], "label.os": [ @@ -1050,13 +1050,13 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Muu" } ], "label.overview": [ { "type": 0, - "value": "Overview" + "value": "Yleiskatsaus" } ], "label.owner": [ @@ -1068,13 +1068,13 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Sivu" } ], "label.page-of": [ { "type": 0, - "value": "Page " + "value": "Sivu " }, { "type": 1, @@ -1082,7 +1082,7 @@ }, { "type": 0, - "value": " of " + "value": " / " }, { "type": 1, @@ -1098,7 +1098,7 @@ "label.pageTitle": [ { "type": 0, - "value": "Page title" + "value": "Sivun otsikko" } ], "label.pages": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Maksetut mainokset" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Maksettu haku" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Maksettu ostaminen" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Maksettu sosiaalinen" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Maksettu video" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Polku" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Polut" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pikselit" } ], "label.powered-by": [ @@ -1198,31 +1198,31 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Ominaisuudet" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Ominaisuus" } ], "label.queries": [ { "type": 0, - "value": "Queries" + "value": "Kyselyt" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "Kysely" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "Kyselyn parametrit" } ], "label.realtime": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Viittaus" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Jäljellä" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Tulot" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Katso tulosi ajan mittaan." } ], "label.role": [ @@ -1360,7 +1360,7 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "Näytöt" } ], "label.search": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Valitse suodatin" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Istunto" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Istuntotiedot" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Jaa" } ], "label.share-url": [ @@ -1450,19 +1450,19 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Lähteet" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "Aloitusvaihe" } ], "label.steps": [ { "type": 0, - "value": "Steps" + "value": "Vaiheet" } ], "label.sum": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Tunniste" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Tunnisteet" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Tiimin asetukset" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Ehdot" } ], "label.theme": [ diff --git a/public/intl/messages/fo-FO.json b/public/intl/messages/fo-FO.json index 0951992a..d02f44c8 100644 --- a/public/intl/messages/fo-FO.json +++ b/public/intl/messages/fo-FO.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Aðgangskoda" } ], "label.actions": [ @@ -20,31 +20,31 @@ "label.add": [ { "type": 0, - "value": "Add" + "value": "Legg afturat" } ], "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Legg borð afturat" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Legg lýsing afturat" } ], "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Legg lim afturat" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Legg stig afturat" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Samband" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "Eftir" } ], "label.all": [ @@ -80,37 +80,37 @@ "label.all-time": [ { "type": 0, - "value": "All time" + "value": "Allur tíðin" } ], "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Greining" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Nýt" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Áseting" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Síggj hvussu brúkarar samskifta við marknaðarføringina og hvat førir til umvendingar." } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Miðal" } ], "label.back": [ @@ -122,13 +122,13 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Áðrenn" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Borð" } ], "label.bounce-rate": [ @@ -140,13 +140,13 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Sundurgreining" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "Kagi" } ], "label.browsers": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Herferðir" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Rásir" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Býir" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "Býur" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Tøm alt" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Bólkur" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Samanber" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Samanber dato" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Staðfest" } ], "label.confirm-password": [ @@ -230,43 +230,43 @@ "label.contains": [ { "type": 0, - "value": "Contains" + "value": "Inniheldur" } ], "label.content": [ { "type": 0, - "value": "Content" + "value": "Innihald" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "Halt fram" } ], "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Umvending" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Umvendingarprosent" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Umvendingarstigur" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Tal" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Land" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "Stovna" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Stovna frágreiðing" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Stovna lið" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Stovna brúkara" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Stovnaður" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Stovnaður av" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Gjaldoyra" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Núverandi" } ], "label.current-password": [ @@ -350,13 +350,13 @@ "label.data": [ { "type": 0, - "value": "Data" + "value": "Dáta" } ], "label.date": [ { "type": 0, - "value": "Date" + "value": "Dato" } ], "label.date-range": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Dagur" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Strika frágreiðing" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Strika lið" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Strika brúkara" } ], "label.delete-website": [ @@ -410,7 +410,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Lýsing" } ], "label.desktop": [ @@ -422,13 +422,13 @@ "label.details": [ { "type": 0, - "value": "Details" + "value": "Nærri upplýsingar" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "Tól" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Beinleiðis" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Sermerkt ID" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Inniheldur ikki" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Er ikki við" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Er ikki til" } ], "label.domain": [ @@ -494,19 +494,19 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Ritstjórna yvirlitsskíggja" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Ritstjórna lim" } ], "label.email": [ { "type": 0, - "value": "Email" + "value": "Teldupostur" } ], "label.enable-share-url": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Endastigur" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "Inngangs URL" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Tiltak" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Tiltaksdata" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Tiltaksnavn" } ], "label.events": [ @@ -554,43 +554,43 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Er til" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "Útgangs URL" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Víðka" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Falskt" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Øki" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Øki" } ], "label.filter": [ { "type": 0, - "value": "Filter" + "value": "Sía" } ], "label.filter-combined": [ @@ -608,181 +608,181 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Síur" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Fyrsta trýst" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Fyrst sæddur" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Traktari" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "Fá yvirlit yvir umvendingar og fráfall hjá brúkarum." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Traktarar" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Mál" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Mál" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Fylg við málum fyri síðuvísingar og tiltøk." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Størri enn" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Størri ella javnt" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Bólkað" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Vertnavn" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Inniheldur" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Innlit" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Innlit" } ], "label.insights-description": [ { "type": 0, - "value": "Dive deeper into your data by using segments and filters." + "value": "Fá meira innlit í tínar dátur við at brúka bólkar og síur." } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "Er" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Er falskt" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Er ikki" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Er ikki sett" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Er sett" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Er satt" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Luttak" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Luttak í liði" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Ferð" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Fá yvirlit yvir hvussu brúkarar ferðast á heimasíðuni." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Ferðir" } ], "label.language": [ { "type": 0, - "value": "Language" + "value": "Mál" } ], "label.languages": [ { "type": 0, - "value": "Languages" + "value": "Mál" } ], "label.laptop": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Seinasta trýst" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Seinastu " }, { "type": 1, @@ -836,43 +836,43 @@ }, { "type": 0, - "value": " months" + "value": " mánaðirnar" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Síðst sæddur" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Far burtur" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Far úr liði" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Minni enn" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Minni ella javnt" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "Leinkjur" } ], "label.login": [ @@ -890,43 +890,43 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "Stýra" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Stjóri" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "Mest" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Miðal" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "Limur" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Limir" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "Minst" } ], "label.mobile": [ @@ -950,13 +950,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "Mín konto" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Mínar heimasíður" } ], "label.name": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Eingin" } ], "label.number-of-records": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organisk leiting" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organisk keyp" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organisk sosial miðla" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organisk video" } ], "label.os": [ @@ -1050,31 +1050,31 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Annað" } ], "label.overview": [ { "type": 0, - "value": "Overview" + "value": "Yvirlit" } ], "label.owner": [ { "type": 0, - "value": "Owner" + "value": "Eigari" } ], "label.page": [ { "type": 0, - "value": "Page" + "value": "Síða" } ], "label.page-of": [ { "type": 0, - "value": "Page " + "value": "Síða " }, { "type": 1, @@ -1082,7 +1082,7 @@ }, { "type": 0, - "value": " of " + "value": " av " }, { "type": 1, @@ -1098,7 +1098,7 @@ "label.pageTitle": [ { "type": 0, - "value": "Page title" + "value": "Síðuheiti" } ], "label.pages": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Goldnar lýsingar" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Goldin leiting" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Goldið keyp" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Goldin sosial miðla" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Goldið video" } ], "label.password": [ @@ -1146,25 +1146,25 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Leið" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Leiðir" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pikslur" } ], "label.powered-by": [ { "type": 0, - "value": "Powered by " + "value": "Rikið av " }, { "type": 1, @@ -1174,19 +1174,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Fyrra" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Fyrra tíðarskeið" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Fyrra ár" } ], "label.profile": [ @@ -1198,31 +1198,31 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Eginleikar" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Eginleiki" } ], "label.queries": [ { "type": 0, - "value": "Queries" + "value": "Fyrispurningar" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "Fyrispurningur" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "Fyrispurningsparametrar" } ], "label.realtime": [ @@ -1234,13 +1234,13 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Ávísing" } ], "label.referrer": [ { "type": 0, - "value": "Referrer" + "value": "Ávísari" } ], "label.referrers": [ @@ -1252,55 +1252,55 @@ "label.refresh": [ { "type": 0, - "value": "Endurskapa" + "value": "Dagfør" } ], "label.regenerate": [ { "type": 0, - "value": "Regenerate" + "value": "Endurskapa" } ], "label.region": [ { "type": 0, - "value": "Region" + "value": "Øki" } ], "label.regions": [ { "type": 0, - "value": "Regions" + "value": "Øki" } ], "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Eftir" } ], "label.remove": [ { "type": 0, - "value": "Remove" + "value": "Fjern" } ], "label.remove-member": [ { "type": 0, - "value": "Remove member" + "value": "Fjern lim" } ], "label.reports": [ { "type": 0, - "value": "Reports" + "value": "Frágreiðingar" } ], "label.required": [ { "type": 0, - "value": "Kravt" + "value": "Kravið" } ], "label.reset": [ @@ -1312,43 +1312,43 @@ "label.reset-website": [ { "type": 0, - "value": "Reset statistics" + "value": "Nulstilla heimasíðu" } ], "label.retention": [ { "type": 0, - "value": "Retention" + "value": "Hald" } ], "label.retention-description": [ { "type": 0, - "value": "Measure your website stickiness by tracking how often users return." + "value": "Mát hvussu ofta brúkarar koma aftur á tína síðu." } ], "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Inntøka" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Fá yvirlit yvir inntøku yvir tíð." } ], "label.role": [ { "type": 0, - "value": "Role" + "value": "Leiklutur" } ], "label.run-query": [ { "type": 0, - "value": "Run query" + "value": "Koyr fyrispurning" } ], "label.save": [ @@ -1360,61 +1360,61 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "Skíggjar" } ], "label.search": [ { "type": 0, - "value": "Search" + "value": "Leita" } ], "label.select": [ { "type": 0, - "value": "Select" + "value": "Vel" } ], "label.select-date": [ { "type": 0, - "value": "Select date" + "value": "Vel dato" } ], "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Vel síu" } ], "label.select-role": [ { "type": 0, - "value": "Select role" + "value": "Vel leiklut" } ], "label.select-website": [ { "type": 0, - "value": "Select website" + "value": "Vel heimasíðu" } ], "label.session": [ { "type": 0, - "value": "Session" + "value": "Seta" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Setudáta" } ], "label.sessions": [ { "type": 0, - "value": "Sessions" + "value": "Setur" } ], "label.settings": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Deil" } ], "label.share-url": [ @@ -1450,25 +1450,25 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Keldur" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "Byrjanarstigur" } ], "label.steps": [ { "type": 0, - "value": "Steps" + "value": "Stig" } ], "label.sum": [ { "type": 0, - "value": "Sum" + "value": "Samanlagt" } ], "label.tablet": [ @@ -1480,85 +1480,85 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Merki" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Merki" } ], "label.team": [ { "type": 0, - "value": "Team" + "value": "Lið" } ], "label.team-id": [ { "type": 0, - "value": "Team ID" + "value": "Lið ID" } ], "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Liðleiðari" } ], "label.team-member": [ { "type": 0, - "value": "Team member" + "value": "Liðlimur" } ], "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "Liðnavn" } ], "label.team-owner": [ { "type": 0, - "value": "Team owner" + "value": "Liðeigari" } ], "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Liðstillingar" } ], "label.team-view-only": [ { "type": 0, - "value": "Team view only" + "value": "Bert til at síggja lið" } ], "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "Lið heimasíður" } ], "label.teams": [ { "type": 0, - "value": "Teams" + "value": "Lið" } ], "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Treytir" } ], "label.theme": [ { "type": 0, - "value": "Theme" + "value": "Evni" } ], "label.this-month": [ diff --git a/public/intl/messages/fr-FR.json b/public/intl/messages/fr-FR.json index 11115211..79697401 100644 --- a/public/intl/messages/fr-FR.json +++ b/public/intl/messages/fr-FR.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Ajouter un tableau" } ], "label.add-description": [ @@ -86,13 +86,13 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analytique" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Appliquer" } ], "label.attribution": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Tableaux" } ], "label.bounce-rate": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Cohorte" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Comparer les dates" } ], "label.confirm": [ @@ -251,10 +251,10 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Taux de conversion" } ], "label.conversion-step": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "ID distinct" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "N'inclut pas" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "N'existe pas" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Nom de l'évènement" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existe" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Développer" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Premier clic" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Entonnoirs" } ], "label.goal": [ @@ -680,25 +680,25 @@ "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Nom d'hôte" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Inclut" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Aperçu" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Aperçus" } ], "label.insights-description": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Est faux" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Est vrai" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Parcours" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Dernier clic" } ], "label.last-days": [ @@ -860,7 +860,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Liens" } ], "label.login": [ @@ -884,7 +884,7 @@ "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Gestionnaire" } ], "label.max": [ @@ -896,7 +896,7 @@ "label.medium": [ { "type": 0, - "value": "Support" + "value": "Moyen" } ], "label.member": [ @@ -1014,7 +1014,7 @@ "label.organic-shopping": [ { "type": 0, - "value": "E-commerce organique" + "value": "Achat organique" } ], "label.organic-social": [ @@ -1110,7 +1110,7 @@ "label.paid-shopping": [ { "type": 0, - "value": "E-commerce payant" + "value": "Achat payant" } ], "label.paid-social": [ @@ -1264,7 +1264,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Restant" } ], "label.remove": [ @@ -1318,13 +1318,13 @@ "label.revenue": [ { "type": 0, - "value": "Recettes" + "value": "Revenus" } ], "label.revenue-description": [ { "type": 0, - "value": "Examinez vos recettes et comment dépensent vos utilisateurs." + "value": "Consultez vos revenus au fil du temps." } ], "label.role": [ @@ -1348,7 +1348,7 @@ "label.screens": [ { "type": 0, - "value": "Résolutions d'écran" + "value": "Écrans" } ], "label.search": [ @@ -1372,7 +1372,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Sélectionner un filtre" } ], "label.select-role": [ @@ -1396,7 +1396,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Données de session" } ], "label.sessions": [ @@ -1414,7 +1414,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Partager" } ], "label.share-url": [ @@ -1468,13 +1468,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Étiquette" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Étiquettes" } ], "label.team": [ diff --git a/public/intl/messages/ga-ES.json b/public/intl/messages/ga-ES.json index b658dc54..ca365e91 100644 --- a/public/intl/messages/ga-ES.json +++ b/public/intl/messages/ga-ES.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Engadir taboleiro" } ], "label.add-description": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Afiliado" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "Despois" } ], "label.all": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Aplicar" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atribución" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Vexa como os usuarios interactúan co seu márketing e que impulsa as conversións." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Taboleiros" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Campañas" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Canles" } ], "label.cities": [ @@ -194,13 +194,13 @@ "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Limpar todo" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Cohorte" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Comparar datas" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Contido" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Conversión" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Taxa de conversión" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Paso de conversión" } ], "label.count": [ @@ -290,19 +290,19 @@ "label.create-report": [ { "type": 0, - "value": "Crear report" + "value": "Crear informe" } ], "label.create-team": [ { "type": 0, - "value": "Crear team" + "value": "Crear equipo" } ], "label.create-user": [ { "type": 0, - "value": "Crear user" + "value": "Crear usuario" } ], "label.created": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Moeda" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Directo" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "ID distinto" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Non inclúe" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Non existe" } ], "label.domain": [ @@ -506,7 +506,7 @@ "label.email": [ { "type": 0, - "value": "Email" + "value": "Correo electrónico" } ], "label.enable-share-url": [ @@ -518,13 +518,13 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Paso final" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "URL de entrada" } ], "label.event": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Nome do evento" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existe" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Expandir" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Primeiro clic" } ], "label.first-seen": [ @@ -626,7 +626,7 @@ "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Funil" } ], "label.funnel-description": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Funís" } ], "label.goal": [ @@ -674,37 +674,37 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Agrupado" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Nome do host" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Inclúe" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Información" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Informacións" } ], "label.insights-description": [ { "type": 0, - "value": "Dive deeper into your data by using segments and filters." + "value": "Afonda nos teus datos usando segmentos e filtros." } ], "label.is": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "É falso" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "É verdadeiro" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Traxectorias" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Último clic" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Ligazóns" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Medio" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Modelo" } ], "label.more": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Ningún" } ], "label.number-of-records": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Busca orgánica" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Compra orgánica" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Social orgánico" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Vídeo orgánico" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Outro" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Páxina" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Anuncios de pago" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Busca de pago" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Compra de pago" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Social de pago" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Vídeo de pago" } ], "label.password": [ @@ -1158,7 +1158,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Píxeles" } ], "label.powered-by": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Referencia" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Restante" } ], "label.remove": [ @@ -1392,7 +1392,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Seleccionar filtro" } ], "label.select-role": [ @@ -1416,7 +1416,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Datos da sesión" } ], "label.sessions": [ @@ -1434,7 +1434,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Compartir" } ], "label.share-url": [ @@ -1458,7 +1458,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Fontes" } ], "label.start-step": [ @@ -1488,13 +1488,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Etiqueta" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Etiquetas" } ], "label.team": [ @@ -1536,7 +1536,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Axustes do equipo" } ], "label.team-view-only": [ @@ -1560,7 +1560,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Termos" } ], "label.theme": [ diff --git a/public/intl/messages/he-IL.json b/public/intl/messages/he-IL.json index e8211e00..b2196f87 100644 --- a/public/intl/messages/he-IL.json +++ b/public/intl/messages/he-IL.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "קוד גישה" } ], "label.actions": [ @@ -14,37 +14,37 @@ "label.activity": [ { "type": 0, - "value": "Activity log" + "value": "יומן פעילות" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "הוסף" } ], "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "הוסף לוח" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "הוסף תיאור" } ], "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "הוסף חבר" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "הוסף שלב" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "שותף" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "אחרי" } ], "label.all": [ @@ -80,37 +80,37 @@ "label.all-time": [ { "type": 0, - "value": "All time" + "value": "כל הזמנים" } ], "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "אנליטיקה" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "החל" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "שיוך" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "צפה כיצד משתמשים מתקשרים עם השיווק שלך ומה מניע המרות." } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "ממוצע" } ], "label.back": [ @@ -122,31 +122,31 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "לפני" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "לוחות" } ], "label.bounce-rate": [ { "type": 0, - "value": "Bounce rate" + "value": "שיעור נטישה" } ], "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "פירוט" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "דפדפן" } ], "label.browsers": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "קמפיינים" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "ערוצים" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "ערים" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "עיר" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "נקה הכל" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "קבוצה" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "השווה" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "השווה תאריכים" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "אשר" } ], "label.confirm-password": [ @@ -236,37 +236,37 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "תוכן" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "המשך" } ], "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "המרה" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "שיעור המרה" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "שלב המרה" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "ספירה" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "מדינה" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "צור" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "צור דוח" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "צור צוות" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "צור משתמש" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "נוצר" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "נוצר על ידי" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "מטבע" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "נוכחי" } ], "label.current-password": [ @@ -350,13 +350,13 @@ "label.data": [ { "type": 0, - "value": "Data" + "value": "נתונים" } ], "label.date": [ { "type": 0, - "value": "Date" + "value": "תאריך" } ], "label.date-range": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "יום" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "מחק דוח" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "מחק צוות" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "מחק משתמש" } ], "label.delete-website": [ @@ -410,25 +410,25 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "תיאור" } ], "label.desktop": [ { "type": 0, - "value": "דסקטופ" + "value": "מחשב שולחני" } ], "label.details": [ { "type": 0, - "value": "Details" + "value": "פרטים" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "מכשיר" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "ישיר" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "מזהה ייחודי" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "לא מכיל" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "לא כולל" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "לא קיים" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "עזיבה" } ], "label.edit": [ @@ -494,19 +494,19 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "ערוך לוח מחוונים" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "ערוך חבר" } ], "label.email": [ { "type": 0, - "value": "Email" + "value": "אימייל" } ], "label.enable-share-url": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "שלב סיום" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "כתובת כניסה" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "אירוע" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "נתוני אירוע" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "שם האירוע" } ], "label.events": [ @@ -554,37 +554,37 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "קיים" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "כתובת יציאה" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "הרחב" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "שקר" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "שדה" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "שדות" } ], "label.filter": [ @@ -608,169 +608,169 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "מסננים" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "קליק ראשון" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "נראה לראשונה" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "משפך" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "הבן את שיעור ההמרה והעזיבה של המשתמשים." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "משפכים" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "מטרה" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "מטרות" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "עקוב אחרי המטרות שלך לצפיות בדף ואירועים." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "גדול מ-" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "גדול או שווה ל-" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "מקובץ" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "שם מארח" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "כולל" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "תובנה" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "תובנות" } ], "label.insights-description": [ { "type": 0, - "value": "Dive deeper into your data by using segments and filters." + "value": "צלול עמוק יותר לנתונים שלך באמצעות פילוחים ומסננים." } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "הוא" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "הוא שקר" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "אינו" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "לא הוגדר" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "הוגדר" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "הוא אמת" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "הצטרף" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "הצטרף לצוות" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "מסע" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "הבן כיצד משתמשים מנווטים באתר שלך." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "מסעות" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "קליק אחרון" } ], "label.last-days": [ @@ -818,53 +818,49 @@ } ], "label.last-months": [ - { - "type": 0, - "value": "Last " - }, { "type": 1, "value": "x" }, { "type": 0, - "value": " months" + "value": " חודשים אחרונים" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "נראה לאחרונה" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "עזוב" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "עזוב צוות" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "פחות מ-" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "פחות או שווה ל-" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "קישורים" } ], "label.login": [ @@ -882,43 +878,43 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "נהל" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "מנהל" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "מקסימום" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "בינוני" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "חבר" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "חברים" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "מינימום" } ], "label.mobile": [ @@ -942,13 +938,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "החשבון שלי" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "האתרים שלי" } ], "label.name": [ @@ -966,7 +962,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "ללא" } ], "label.number-of-records": [ @@ -985,7 +981,7 @@ "value": [ { "type": 0, - "value": "record" + "value": "רשומה" } ] }, @@ -993,7 +989,7 @@ "value": [ { "type": 0, - "value": "records" + "value": "רשומות" } ] } @@ -1012,25 +1008,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "חיפוש אורגני" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "קניות אורגניות" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "רשת חברתית אורגנית" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "וידאו אורגני" } ], "label.os": [ @@ -1042,31 +1038,31 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "אחר" } ], "label.overview": [ { "type": 0, - "value": "Overview" + "value": "סקירה כללית" } ], "label.owner": [ { "type": 0, - "value": "Owner" + "value": "בעלים" } ], "label.page": [ { "type": 0, - "value": "Page" + "value": "דף" } ], "label.page-of": [ { "type": 0, - "value": "Page " + "value": "דף " }, { "type": 1, @@ -1074,7 +1070,7 @@ }, { "type": 0, - "value": " of " + "value": " מתוך " }, { "type": 1, @@ -1102,31 +1098,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "מודעות בתשלום" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "חיפוש בתשלום" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "קניות בתשלום" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "רשת חברתית בתשלום" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "וידאו בתשלום" } ], "label.password": [ @@ -1138,19 +1134,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "נתיב" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "נתיבים" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "פיקסלים" } ], "label.powered-by": [ @@ -1190,31 +1186,31 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "מאפיינים" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "מאפיין" } ], "label.queries": [ { "type": 0, - "value": "Queries" + "value": "שאילתות" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "שאילתה" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "פרמטרי שאילתה" } ], "label.realtime": [ @@ -1226,7 +1222,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "הפניה" } ], "label.referrer": [ @@ -1268,7 +1264,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "נותר" } ], "label.remove": [ @@ -1322,13 +1318,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "הכנסה" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "בדוק את ההכנסות שלך לאורך זמן." } ], "label.role": [ @@ -1352,7 +1348,7 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "מסכים" } ], "label.search": [ @@ -1376,7 +1372,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "בחר מסנן" } ], "label.select-role": [ @@ -1394,13 +1390,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "סשן" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "נתוני סשן" } ], "label.sessions": [ @@ -1418,7 +1414,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "שתף" } ], "label.share-url": [ @@ -1442,19 +1438,19 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "מקורות" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "שלב התחלה" } ], "label.steps": [ { "type": 0, - "value": "Steps" + "value": "שלבים" } ], "label.sum": [ @@ -1472,13 +1468,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "תגית" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "תגיות" } ], "label.team": [ @@ -1520,7 +1516,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "הגדרות צוות" } ], "label.team-view-only": [ @@ -1544,7 +1540,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "תנאים" } ], "label.theme": [ diff --git a/public/intl/messages/hi-IN.json b/public/intl/messages/hi-IN.json index fc0ab36b..437fc433 100644 --- a/public/intl/messages/hi-IN.json +++ b/public/intl/messages/hi-IN.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "बोर्ड जोड़ें" } ], "label.add-description": [ @@ -38,13 +38,13 @@ "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "सदस्य जोड़ें" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "चरण जोड़ें" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "संबद्ध" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "बाद में" } ], "label.all": [ @@ -80,37 +80,37 @@ "label.all-time": [ { "type": 0, - "value": "All time" + "value": "सभी समय" } ], "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "विश्लेषण" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "लागू करें" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "अर्पण" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "देखें कि उपयोगकर्ता आपके विपणन के साथ कैसे जुड़ते हैं और क्या रूपांतरण को प्रेरित करता है।" } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "औसत" } ], "label.back": [ @@ -122,13 +122,13 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "पहले" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "बोर्ड्स" } ], "label.bounce-rate": [ @@ -140,13 +140,13 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "विभाजन" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "ब्राउज़र" } ], "label.browsers": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "अभियान" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "चैनल" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "शहर" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "शहर" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "सभी साफ करें" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "समूह" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "तुलना करें" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "तिथियों की तुलना करें" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "पुष्टि करें" } ], "label.confirm-password": [ @@ -230,43 +230,43 @@ "label.contains": [ { "type": 0, - "value": "Contains" + "value": "शामिल है" } ], "label.content": [ { "type": 0, - "value": "Content" + "value": "सामग्री" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "जारी रखें" } ], "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "रूपांतरण" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "रूपांतरण दर" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "रूपांतरण चरण" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "गिनती" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "देश" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "बनाएँ" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "रिपोर्ट बनाएं" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "टीम बनाएं" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "उपयोगकर्ता बनाएं" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "बनाया गया" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "द्वारा बनाया गया" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "मुद्रा" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "वर्तमान" } ], "label.current-password": [ @@ -350,13 +350,13 @@ "label.data": [ { "type": 0, - "value": "Data" + "value": "डेटा" } ], "label.date": [ { "type": 0, - "value": "Date" + "value": "तिथि" } ], "label.date-range": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "दिन" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "रिपोर्ट हटाएं" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "टीम हटाएं" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "उपयोगकर्ता हटाएं" } ], "label.delete-website": [ @@ -410,7 +410,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "विवरण" } ], "label.desktop": [ @@ -422,13 +422,13 @@ "label.details": [ { "type": 0, - "value": "Details" + "value": "विवरण" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "डिवाइस" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "प्रत्यक्ष" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "अद्वितीय आईडी" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "शामिल नहीं है" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "शामिल नहीं है" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "मौजूद नहीं है" } ], "label.domain": [ @@ -494,19 +494,19 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "डैशबोर्ड संपादित करें" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "सदस्य संपादित करें" } ], "label.email": [ { "type": 0, - "value": "Email" + "value": "ईमेल" } ], "label.enable-share-url": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "अंतिम चरण" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "प्रवेश URL" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "घटना" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "घटना डेटा" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "घटना नाम" } ], "label.events": [ @@ -554,43 +554,43 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "मौजूद है" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "निकास URL" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "विस्तार करें" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "गलत" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "फ़ील्ड" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "फ़ील्ड्स" } ], "label.filter": [ { "type": 0, - "value": "Filter" + "value": "फ़िल्टर" } ], "label.filter-combined": [ @@ -608,181 +608,181 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "फ़िल्टर" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "पहला क्लिक" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "पहली बार देखा गया" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "फनल" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "उपयोगकर्ताओं की रूपांतरण और ड्रॉप-ऑफ दर को समझें।" } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "फनल्स" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "लक्ष्य" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "लक्ष्य" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "पृष्ठदृश्यों और घटनाओं के लिए अपने लक्ष्यों को ट्रैक करें।" } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "से अधिक" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "से अधिक या बराबर" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "समूहित" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "होस्टनाम" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "शामिल है" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "अंतर्दृष्टि" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "अंतर्दृष्टियाँ" } ], "label.insights-description": [ { "type": 0, - "value": "Dive deeper into your data by using segments and filters." + "value": "सेगमेंट और फ़िल्टर का उपयोग करके अपने डेटा में गहराई से जाएं।" } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "है" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "गलत है" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "नहीं है" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "सेट नहीं है" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "सेट है" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "सही है" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "शामिल हों" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "टीम में शामिल हों" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "यात्रा" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "समझें कि उपयोगकर्ता आपकी वेबसाइट पर कैसे नेविगेट करते हैं।" } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "यात्राएँ" } ], "label.language": [ { "type": 0, - "value": "Language" + "value": "भाषा" } ], "label.languages": [ { "type": 0, - "value": "Languages" + "value": "भाषाएँ" } ], "label.laptop": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "अंतिम क्लिक" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "पिछले " }, { "type": 1, @@ -836,43 +836,43 @@ }, { "type": 0, - "value": " months" + "value": " महीने" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "अंतिम बार देखा गया" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "छोड़ें" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "टीम छोड़ें" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "से कम" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "से कम या बराबर" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "लिंक" } ], "label.login": [ @@ -890,43 +890,43 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "प्रबंधित करें" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "प्रबंधक" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "अधिकतम" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "मध्यम" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "सदस्य" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "सदस्यगण" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "न्यूनतम" } ], "label.mobile": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "मॉडल" } ], "label.more": [ @@ -950,13 +950,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "मेरा खाता" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "मेरी वेबसाइट्स" } ], "label.name": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "कोई नहीं" } ], "label.number-of-records": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "ऑर्गेनिक खोज" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "ऑर्गेनिक खरीदारी" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "ऑर्गेनिक सोशल" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "ऑर्गेनिक वीडियो" } ], "label.os": [ @@ -1050,31 +1050,31 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "अन्य" } ], "label.overview": [ { "type": 0, - "value": "Overview" + "value": "सारांश" } ], "label.owner": [ { "type": 0, - "value": "Owner" + "value": "मालिक" } ], "label.page": [ { "type": 0, - "value": "Page" + "value": "पृष्ठ" } ], "label.page-of": [ { "type": 0, - "value": "Page " + "value": "पृष्ठ " }, { "type": 1, @@ -1082,7 +1082,7 @@ }, { "type": 0, - "value": " of " + "value": " का " }, { "type": 1, @@ -1098,7 +1098,7 @@ "label.pageTitle": [ { "type": 0, - "value": "Page title" + "value": "पृष्ठ शीर्षक" } ], "label.pages": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "पेड विज्ञापन" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "पेड खोज" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "पेड खरीदारी" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "पेड सोशल" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "पेड वीडियो" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "पथ" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "पथ" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "पिक्सेल" } ], "label.powered-by": [ @@ -1198,31 +1198,31 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "गुण" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "गुण" } ], "label.queries": [ { "type": 0, - "value": "Queries" + "value": "प्रश्न" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "प्रश्न" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "प्रश्न पैरामीटर" } ], "label.realtime": [ @@ -1234,13 +1234,13 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "संदर्भ" } ], "label.referrer": [ { "type": 0, - "value": "Referrer" + "value": "संदर्भकर्ता" } ], "label.referrers": [ @@ -1258,43 +1258,43 @@ "label.regenerate": [ { "type": 0, - "value": "Regenerate" + "value": "पुनः उत्पन्न करें" } ], "label.region": [ { "type": 0, - "value": "Region" + "value": "क्षेत्र" } ], "label.regions": [ { "type": 0, - "value": "Regions" + "value": "क्षेत्र" } ], "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "शेष" } ], "label.remove": [ { "type": 0, - "value": "Remove" + "value": "हटाएं" } ], "label.remove-member": [ { "type": 0, - "value": "Remove member" + "value": "सदस्य हटाएं" } ], "label.reports": [ { "type": 0, - "value": "प्रतिवेदन" + "value": "रिपोर्ट्स" } ], "label.required": [ @@ -1312,43 +1312,43 @@ "label.reset-website": [ { "type": 0, - "value": "Reset statistics" + "value": "आँकड़े रीसेट करें" } ], "label.retention": [ { "type": 0, - "value": "Retention" + "value": "पुनः आगमन" } ], "label.retention-description": [ { "type": 0, - "value": "Measure your website stickiness by tracking how often users return." + "value": "यह मापें कि उपयोगकर्ता कितनी बार आपकी वेबसाइट पर लौटते हैं।" } ], "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "राजस्व" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "समय के साथ अपने राजस्व को देखें।" } ], "label.role": [ { "type": 0, - "value": "Role" + "value": "भूमिका" } ], "label.run-query": [ { "type": 0, - "value": "Run query" + "value": "प्रश्न चलाएँ" } ], "label.save": [ @@ -1360,61 +1360,61 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "स्क्रीन" } ], "label.search": [ { "type": 0, - "value": "Search" + "value": "खोजें" } ], "label.select": [ { "type": 0, - "value": "Select" + "value": "चुनें" } ], "label.select-date": [ { "type": 0, - "value": "Select date" + "value": "तिथि चुनें" } ], "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "फ़िल्टर चुनें" } ], "label.select-role": [ { "type": 0, - "value": "Select role" + "value": "भूमिका चुनें" } ], "label.select-website": [ { "type": 0, - "value": "Select website" + "value": "वेबसाइट चुनें" } ], "label.session": [ { "type": 0, - "value": "Session" + "value": "सत्र" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "सत्र डेटा" } ], "label.sessions": [ { "type": 0, - "value": "Sessions" + "value": "सत्र" } ], "label.settings": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "साझा करें" } ], "label.share-url": [ @@ -1450,25 +1450,25 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "स्रोत" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "प्रारंभिक चरण" } ], "label.steps": [ { "type": 0, - "value": "Steps" + "value": "चरण" } ], "label.sum": [ { "type": 0, - "value": "Sum" + "value": "योग" } ], "label.tablet": [ @@ -1480,85 +1480,85 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "टैग" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "टैग्स" } ], "label.team": [ { "type": 0, - "value": "Team" + "value": "टीम" } ], "label.team-id": [ { "type": 0, - "value": "Team ID" + "value": "टीम आईडी" } ], "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "टीम प्रबंधक" } ], "label.team-member": [ { "type": 0, - "value": "Team member" + "value": "टीम सदस्य" } ], "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "टीम नाम" } ], "label.team-owner": [ { "type": 0, - "value": "Team owner" + "value": "टीम मालिक" } ], "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "टीम सेटिंग्स" } ], "label.team-view-only": [ { "type": 0, - "value": "Team view only" + "value": "केवल टीम देखें" } ], "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "टीम वेबसाइट्स" } ], "label.teams": [ { "type": 0, - "value": "Teams" + "value": "टीमें" } ], "label.terms": [ { "type": 0, - "value": "Terms" + "value": "शर्तें" } ], "label.theme": [ { "type": 0, - "value": "Theme" + "value": "थीम" } ], "label.this-month": [ diff --git a/public/intl/messages/hr-HR.json b/public/intl/messages/hr-HR.json index ee0cf8ed..0b0e8b7d 100644 --- a/public/intl/messages/hr-HR.json +++ b/public/intl/messages/hr-HR.json @@ -2,49 +2,49 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Pristupni kod" } ], "label.actions": [ { "type": 0, - "value": "Actions" + "value": "Akcije" } ], "label.activity": [ { "type": 0, - "value": "Activity log" + "value": "Dnevnik aktivnosti" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "Dodaj" } ], "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Dodaj ploču" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Dodaj opis" } ], "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Dodaj člana" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Dodaj korak" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partner" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "Nakon" } ], "label.all": [ @@ -86,31 +86,31 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analitika" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Primijeni" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atribucija" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Pogledajte kako korisnici komuniciraju s vašim marketingom i što dovodi do konverzija." } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Prosjek" } ], "label.back": [ @@ -122,43 +122,43 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Prije" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Ploče" } ], "label.bounce-rate": [ { "type": 0, - "value": "Bounce rate" + "value": "Stopa napuštanja" } ], "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Raspad" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "Preglednik" } ], "label.browsers": [ { "type": 0, - "value": "Browsers" + "value": "Preglednici" } ], "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampanje" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanali" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Gradovi" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "Grad" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Očisti sve" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohorta" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Usporedi" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Usporedi datume" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Potvrdi" } ], "label.confirm-password": [ @@ -236,37 +236,37 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Sadržaj" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "Nastavi" } ], "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konverzija" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Stopa konverzije" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Korak konverzije" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Broj" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Država" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "Kreiraj" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Kreiraj izvještaj" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Kreiraj tim" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Kreiraj korisnika" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Kreirano" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Kreirao" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Valuta" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Trenutno" } ], "label.current-password": [ @@ -350,13 +350,13 @@ "label.data": [ { "type": 0, - "value": "Data" + "value": "Podaci" } ], "label.date": [ { "type": 0, - "value": "Date" + "value": "Datum" } ], "label.date-range": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Dan" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Obriši izvještaj" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Obriši tim" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Obriši korisnika" } ], "label.delete-website": [ @@ -410,37 +410,37 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Opis" } ], "label.desktop": [ { "type": 0, - "value": "Desktop" + "value": "Stolno računalo" } ], "label.details": [ { "type": 0, - "value": "Details" + "value": "Detalji" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "Uređaj" } ], "label.devices": [ { "type": 0, - "value": "Devices" + "value": "Uređaji" } ], "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Direktno" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Jedinstveni ID" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Ne sadrži" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Ne uključuje" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Ne postoji" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Odlazak" } ], "label.edit": [ @@ -494,19 +494,19 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Uredi nadzornu ploču" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Uredi člana" } ], "label.email": [ { "type": 0, - "value": "Email" + "value": "E-mail" } ], "label.enable-share-url": [ @@ -518,19 +518,19 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Završni korak" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "Ulazni URL" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Događaj" } ], "label.event-data": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Naziv događaja" } ], "label.events": [ @@ -554,37 +554,37 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Postoji" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "Izlazni URL" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Proširi" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Netočno" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Polje" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Polja" } ], "label.filter": [ @@ -608,169 +608,169 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Filteri" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Prvi klik" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Prvi put viđeno" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Lijevak" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "Razumite stopu konverzije i odlaska korisnika." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Ljevci" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Cilj" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Ciljevi" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Pratite svoje ciljeve za prikaze stranica i događaje." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Veće od" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Veće ili jednako" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Grupirano" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Naziv hosta" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Uključuje" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Uvid" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Uvidi" } ], "label.insights-description": [ { "type": 0, - "value": "Dive deeper into your data by using segments and filters." + "value": "Dublje analizirajte svoje podatke pomoću segmenata i filtera." } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "Je" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Je netočno" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Nije" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Nije postavljeno" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Postavljeno" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Je točno" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Pridruži se" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Pridruži se timu" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Putovanje" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Razumite kako korisnici navigiraju vašom web stranicom." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Putovanja" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Zadnji klik" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Zadnjih " }, { "type": 1, @@ -836,43 +836,43 @@ }, { "type": 0, - "value": " months" + "value": " mjeseci" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Zadnji put viđeno" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Napusti" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Napusti tim" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Manje od" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Manje ili jednako" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "Poveznice" } ], "label.login": [ @@ -890,43 +890,43 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "Upravljaj" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Upravitelj" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "Maksimum" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Srednje" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "Član" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Članovi" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "Minimum" } ], "label.mobile": [ @@ -950,13 +950,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "Moj račun" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Moje web stranice" } ], "label.name": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "Ništa" + "value": "Nijedan" } ], "label.number-of-records": [ @@ -993,7 +993,7 @@ "value": [ { "type": 0, - "value": "record" + "value": "zapis" } ] }, @@ -1001,7 +1001,7 @@ "value": [ { "type": 0, - "value": "records" + "value": "zapisa" } ] } @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organsko pretraživanje" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organska kupovina" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organska društvena mreža" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organski videozapis" } ], "label.os": [ @@ -1050,13 +1050,13 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Ostalo" } ], "label.overview": [ { "type": 0, - "value": "Overview" + "value": "Pregled" } ], "label.owner": [ @@ -1068,13 +1068,13 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Stranica" } ], "label.page-of": [ { "type": 0, - "value": "Page " + "value": "Stranica " }, { "type": 1, @@ -1082,7 +1082,7 @@ }, { "type": 0, - "value": " of " + "value": " od " }, { "type": 1, @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Plaćeni oglasi" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Plaćeno pretraživanje" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Plaćena kupovina" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Plaćena društvena mreža" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Plaćeni videozapis" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Putanja" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Putanje" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pikseli" } ], "label.powered-by": [ @@ -1198,31 +1198,31 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Svojstva" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Svojstvo" } ], "label.queries": [ { "type": 0, - "value": "Queries" + "value": "Upiti" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "Upit" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "Parametri upita" } ], "label.realtime": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Preporuka" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Preostalo" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Prihod" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Pogledajte svoj prihod tijekom vremena." } ], "label.role": [ @@ -1360,7 +1360,7 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "Ekrani" } ], "label.search": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Odaberi filter" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Sesija" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Podaci sesije" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Podijeli" } ], "label.share-url": [ @@ -1450,19 +1450,19 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Izvori" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "Početni korak" } ], "label.steps": [ { "type": 0, - "value": "Steps" + "value": "Koraci" } ], "label.sum": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Oznaka" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Oznake" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Postavke tima" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Pojmovi" } ], "label.theme": [ diff --git a/public/intl/messages/hu-HU.json b/public/intl/messages/hu-HU.json index f5a5c3a6..be086217 100644 --- a/public/intl/messages/hu-HU.json +++ b/public/intl/messages/hu-HU.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Hozzáférési kód" } ], "label.actions": [ @@ -14,37 +14,37 @@ "label.activity": [ { "type": 0, - "value": "Activity log" + "value": "Tevékenységnapló" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "Hozzáadás" } ], "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Tábla hozzáadása" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Leírás hozzáadása" } ], "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Tag hozzáadása" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Lépés hozzáadása" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partner" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "Után" } ], "label.all": [ @@ -80,37 +80,37 @@ "label.all-time": [ { "type": 0, - "value": "All time" + "value": "Minden időszak" } ], "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analitika" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Alkalmaz" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Attribúció" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Nézze meg, hogyan lépnek kapcsolatba a felhasználók a marketingjével, és mi vezet konverzióhoz." } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Átlag" } ], "label.back": [ @@ -122,13 +122,13 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Előtt" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Táblák" } ], "label.bounce-rate": [ @@ -140,13 +140,13 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Bontás" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "Böngésző" } ], "label.browsers": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampányok" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Csatornák" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Városok" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "Város" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Összes törlése" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohorsz" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Összehasonlít" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Dátumok összehasonlítása" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Megerősít" } ], "label.confirm-password": [ @@ -236,37 +236,37 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Tartalom" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "Folytatás" } ], "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konverzió" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Konverziós arány" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Konverziós lépés" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Darabszám" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Ország" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "Létrehozás" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Jelentés létrehozása" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Csapat létrehozása" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Felhasználó létrehozása" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Létrehozva" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Létrehozta" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Pénznem" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Jelenlegi" } ], "label.current-password": [ @@ -350,13 +350,13 @@ "label.data": [ { "type": 0, - "value": "Data" + "value": "Adat" } ], "label.date": [ { "type": 0, - "value": "Date" + "value": "Dátum" } ], "label.date-range": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Nap" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Jelentés törlése" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Csapat törlése" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Felhasználó törlése" } ], "label.delete-website": [ @@ -410,7 +410,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Leírás" } ], "label.desktop": [ @@ -422,13 +422,13 @@ "label.details": [ { "type": 0, - "value": "Details" + "value": "Részletek" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "Eszköz" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Közvetlen" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Egyedi azonosító" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Nem tartalmazza" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Nem tartalmazza" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Nem létezik" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Lemorzsolódás" } ], "label.edit": [ @@ -494,19 +494,19 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Irányítópult szerkesztése" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Tag szerkesztése" } ], "label.email": [ { "type": 0, - "value": "Email" + "value": "E-mail" } ], "label.enable-share-url": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Befejező lépés" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "Belépési URL" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Esemény" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Eseményadatok" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Esemény neve" } ], "label.events": [ @@ -554,37 +554,37 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Létezik" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "Kilépési URL" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Kibontás" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Hamis" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Mező" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Mezők" } ], "label.filter": [ @@ -608,169 +608,169 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Szűrők" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Első kattintás" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Első megtekintés" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Tölcsér" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "Értse meg a felhasználók konverziós és lemorzsolódási arányát." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Tölcsérek" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Cél" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Célok" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Kövesse nyomon a céljait oldalmegtekintések és események alapján." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Nagyobb mint" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Nagyobb vagy egyenlő" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Csoportosítva" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Hosztnév" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Tartalmazza" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Betekintés" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Betekintések" } ], "label.insights-description": [ { "type": 0, - "value": "Dive deeper into your data by using segments and filters." + "value": "Merüljön el mélyebben az adataiban szegmensek és szűrők használatával." } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "Az" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Hamis" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Nem az" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Nincs beállítva" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Beállítva" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Igaz" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Csatlakozás" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Csatlakozás a csapathoz" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Út" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Értse meg, hogyan navigálnak a felhasználók a weboldalán." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Utak" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Utolsó kattintás" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Utolsó " }, { "type": 1, @@ -836,43 +836,43 @@ }, { "type": 0, - "value": " months" + "value": " hónap" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Utoljára látva" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Kilépés" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Csapat elhagyása" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Kevesebb mint" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Kevesebb vagy egyenlő" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "Linkek" } ], "label.login": [ @@ -890,43 +890,43 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "Kezelés" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Menedzser" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "Maximum" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Közepes" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "Tag" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Tagok" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "Minimum" } ], "label.mobile": [ @@ -950,13 +950,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "Saját fiók" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Saját weboldalak" } ], "label.name": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Nincs" } ], "label.number-of-records": [ @@ -993,7 +993,7 @@ "value": [ { "type": 0, - "value": "record" + "value": "rekord" } ] }, @@ -1001,7 +1001,7 @@ "value": [ { "type": 0, - "value": "records" + "value": "rekord" } ] } @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organikus keresés" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organikus vásárlás" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organikus közösségi" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organikus videó" } ], "label.os": [ @@ -1050,31 +1050,31 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Egyéb" } ], "label.overview": [ { "type": 0, - "value": "Overview" + "value": "Áttekintés" } ], "label.owner": [ { "type": 0, - "value": "Owner" + "value": "Tulajdonos" } ], "label.page": [ { "type": 0, - "value": "Page" + "value": "Oldal" } ], "label.page-of": [ { "type": 0, - "value": "Page " + "value": "Oldal " }, { "type": 1, @@ -1082,7 +1082,7 @@ }, { "type": 0, - "value": " of " + "value": " / " }, { "type": 1, @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Fizetett hirdetések" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Fizetett keresés" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Fizetett vásárlás" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Fizetett közösségi" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Fizetett videó" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Útvonal" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Útvonalak" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pixelek" } ], "label.powered-by": [ @@ -1198,31 +1198,31 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Tulajdonságok" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Tulajdonság" } ], "label.queries": [ { "type": 0, - "value": "Queries" + "value": "Lekérdezések" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "Lekérdezés" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "Lekérdezési paraméterek" } ], "label.realtime": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Hivatkozás" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Hátralévő" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Bevétel" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Tekintse meg bevételeit az idő múlásával." } ], "label.role": [ @@ -1360,7 +1360,7 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "Képernyők" } ], "label.search": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Szűrő kiválasztása" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Munkamenet" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Munkamenet adatai" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Megosztás" } ], "label.share-url": [ @@ -1450,19 +1450,19 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Források" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "Kezdő lépés" } ], "label.steps": [ { "type": 0, - "value": "Steps" + "value": "Lépések" } ], "label.sum": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Címke" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Címkék" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Csapat beállításai" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Kifejezések" } ], "label.theme": [ diff --git a/public/intl/messages/id-ID.json b/public/intl/messages/id-ID.json index 7db832e9..06c9e186 100644 --- a/public/intl/messages/id-ID.json +++ b/public/intl/messages/id-ID.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Tambah papan" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Afiliasi" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Terapkan" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atribusi" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Lihat bagaimana pengguna berinteraksi dengan pemasaran Anda dan apa yang mendorong konversi." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Papan" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampanye" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Saluran" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kelompok" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Bandingkan tanggal" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Konten" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konversi" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Tingkat konversi" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Langkah konversi" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Mata uang" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Langsung" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "ID unik" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Tidak termasuk" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Tidak ada" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Nama peristiwa" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Ada" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Perluas" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Klik pertama" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Corong" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Dikelompokkan" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Nama host" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Termasuk" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Wawasan" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Salah" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Benar" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Perjalanan" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Klik terakhir" } ], "label.last-days": [ @@ -860,7 +860,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Tautan" } ], "label.login": [ @@ -884,19 +884,19 @@ "label.manager": [ { "type": 0, - "value": "Pengelola" + "value": "Manajer" } ], "label.max": [ { "type": 0, - "value": "Maks" + "value": "Maksimum" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Sedang" } ], "label.member": [ @@ -914,7 +914,7 @@ "label.min": [ { "type": 0, - "value": "Min" + "value": "Minimum" } ], "label.mobile": [ @@ -981,7 +981,7 @@ "value": [ { "type": 0, - "value": "record" + "value": "catatan" } ] }, @@ -989,7 +989,7 @@ "value": [ { "type": 0, - "value": "records" + "value": "catatan" } ] } @@ -1008,25 +1008,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Pencarian organik" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Belanja organik" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Sosial organik" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Video organik" } ], "label.os": [ @@ -1038,7 +1038,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Lainnya" } ], "label.overview": [ @@ -1056,7 +1056,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Halaman" } ], "label.page-of": [ @@ -1098,31 +1098,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Iklan berbayar" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Pencarian berbayar" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Belanja berbayar" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Sosial berbayar" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Video berbayar" } ], "label.password": [ @@ -1134,19 +1134,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Jalur" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Jalur" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Piksel" } ], "label.powered-by": [ @@ -1186,31 +1186,31 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Properti" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Properti" } ], "label.queries": [ { "type": 0, - "value": "Queries" + "value": "Kueri" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "Kueri" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "Parameter kueri" } ], "label.realtime": [ @@ -1222,7 +1222,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Rujukan" } ], "label.referrer": [ @@ -1264,7 +1264,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Tersisa" } ], "label.remove": [ @@ -1372,7 +1372,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Pilih filter" } ], "label.select-role": [ @@ -1396,7 +1396,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Data sesi" } ], "label.sessions": [ @@ -1414,7 +1414,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Bagikan" } ], "label.share-url": [ @@ -1438,7 +1438,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Sumber" } ], "label.start-step": [ @@ -1474,7 +1474,7 @@ "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Tag" } ], "label.team": [ @@ -1516,7 +1516,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Pengaturan tim" } ], "label.team-view-only": [ @@ -1540,7 +1540,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Ketentuan" } ], "label.theme": [ diff --git a/public/intl/messages/it-IT.json b/public/intl/messages/it-IT.json index d9448d06..a8640bd7 100644 --- a/public/intl/messages/it-IT.json +++ b/public/intl/messages/it-IT.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Codice di accesso" } ], "label.actions": [ @@ -14,37 +14,37 @@ "label.activity": [ { "type": 0, - "value": "Activity log" + "value": "Registro attività" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "Aggiungi" } ], "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Aggiungi bacheca" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Aggiungi descrizione" } ], "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Aggiungi membro" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Aggiungi passaggio" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Affiliato" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "Dopo" } ], "label.all": [ @@ -86,31 +86,31 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analitica" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Applica" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Attribuzione" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Scopri come gli utenti interagiscono con il tuo marketing e cosa genera conversioni." } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Media" } ], "label.back": [ @@ -122,13 +122,13 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Prima" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Bacheche" } ], "label.bounce-rate": [ @@ -140,7 +140,7 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Dettaglio" } ], "label.browser": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Campagne" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Canali" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Città" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "Città" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Cancella tutto" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Coorte" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Confronta" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Confronta date" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Conferma" } ], "label.confirm-password": [ @@ -236,37 +236,37 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Contenuto" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "Continua" } ], "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Conversione" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Tasso di conversione" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Passaggio di conversione" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Conteggio" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Paese" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "Crea" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Crea rapporto" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Crea team" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Crea utente" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Creato" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Creato da" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Valuta" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Attuale" } ], "label.current-password": [ @@ -350,13 +350,13 @@ "label.data": [ { "type": 0, - "value": "Data" + "value": "Dati" } ], "label.date": [ { "type": 0, - "value": "Date" + "value": "Data" } ], "label.date-range": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Giorno" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Elimina rapporto" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Elimina team" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Elimina utente" } ], "label.delete-website": [ @@ -410,7 +410,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Descrizione" } ], "label.desktop": [ @@ -422,13 +422,13 @@ "label.details": [ { "type": 0, - "value": "Details" + "value": "Dettagli" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "Dispositivo" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Diretto" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "ID distinto" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Non contiene" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Non include" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Non esiste" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Abbandono" } ], "label.edit": [ @@ -494,13 +494,13 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Modifica pannello di controllo" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Modifica membro" } ], "label.email": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Passaggio finale" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "URL di ingresso" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Evento" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Dati evento" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Nome evento" } ], "label.events": [ @@ -554,37 +554,37 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Esiste" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "URL di uscita" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Espandi" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Falso" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Campo" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Campi" } ], "label.filter": [ @@ -608,19 +608,19 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Filtri" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Primo clic" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Prima visualizzazione" } ], "label.funnel": [ @@ -632,145 +632,145 @@ "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "Comprendi il tasso di conversione e di abbandono degli utenti." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Funnel" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Obiettivo" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Obiettivi" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Tieni traccia dei tuoi obiettivi per visualizzazioni di pagina ed eventi." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Maggiore di" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Maggiore o uguale a" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Raggruppato" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Nome host" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Include" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Approfondimento" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Approfondimenti" } ], "label.insights-description": [ { "type": 0, - "value": "Dive deeper into your data by using segments and filters." + "value": "Analizza più a fondo i tuoi dati utilizzando segmenti e filtri." } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "È" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "È falso" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Non è" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Non impostato" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Impostato" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "È vero" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Unisciti" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Unisciti al team" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Percorso" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Comprendi come gli utenti navigano nel tuo sito web." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Percorsi" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Ultimo clic" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Ultimi " }, { "type": 1, @@ -836,43 +836,43 @@ }, { "type": 0, - "value": " months" + "value": " mesi" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Ultima visualizzazione" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Lascia" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Lascia il team" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Meno di" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Meno o uguale a" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "Link" } ], "label.login": [ @@ -890,7 +890,7 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "Gestisci" } ], "label.manager": [ @@ -902,31 +902,31 @@ "label.max": [ { "type": 0, - "value": "Max" + "value": "Massimo" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Medio" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "Membro" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Membri" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "Minimo" } ], "label.mobile": [ @@ -950,13 +950,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "Il mio account" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "I miei siti" } ], "label.name": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Nessuno" } ], "label.number-of-records": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Ricerca organica" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Acquisto organico" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Social organico" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Video organico" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Altro" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Pagina" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Annunci a pagamento" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Ricerca a pagamento" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Acquisto a pagamento" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Social a pagamento" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Video a pagamento" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Percorso" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Percorsi" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pixel" } ], "label.powered-by": [ @@ -1198,19 +1198,19 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Proprietà" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Proprietà" } ], "label.queries": [ { "type": 0, - "value": "Queries" + "value": "Query" } ], "label.query": [ @@ -1222,7 +1222,7 @@ "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "Parametri query" } ], "label.realtime": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Referente" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Rimanente" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Ricavi" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Consulta i tuoi ricavi nel tempo." } ], "label.role": [ @@ -1360,7 +1360,7 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "Schermi" } ], "label.search": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Seleziona filtro" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Dati sessione" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Condividi" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Fonti" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Etichetta" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Etichette" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Impostazioni team" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Termini" } ], "label.theme": [ diff --git a/public/intl/messages/ja-JP.json b/public/intl/messages/ja-JP.json index dbbd415b..9c846ba0 100644 --- a/public/intl/messages/ja-JP.json +++ b/public/intl/messages/ja-JP.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "ボードを追加" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "アフィリエイト" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "適用" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "アトリビューション" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "ユーザーがあなたのマーケティングにどのように関与し、何がコンバージョンを促進するかを確認します。" } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "ボード" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "キャンペーン" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "チャンネル" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "コホート" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "日付を比較" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "コンテンツ" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "コンバージョン" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "コンバージョン率" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "コンバージョンステップ" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "通貨" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "ダイレクト" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "識別ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "含まない" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "存在しない" } ], "label.domain": [ @@ -506,7 +506,7 @@ "label.email": [ { "type": 0, - "value": "Email" + "value": "メール" } ], "label.enable-share-url": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "イベント名" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "存在する" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "展開" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "最初のクリック" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "ファネル" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "グループ化" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "ホスト名" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "含む" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "インサイト" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "偽である" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "真である" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "ジャーニー" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "最後のクリック" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "リンク" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "メディア" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "モデル" } ], "label.more": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "オーガニック検索" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "オーガニックショッピング" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "オーガニックソーシャル" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "オーガニックビデオ" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "その他" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "ページ" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "有料広告" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "有料検索" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "有料ショッピング" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "有料ソーシャル" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "有料ビデオ" } ], "label.password": [ @@ -1158,7 +1158,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "ピクセル" } ], "label.powered-by": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "残り" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "フィルターを選択" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "セッションデータ" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "共有" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "ソース" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "タグ" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "タグ" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "チーム設定" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "利用規約" } ], "label.theme": [ diff --git a/public/intl/messages/km-KH.json b/public/intl/messages/km-KH.json index 23c062a5..eb7cd70f 100644 --- a/public/intl/messages/km-KH.json +++ b/public/intl/messages/km-KH.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "កូដចូលប្រើ" } ], "label.actions": [ @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "បន្ថែមក្តារ" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "ដៃគូ" } ], "label.after": [ @@ -86,25 +86,25 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "វិភាគ" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "អនុវត្ត" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "ការបញ្ជាក់" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "មើលថាប្រើប្រាស់របស់អ្នកធ្វើអ្វីជាមួយទីផ្សាររបស់អ្នក និងអ្វីជាហេតុបណ្តាលឲ្យមានការបម្លែង។" } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "ក្តារ" } ], "label.bounce-rate": [ @@ -140,13 +140,13 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "បំបែកលម្អិត" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "កម្មវិធីរុករក" } ], "label.browsers": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "យុទ្ធនាការ" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "ឆានែល" } ], "label.cities": [ @@ -194,13 +194,13 @@ "label.clear-all": [ { "type": 0, - "value": "លុបទាំងអស់" + "value": "លុបចេញទាំងអស់" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "ក្រុម" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "ប្រៀបធៀបទិន្នន័យថ្ងៃខែ" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "មាតិកា" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "ការបម្លែង" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "អត្រាបម្លែង" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "ជំហានបម្លែង" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "រូបិយប័ណ្ណ" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "ផ្ទាល់" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "លេខសម្គាល់ពិសេស" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "មិនរួមបញ្ចូល" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "មិនមានទេ" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "ឈ្មោះព្រឹត្តិការណ៍" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "មាន" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "ពង្រីក" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "ចុចដំបូង" } ], "label.first-seen": [ @@ -626,7 +626,7 @@ "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "ផ្លូវបង្ហាញ" } ], "label.funnel-description": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "ផ្លូវបង្ហាញ" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "បានដាក់ជាក្រុម" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "ឈ្មោះម៉ាស៊ីន" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "រួមបញ្ចូល" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "ការយល់ដឹង" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "មិនពិត" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "ពិត" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "ដំណើរ" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "ចុចចុងក្រោយ" } ], "label.last-days": [ @@ -860,7 +860,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "តំណភ្ជាប់" } ], "label.login": [ @@ -896,7 +896,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "មធ្យម" } ], "label.member": [ @@ -926,7 +926,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "ម៉ូដែល" } ], "label.more": [ @@ -962,7 +962,7 @@ "label.none": [ { "type": 0, - "value": "មិនមាន" + "value": "គ្មាន" } ], "label.number-of-records": [ @@ -1008,25 +1008,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "ស្វែងរកធម្មជាតិ" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "ការទិញធម្មជាតិ" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "សង្គមធម្មជាតិ" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "វីដេអូធម្មជាតិ" } ], "label.os": [ @@ -1038,7 +1038,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "ផ្សេងទៀត" } ], "label.overview": [ @@ -1056,7 +1056,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "ទំព័រ" } ], "label.page-of": [ @@ -1098,31 +1098,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "ផ្សាយពាណិជ្ជកម្មបង់ប្រាក់" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "ស្វែងរកបង់ប្រាក់" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "ទិញបង់ប្រាក់" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "សង្គមបង់ប្រាក់" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "វីដេអូបង់ប្រាក់" } ], "label.password": [ @@ -1146,7 +1146,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "ភីកសែល" } ], "label.powered-by": [ @@ -1186,13 +1186,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "លក្ខណៈពិសេស" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "លក្ខណៈពិសេស" } ], "label.queries": [ @@ -1222,7 +1222,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "ការបញ្ជូន" } ], "label.referrer": [ @@ -1264,7 +1264,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "នៅសល់" } ], "label.remove": [ @@ -1300,7 +1300,21 @@ "label.reset-website": [ { "type": 0, - "value": "កំណត់ស្ថិតិឡើងវិញ" + "value": "ដើម្បីកែគេហទំព័រនេះឡើងវិញ សូមសរសេរ " + }, + { + "type": 1, + "value": "confirmation" + }, + { + "type": 0, + "value": " នៅក្នុងប្រអប់ខាងក្រោមដើម្បីបញ្ជាក់។" + } + ], + "label.reset-website-warning": [ + { + "type": 0, + "value": "ស្ថិតិទាំងអស់សម្រាប់គេហទំព័រនេះនឹងត្រូវបានលុប ប៉ុន្តែកូដតាមដានរបស់អ្នកនឹងនៅដដែល។" } ], "label.retention": [ @@ -1372,7 +1386,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "ជ្រើសរើសតម្រង" } ], "label.select-role": [ @@ -1396,7 +1410,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "ទិន្នន័យសម័យ" } ], "label.sessions": [ @@ -1414,7 +1428,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "ចែករំលែក" } ], "label.share-url": [ @@ -1438,7 +1452,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "ប្រភព" } ], "label.start-step": [ @@ -1468,13 +1482,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "ស្លាក" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "ស្លាក" } ], "label.team": [ @@ -1516,7 +1530,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "ការកំណត់ក្រុម" } ], "label.team-view-only": [ @@ -1540,7 +1554,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "លក្ខខណ្ឌ" } ], "label.theme": [ diff --git a/public/intl/messages/ko-KR.json b/public/intl/messages/ko-KR.json index 3819a6d2..638e60f2 100644 --- a/public/intl/messages/ko-KR.json +++ b/public/intl/messages/ko-KR.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "보드 추가" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "제휴사" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "적용" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "기여도" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "사용자가 마케팅에 어떻게 반응하고 전환을 유도하는지 확인하세요." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "보드" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "캠페인" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "채널" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "코호트" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "날짜 비교" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "콘텐츠" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "전환" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "전환율" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "전환 단계" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "통화" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "직접" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "고유 ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "포함하지 않음" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "존재하지 않음" } ], "label.domain": [ @@ -506,7 +506,7 @@ "label.email": [ { "type": 0, - "value": "Email" + "value": "이메일" } ], "label.enable-share-url": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "이벤트 이름" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "존재함" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "확장" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "첫 클릭" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "퍼널" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "그룹화됨" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "호스트명" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "포함" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "인사이트" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "거짓임" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "참임" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "여정" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "마지막 클릭" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "링크" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "미디엄" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "모델" } ], "label.more": [ @@ -996,25 +996,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "자연 검색" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "자연 쇼핑" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "자연 소셜" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "자연 비디오" } ], "label.os": [ @@ -1026,7 +1026,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "기타" } ], "label.overview": [ @@ -1044,7 +1044,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "페이지" } ], "label.page-of": [ @@ -1086,31 +1086,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "유료 광고" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "유료 검색" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "유료 쇼핑" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "유료 소셜" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "유료 비디오" } ], "label.password": [ @@ -1134,7 +1134,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "픽셀" } ], "label.powered-by": [ @@ -1252,7 +1252,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "남음" } ], "label.remove": [ @@ -1360,7 +1360,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "필터 선택" } ], "label.select-role": [ @@ -1384,7 +1384,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "세션 데이터" } ], "label.sessions": [ @@ -1402,7 +1402,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "공유" } ], "label.share-url": [ @@ -1426,7 +1426,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "소스" } ], "label.start-step": [ @@ -1456,13 +1456,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "태그" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "태그" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "팀 설정" } ], "label.team-view-only": [ @@ -1528,7 +1528,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "약관" } ], "label.theme": [ diff --git a/public/intl/messages/lt-LT.json b/public/intl/messages/lt-LT.json index c733d5e6..6ba52cf4 100644 --- a/public/intl/messages/lt-LT.json +++ b/public/intl/messages/lt-LT.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Pridėti lentą" } ], "label.add-description": [ @@ -44,7 +44,7 @@ "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Pridėti žingsnį" } ], "label.add-website": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partneris" } ], "label.after": [ @@ -86,25 +86,25 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analitika" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Taikyti" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Priskyrimas" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Žiūrėkite, kaip naudotojai įsitraukia į jūsų rinkodarą ir kas lemia konversijas." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Lentos" } ], "label.bounce-rate": [ @@ -140,7 +140,7 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Išskaidymas" } ], "label.browser": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampanijos" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanalai" } ], "label.cities": [ @@ -200,19 +200,19 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohorta" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Palyginti" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Palyginti datas" } ], "label.confirm": [ @@ -230,43 +230,43 @@ "label.contains": [ { "type": 0, - "value": "Contains" + "value": "Turi" } ], "label.content": [ { "type": 0, - "value": "Content" + "value": "Turinys" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "Tęsti" } ], "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konversija" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Konversijos rodiklis" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Konversijos žingsnis" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Skaičius" } ], "label.countries": [ @@ -308,25 +308,25 @@ "label.created": [ { "type": 0, - "value": "Created" + "value": "Sukurta" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Sukūrė" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Valiuta" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Dabartinis" } ], "label.current-password": [ @@ -416,7 +416,7 @@ "label.desktop": [ { "type": 0, - "value": "Desktop" + "value": "Stalinis kompiuteris" } ], "label.details": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Tiesioginis" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Unikalus ID" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Neturi" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Neįtraukia" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Neegzistuoja" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Atsitraukimas" } ], "label.edit": [ @@ -506,7 +506,7 @@ "label.email": [ { "type": 0, - "value": "Email" + "value": "El. paštas" } ], "label.enable-share-url": [ @@ -518,13 +518,13 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Paskutinis žingsnis" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "Įėjimo URL" } ], "label.event": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Įvykio pavadinimas" } ], "label.events": [ @@ -554,25 +554,25 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Egzistuoja" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "Išėjimo URL" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Išplėsti" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Netiesa" } ], "label.field": [ @@ -614,85 +614,85 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Pirmas paspaudimas" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Pirmą kartą matyta" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Piltuvas" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "Supraskite naudotojų konversijos ir atsitraukimo rodiklius." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Piltuvai" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Tikslas" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Tikslai" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Sekite savo tikslus puslapių peržiūroms ir įvykiams." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Daugiau nei" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Daugiau arba lygu" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Grupuota" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Pagrindinis kompiuteris" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Įtraukia" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Įžvalga" } ], "label.insights": [ @@ -710,37 +710,37 @@ "label.is": [ { "type": 0, - "value": "Is" + "value": "Yra" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Yra netiesa" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Nėra" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Nenurodyta" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Nustatyta" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Yra tiesa" } ], "label.join": [ @@ -758,19 +758,19 @@ "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Kelionė" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Sužinokite, kaip naudotojai naršo jūsų svetainėje." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Kelionės" } ], "label.language": [ @@ -788,13 +788,13 @@ "label.laptop": [ { "type": 0, - "value": "Laptop" + "value": "Nešiojamas kompiuteris" } ], "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Paskutinis paspaudimas" } ], "label.last-days": [ @@ -933,7 +933,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Paskutiniai " }, { "type": 1, @@ -941,13 +941,13 @@ }, { "type": 0, - "value": " months" + "value": " mėnesiai" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Paskutinį kartą matyta" } ], "label.leave": [ @@ -965,19 +965,19 @@ "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Mažiau nei" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Mažiau arba lygu" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "Nuorodos" } ], "label.login": [ @@ -1001,19 +1001,19 @@ "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Vadovas" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "Maksimumas" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Vidutinis" } ], "label.member": [ @@ -1031,7 +1031,7 @@ "label.min": [ { "type": 0, - "value": "Min" + "value": "Minimumas" } ], "label.mobile": [ @@ -1043,7 +1043,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Modelis" } ], "label.more": [ @@ -1079,7 +1079,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Nėra" } ], "label.number-of-records": [ @@ -1125,25 +1125,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organinė paieška" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organinis apsipirkimas" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organinis socialinis" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organinis vaizdo įrašas" } ], "label.os": [ @@ -1155,7 +1155,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Kita" } ], "label.overview": [ @@ -1173,7 +1173,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Puslapis" } ], "label.page-of": [ @@ -1215,31 +1215,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Mokama reklama" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Mokama paieška" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Mokamas apsipirkimas" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Mokamas socialinis" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Mokamas vaizdo įrašas" } ], "label.password": [ @@ -1251,19 +1251,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Kelias" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Keliai" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pikseliai" } ], "label.powered-by": [ @@ -1279,19 +1279,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Ankstesnis" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Ankstesnis laikotarpis" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Ankstesni metai" } ], "label.profile": [ @@ -1303,13 +1303,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Savybės" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Savybė" } ], "label.queries": [ @@ -1339,7 +1339,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Persiuntimas" } ], "label.referrer": [ @@ -1363,7 +1363,7 @@ "label.regenerate": [ { "type": 0, - "value": "Regenerate" + "value": "Sugeneruoti iš naujo" } ], "label.region": [ @@ -1381,7 +1381,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Likę" } ], "label.remove": [ @@ -1423,37 +1423,37 @@ "label.retention": [ { "type": 0, - "value": "Retention" + "value": "Išlaikymas" } ], "label.retention-description": [ { "type": 0, - "value": "Measure your website stickiness by tracking how often users return." + "value": "Išmatuokite, kaip dažnai naudotojai grįžta į jūsų svetainę." } ], "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Pajamos" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Peržiūrėkite savo pajamas laikui bėgant." } ], "label.role": [ { "type": 0, - "value": "Rolė" + "value": "Vaidmuo" } ], "label.run-query": [ { "type": 0, - "value": "Run query" + "value": "Vykdyti užklausą" } ], "label.save": [ @@ -1477,7 +1477,7 @@ "label.select": [ { "type": 0, - "value": "Select" + "value": "Pasirinkti" } ], "label.select-date": [ @@ -1489,7 +1489,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Pasirinkti filtrą" } ], "label.select-role": [ @@ -1507,13 +1507,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Sesija" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Sesijos duomenys" } ], "label.sessions": [ @@ -1531,7 +1531,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Dalintis" } ], "label.share-url": [ @@ -1555,19 +1555,19 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Šaltiniai" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "Pradžios žingsnis" } ], "label.steps": [ { "type": 0, - "value": "Steps" + "value": "Žingsniai" } ], "label.sum": [ @@ -1585,13 +1585,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Žyma" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Žymos" } ], "label.team": [ @@ -1609,7 +1609,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Komandos vadovas" } ], "label.team-member": [ @@ -1633,19 +1633,19 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Komandos nustatymai" } ], "label.team-view-only": [ { "type": 0, - "value": "Team view only" + "value": "Tik peržiūra" } ], "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "Komandos svetainės" } ], "label.teams": [ @@ -1657,7 +1657,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Sąlygos" } ], "label.theme": [ diff --git a/public/intl/messages/mn-MN.json b/public/intl/messages/mn-MN.json index 239ff85d..574875f7 100644 --- a/public/intl/messages/mn-MN.json +++ b/public/intl/messages/mn-MN.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Самбар нэмэх" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Харьяа" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Хэрэглэх" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Холбогдол" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Хэрэглэгчид таны маркетингт хэрхэн оролцож, ямар зүйлс хөрвүүлэлтэд нөлөөлж байгааг хараарай." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Самбарууд" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Аянууд" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Суваг" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Бүлэг" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Огноо харьцуулах" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Агуулга" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Хөрвүүлэлт" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Хөрвүүлэлтийн хувь" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Хөрвүүлэлтийн алхам" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Валют" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Шууд" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Ялгаатай ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Агуулаагүй" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Байхгүй" } ], "label.domain": [ @@ -506,7 +506,7 @@ "label.email": [ { "type": 0, - "value": "Email" + "value": "Имэйл" } ], "label.enable-share-url": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Үйлдлийн нэр" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Байгаа" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Өргөтгөх" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Эхний даралт" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Цутгалууд" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Бүлэглэсэн" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Хост нэр" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Агуулсан" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Ойлголт" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Худал байна" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Үнэн байна" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Аялалууд" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Сүүлийн даралт" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Холбоосууд" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Дунд" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Загвар" } ], "label.more": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Байгалийн хайлт" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Байгалийн дэлгүүр" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Байгалийн сошиал" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Байгалийн видео" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Бусад" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Хуудас" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Төлбөртэй зар" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Төлбөртэй хайлт" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Төлбөртэй дэлгүүр" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Төлбөртэй сошиал" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Төлбөртэй видео" } ], "label.password": [ @@ -1158,7 +1158,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Пиксел" } ], "label.powered-by": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Үлдсэн" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Шүүлтүүр сонгох" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Сессийн өгөгдөл" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Хуваалцах" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Эх сурвалжууд" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Таг" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Тагууд" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Багийн тохиргоо" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Нөхцөл" } ], "label.theme": [ diff --git a/public/intl/messages/ms-MY.json b/public/intl/messages/ms-MY.json index a643641e..b55ab0b0 100644 --- a/public/intl/messages/ms-MY.json +++ b/public/intl/messages/ms-MY.json @@ -251,7 +251,7 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, "value": "Conversion rate" diff --git a/public/intl/messages/my-MM.json b/public/intl/messages/my-MM.json index 448055a8..91a477ed 100644 --- a/public/intl/messages/my-MM.json +++ b/public/intl/messages/my-MM.json @@ -251,7 +251,7 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, "value": "Conversion rate" diff --git a/public/intl/messages/nb-NO.json b/public/intl/messages/nb-NO.json index a8d22a61..b9090692 100644 --- a/public/intl/messages/nb-NO.json +++ b/public/intl/messages/nb-NO.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Legg til tavle" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Tilknyttet" } ], "label.after": [ @@ -86,25 +86,25 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analyse" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Bruk" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Attribusjon" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Se hvordan brukere engasjerer seg i markedsføringen din og hva som driver konverteringer." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Tavler" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampanjer" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanaler" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohort" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Sammenlign datoer" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Innhold" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konvertering" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Konverteringsrate" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Konverteringssteg" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Valuta" } ], "label.current": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Slett rapport" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Slett team" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Slett bruker" } ], "label.delete-website": [ @@ -410,7 +410,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Beskrivelse" } ], "label.desktop": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Direkte" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Unik ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Inkluderer ikke" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Eksisterer ikke" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Hendelsesnavn" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Eksisterer" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Utvid" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Første klikk" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Trakter" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Gruppert" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Vertsnavn" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Inkluderer" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Innsikt" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Er usant" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Er sant" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Reiser" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Siste klikk" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Lenker" } ], "label.login": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Modell" } ], "label.more": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organisk søk" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organisk handel" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organisk sosial" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organisk video" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Annet" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Side" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Betalte annonser" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Betalt søk" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Betalt handel" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Betalt sosial" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Betalt video" } ], "label.password": [ @@ -1158,7 +1158,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Piksler" } ], "label.powered-by": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Gjenstår" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Velg filter" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Øktdata" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Del" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Kilder" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Tagg" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Tagger" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Teaminnstillinger" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Vilkår" } ], "label.theme": [ diff --git a/public/intl/messages/nl-NL.json b/public/intl/messages/nl-NL.json index e0a4b575..0672d332 100644 --- a/public/intl/messages/nl-NL.json +++ b/public/intl/messages/nl-NL.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Bord toevoegen" } ], "label.add-description": [ @@ -38,13 +38,13 @@ "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Lid toevoegen" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Stap toevoegen" } ], "label.add-website": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partner" } ], "label.after": [ @@ -86,25 +86,25 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analyse" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Toepassen" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Toewijzing" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Bekijk hoe gebruikers omgaan met je marketing en wat conversies stimuleert." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Borden" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Campagnes" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanalen" } ], "label.cities": [ @@ -206,13 +206,13 @@ "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Vergelijken" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Datums vergelijken" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Inhoud" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Conversie" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Conversieratio" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Conversiestap" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Aantal" } ], "label.countries": [ @@ -320,13 +320,13 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Valuta" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Huidig" } ], "label.current-password": [ @@ -398,7 +398,7 @@ "label.delete-user": [ { "type": 0, - "value": "Verwijder gebruiker" + "value": "Gebruiker verwijderen" } ], "label.delete-website": [ @@ -410,7 +410,7 @@ "label.description": [ { "type": 0, - "value": "Omschrijving" + "value": "Beschrijving" } ], "label.desktop": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Uniek ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Bevat niet" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Bestaat niet" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Gebeurtenisnaam" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Bestaat" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Uitvouwen" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Eerste klik" } ], "label.first-seen": [ @@ -638,25 +638,25 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Trechters" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Doel" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Doelen" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Volg je doelen voor paginaweergaven en gebeurtenissen." } ], "label.greater-than": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Gegroepeerd" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Hostnaam" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Bevat" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Inzicht" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Is onwaar" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Is waar" } ], "label.join": [ @@ -758,19 +758,19 @@ "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Reis" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Begrijp hoe gebruikers door je website navigeren." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Reizen" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Laatste klik" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Laatste " }, { "type": 1, @@ -836,13 +836,13 @@ }, { "type": 0, - "value": " months" + "value": " maanden" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Laatst gezien" } ], "label.leave": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Koppelingen" } ], "label.login": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organisch zoeken" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organisch winkelen" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organisch sociaal" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organische video" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Overig" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Pagina" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Betaalde advertenties" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Betaald zoeken" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Betaald winkelen" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Betaald sociaal" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Betaalde video" } ], "label.password": [ @@ -1146,13 +1146,13 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Pad" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Paden" } ], "label.pixels": [ @@ -1174,19 +1174,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Vorige" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Vorige periode" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Vorig jaar" } ], "label.profile": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Eigenschappen" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Eigenschap" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Verwijzing" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Resterend" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Omzet" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Bekijk je omzet in de loop van de tijd." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Filter selecteren" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Sessie" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Sessiegegevens" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Delen" } ], "label.share-url": [ @@ -1450,19 +1450,19 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Bronnen" } ], "label.start-step": [ { "type": 0, - "value": "Start Step" + "value": "Startstap" } ], "label.steps": [ { "type": 0, - "value": "Steps" + "value": "Stappen" } ], "label.sum": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Label" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Labels" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Teamleider" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Teaminstellingen" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Voorwaarden" } ], "label.theme": [ diff --git a/public/intl/messages/pl-PL.json b/public/intl/messages/pl-PL.json index 6e332c4c..44a4b620 100644 --- a/public/intl/messages/pl-PL.json +++ b/public/intl/messages/pl-PL.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Dodaj tablicę" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partner" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Zastosuj" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atrybucja" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Zobacz, jak użytkownicy angażują się w Twoją reklamę i co napędza konwersje." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Tablice" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampanie" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanały" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohorta" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Porównaj daty" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Treść" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konwersja" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Wskaźnik konwersji" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Etap konwersji" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Waluta" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Bezpośredni" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Unikalny ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Nie zawiera" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Nie istnieje" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Nazwa zdarzenia" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Istnieje" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Rozwiń" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Pierwsze kliknięcie" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Lejki" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Grupowane" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Nazwa hosta" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Zawiera" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Wgląd" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Jest fałszem" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Jest prawdą" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Drogi" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Ostatnie kliknięcie" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Osatnie " + "value": "Ostatnie " }, { "type": 1, @@ -842,7 +842,7 @@ "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Ostatnio widziany" } ], "label.leave": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Linki" } ], "label.login": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Wyszukiwanie organiczne" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Zakupy organiczne" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organiczne social media" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organiczne wideo" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Inne" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Strona" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Reklamy płatne" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Płatne wyszukiwanie" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Płatne zakupy" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Płatne social media" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Płatne wideo" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Ścieżka" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Ścieżki" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Piksele" } ], "label.powered-by": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Właściwości" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Właściwość" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Polecenie" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Pozostało" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Przychód" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Sprawdź swoje przychody w czasie." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Wybierz filtr" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Sesja" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Dane sesji" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Udostępnij" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Źródła" } ], "label.start-step": [ @@ -1486,7 +1486,7 @@ "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Tagi" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Menedżer zespołu" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Ustawienia zespołu" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Warunki" } ], "label.theme": [ diff --git a/public/intl/messages/pt-BR.json b/public/intl/messages/pt-BR.json index 04b6dd9a..b23bd062 100644 --- a/public/intl/messages/pt-BR.json +++ b/public/intl/messages/pt-BR.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Adicionar quadro" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Afiliado" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Aplicar" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atribuição" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Veja como os usuários interagem com seu marketing e o que impulsiona conversões." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Quadros" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Campanhas" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Canais" } ], "label.cities": [ @@ -200,19 +200,19 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Cohorte" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Comparar" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Comparar datas" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Conteúdo" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Conversão" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Taxa de conversão" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Etapa de conversão" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Contagem" } ], "label.countries": [ @@ -320,13 +320,13 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Moeda" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Atual" } ], "label.current-password": [ @@ -416,7 +416,7 @@ "label.desktop": [ { "type": 0, - "value": "Desktop" + "value": "Computador" } ], "label.details": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Direto" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "ID distinto" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Não inclui" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Não existe" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Nome do evento" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existe" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Expandir" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Primeiro clique" } ], "label.first-seen": [ @@ -638,25 +638,25 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Funis" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Meta" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Metas" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Acompanhe suas metas para visualizações de página e eventos." } ], "label.greater-than": [ @@ -674,19 +674,19 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Agrupado" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Nome do host" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Inclui" } ], "label.insight": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "É falso" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "É verdadeiro" } ], "label.join": [ @@ -758,19 +758,19 @@ "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Jornada" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Entenda como os usuários navegam pelo seu site." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Jornadas" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Último clique" } ], "label.last-days": [ @@ -842,7 +842,7 @@ "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Última visualização" } ], "label.leave": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Médio" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Modelo" } ], "label.more": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Busca orgânica" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Compras orgânicas" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Social orgânico" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Vídeo orgânico" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Outro" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Página" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Anúncios pagos" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Busca paga" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Compras pagas" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Social pago" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Vídeo pago" } ], "label.password": [ @@ -1146,13 +1146,13 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Caminho" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Caminhos" } ], "label.pixels": [ @@ -1174,19 +1174,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Anterior" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Período anterior" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Ano anterior" } ], "label.profile": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Propriedades" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Propriedade" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Referência" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Restante" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Receita" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Veja sua receita ao longo do tempo." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Selecionar filtro" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Sessão" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Dados da sessão" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Compartilhar" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Fontes" } ], "label.start-step": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Gerente da equipe" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Configurações da equipe" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Termos" } ], "label.theme": [ diff --git a/public/intl/messages/pt-PT.json b/public/intl/messages/pt-PT.json index ad2aa71c..f6ab5858 100644 --- a/public/intl/messages/pt-PT.json +++ b/public/intl/messages/pt-PT.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Código de acesso" } ], "label.actions": [ @@ -14,37 +14,37 @@ "label.activity": [ { "type": 0, - "value": "Activity log" + "value": "Registo de atividade" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "Adicionar" } ], "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Adicionar quadro" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Adicionar descrição" } ], "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Adicionar membro" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Adicionar passo" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Afiliado" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "Depois" } ], "label.all": [ @@ -86,31 +86,31 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Análise" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Aplicar" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atribuição" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Veja como os utilizadores interagem com o seu marketing e o que impulsiona conversões." } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Média" } ], "label.back": [ @@ -122,13 +122,13 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Antes" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Quadros" } ], "label.bounce-rate": [ @@ -140,13 +140,13 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Detalhamento" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "Navegador" } ], "label.browsers": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Campanhas" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Canais" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Cidades" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "Cidade" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Limpar tudo" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Cohorte" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Comparar" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Comparar datas" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Confirmar" } ], "label.confirm-password": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Conteúdo" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Conversão" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Taxa de conversão" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Passo de conversão" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Contagem" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "País" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "Criar" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Criar relatório" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Criar equipa" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Criar utilizador" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Criado" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Criado por" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Moeda" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Atual" } ], "label.current-password": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Dia" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Eliminar relatório" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Eliminar equipa" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Eliminar utilizador" } ], "label.delete-website": [ @@ -410,25 +410,25 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Descrição" } ], "label.desktop": [ { "type": 0, - "value": "Desktop" + "value": "Computador" } ], "label.details": [ { "type": 0, - "value": "Details" + "value": "Detalhes" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "Dispositivo" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Direto" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "ID distinto" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Não contém" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Não inclui" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Não existe" } ], "label.domain": [ @@ -494,13 +494,13 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Editar painel" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Editar membro" } ], "label.email": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Passo final" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "URL de entrada" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Evento" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Dados do evento" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Nome do evento" } ], "label.events": [ @@ -554,43 +554,43 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existe" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "URL de saída" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Expandir" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Falso" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Campo" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Campos" } ], "label.filter": [ { "type": 0, - "value": "Filter" + "value": "Filtro" } ], "label.filter-combined": [ @@ -608,85 +608,85 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Filtros" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Primeiro clique" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Primeira visualização" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Funil" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "Compreenda a taxa de conversão e abandono dos utilizadores." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Funis" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Objetivo" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Objetivos" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Acompanhe os seus objetivos para visualizações de página e eventos." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Maior que" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Maior ou igual a" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Agrupado" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Nome do host" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Inclui" } ], "label.insight": [ @@ -710,67 +710,67 @@ "label.is": [ { "type": 0, - "value": "Is" + "value": "É" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "É falso" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Não é" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Não definido" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Definido" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "É verdadeiro" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Juntar-se" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Juntar-se à equipa" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Jornada" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Compreenda como os utilizadores navegam no seu website." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Jornadas" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Último clique" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Últimos " }, { "type": 1, @@ -836,43 +836,43 @@ }, { "type": 0, - "value": " months" + "value": " meses" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Última visualização" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Sair" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Sair da equipa" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Menor que" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Menor ou igual a" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "Ligações" } ], "label.login": [ @@ -890,43 +890,43 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "Gerir" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Gestor" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "Máximo" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Médio" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "Membro" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Membros" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "Mínimo" } ], "label.mobile": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Modelo" } ], "label.more": [ @@ -950,13 +950,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "A minha conta" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Os meus websites" } ], "label.name": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Nenhum" } ], "label.number-of-records": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Pesquisa orgânica" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Compras orgânicas" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Social orgânico" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Vídeo orgânico" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Outro" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Página" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Anúncios pagos" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Pesquisa paga" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Compras pagas" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Social pago" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Vídeo pago" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Caminho" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Caminhos" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Píxeis" } ], "label.powered-by": [ @@ -1174,19 +1174,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Anterior" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Período anterior" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Ano anterior" } ], "label.profile": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Propriedades" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Propriedade" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Referência" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Restante" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Receita" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Veja a sua receita ao longo do tempo." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Selecionar filtro" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Sessão" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Dados da sessão" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Partilhar" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Fontes" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Etiqueta" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Etiquetas" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Gestor de equipa" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Definições da equipa" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Termos" } ], "label.theme": [ diff --git a/public/intl/messages/ro-RO.json b/public/intl/messages/ro-RO.json index 2a95d9ae..a235caee 100644 --- a/public/intl/messages/ro-RO.json +++ b/public/intl/messages/ro-RO.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Adaugă panou" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Afiliat" } ], "label.after": [ @@ -86,25 +86,25 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analiză" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Aplică" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atribuire" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Vezi cum utilizatorii interacționează cu marketingul tău și ce determină conversiile." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Panouri" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Campanii" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Canale" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Cohortă" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Compară datele" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Conținut" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Conversie" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Rată de conversie" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Pas de conversie" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Monedă" } ], "label.current": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Nu include" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Nu există" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Nume eveniment" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Există" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Extinde" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Primul click" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Parcursuri" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Grupat" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Nume gazdă" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Include" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Perspectivă" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Este fals" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Este adevărat" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Trasee" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Ultimul click" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Linkuri" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Mediu" } ], "label.member": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Căutare organică" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Cumpărături organice" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Social organic" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Video organic" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Altul" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Pagină" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Reclame plătite" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Căutare plătită" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Cumpărături plătite" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Social plătit" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Video plătit" } ], "label.password": [ @@ -1158,7 +1158,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pixeli" } ], "label.powered-by": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Rămas" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Selectează filtru" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Date sesiune" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Partajează" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Surse" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Etichetă" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Etichete" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Setări echipă" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Termeni" } ], "label.theme": [ diff --git a/public/intl/messages/ru-RU.json b/public/intl/messages/ru-RU.json index 9e25924a..e6451c1e 100644 --- a/public/intl/messages/ru-RU.json +++ b/public/intl/messages/ru-RU.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Добавить доску" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Партнер" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Применить" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Атрибуция" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Посмотрите, как пользователи взаимодействуют с вашим маркетингом и что приводит к конверсиям." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Доски" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Кампании" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Каналы" } ], "label.cities": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Когорта" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Сравнить даты" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Контент" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Конверсия" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Коэффициент конверсии" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Шаг конверсии" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Валюта" } ], "label.current": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Не включает" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Не существует" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Название события" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Существует" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Развернуть" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Первый клик" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Воронки" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Группировано" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Имя хоста" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Включает" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Инсайт" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Ложно" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Истинно" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Пути" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Последний клик" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Ссылки" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Средний" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Модель" } ], "label.more": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Органический поиск" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Органические покупки" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Органические соцсети" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Органическое видео" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Другое" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Страница" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Платная реклама" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Платный поиск" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Платные покупки" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Платные соцсети" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Платное видео" } ], "label.password": [ @@ -1158,7 +1158,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Пиксели" } ], "label.powered-by": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Осталось" } ], "label.remove": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Выберите фильтр" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Данные сессии" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Поделиться" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Источники" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Тег" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Теги" } ], "label.team": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Настройки команды" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Условия" } ], "label.theme": [ diff --git a/public/intl/messages/si-LK.json b/public/intl/messages/si-LK.json index 70c09c4f..6d75c325 100644 --- a/public/intl/messages/si-LK.json +++ b/public/intl/messages/si-LK.json @@ -251,7 +251,7 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, "value": "Conversion rate" diff --git a/public/intl/messages/sk-SK.json b/public/intl/messages/sk-SK.json index 103c5bf7..7446cd5d 100644 --- a/public/intl/messages/sk-SK.json +++ b/public/intl/messages/sk-SK.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Prístupový kód" } ], "label.actions": [ @@ -14,37 +14,37 @@ "label.activity": [ { "type": 0, - "value": "Activity log" + "value": "Denník aktivít" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "Pridať" } ], "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Pridať tabuľu" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Pridať popis" } ], "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Pridať člena" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Pridať krok" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partner" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "Po" } ], "label.all": [ @@ -80,37 +80,37 @@ "label.all-time": [ { "type": 0, - "value": "All time" + "value": "Celý čas" } ], "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analytika" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Použiť" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Priradenie" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Pozrite sa, ako používatelia interagujú s vaším marketingom a čo vedie ku konverziám." } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Priemer" } ], "label.back": [ @@ -122,13 +122,13 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Pred" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Tabule" } ], "label.bounce-rate": [ @@ -140,13 +140,13 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Rozpis" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "Prehliadač" } ], "label.browsers": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampane" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanály" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Mestá" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "Mesto" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Vymazať všetko" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohorta" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Porovnať" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Porovnať dátumy" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Potvrdiť" } ], "label.confirm-password": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Obsah" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konverzia" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Miera konverzie" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Krok konverzie" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Počet" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Krajina" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "Vytvoriť" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Vytvoriť správu" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Vytvoriť tím" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Vytvoriť používateľa" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Vytvorené" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Vytvoril" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Mena" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Aktuálny" } ], "label.current-password": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Deň" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Zmazať správu" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Zmazať tím" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Zmazať používateľa" } ], "label.delete-website": [ @@ -410,7 +410,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Popis" } ], "label.desktop": [ @@ -428,7 +428,7 @@ "label.device": [ { "type": 0, - "value": "Device" + "value": "Zariadenie" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Priamy" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Jedinečné ID" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Neobsahuje" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Nezahŕňa" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Neexistuje" } ], "label.domain": [ @@ -494,13 +494,13 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Upraviť prehľad" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Upraviť člena" } ], "label.email": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Konečný krok" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "Vstupná URL" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Udalosť" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Dáta udalosti" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Názov udalosti" } ], "label.events": [ @@ -554,37 +554,37 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existuje" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "Výstupná URL" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Rozbaliť" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Nepravda" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Pole" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Polia" } ], "label.filter": [ @@ -608,91 +608,91 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Filtre" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Prvé kliknutie" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Prvýkrát videné" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Lievik" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "Pochopte mieru konverzie a odchodu používateľov." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Lieviky" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Cieľ" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Ciele" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Sledujte svoje ciele pre zobrazenia stránok a udalosti." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Väčšie ako" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Väčšie alebo rovné" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Zoskupené" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Názov hostiteľa" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Zahŕňa" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Prehľad" } ], "label.insights": [ @@ -710,79 +710,79 @@ "label.is": [ { "type": 0, - "value": "Is" + "value": "Je" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Je nepravda" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Nie je" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Nie je nastavené" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Nastavené" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Je pravda" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Pripojiť sa" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Pripojiť sa k tímu" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Cesta" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Pochopte, ako používatelia prechádzajú vaším webom." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Cesty" } ], "label.language": [ { "type": 0, - "value": "Language" + "value": "Jazyk" } ], "label.languages": [ { "type": 0, - "value": "Languages" + "value": "Jazyky" } ], "label.laptop": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Posledné kliknutie" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Posledných " }, { "type": 1, @@ -836,43 +836,43 @@ }, { "type": 0, - "value": " months" + "value": " mesiacov" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Naposledy videné" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Odísť" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Opustiť tím" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Menej ako" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Menej alebo rovné" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "Odkazy" } ], "label.login": [ @@ -890,43 +890,43 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "Spravovať" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Manažér" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "Maximum" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Stredný" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "Člen" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Členovia" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "Minimum" } ], "label.mobile": [ @@ -950,13 +950,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "Môj účet" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Moje weby" } ], "label.name": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Žiadny" } ], "label.number-of-records": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organické vyhľadávanie" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organické nakupovanie" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organické sociálne siete" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organické video" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Iné" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Stránka" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Platené reklamy" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Platené vyhľadávanie" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Platené nakupovanie" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Platené sociálne siete" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Platené video" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Cesta" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Cesty" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pixely" } ], "label.powered-by": [ @@ -1174,19 +1174,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Predchádzajúci" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Predchádzajúce obdobie" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Predchádzajúci rok" } ], "label.profile": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Vlastnosti" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Vlastnosť" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Odporúčanie" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Zostáva" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Príjem" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Pozrite si svoj príjem v priebehu času." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Vybrať filter" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Sedenie" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Dáta sedenia" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Zdieľať" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Zdroje" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Značka" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Značky" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Manažér tímu" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Nastavenia tímu" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Podmienky" } ], "label.theme": [ diff --git a/public/intl/messages/sl-SI.json b/public/intl/messages/sl-SI.json index 2b32ae4f..d7a39997 100644 --- a/public/intl/messages/sl-SI.json +++ b/public/intl/messages/sl-SI.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Dodaj tablo" } ], "label.add-description": [ @@ -38,13 +38,13 @@ "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Dodaj člana" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Dodaj korak" } ], "label.add-website": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partner" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Uporabi" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Pripis" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Oglejte si, kako uporabniki sodelujejo z vašim marketingom in kaj spodbuja konverzije." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Table" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampanje" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanali" } ], "label.cities": [ @@ -200,19 +200,19 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohorta" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Primerjaj" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Primerjaj datume" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Vsebina" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konverzija" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Stopnja konverzije" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Korak konverzije" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Števec" } ], "label.countries": [ @@ -314,19 +314,19 @@ "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Ustvaril" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Valuta" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Trenutno" } ], "label.current-password": [ @@ -386,7 +386,7 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Izbriši poročilo" } ], "label.delete-team": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Neposredno" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Unikatni ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Ne vključuje" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Ne obstaja" } ], "label.domain": [ @@ -500,7 +500,7 @@ "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Uredi člana" } ], "label.email": [ @@ -518,13 +518,13 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Končni korak" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "Vhodni URL" } ], "label.event": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Ime dogodka" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Obstaja" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Razširi" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Prvi klik" } ], "label.first-seen": [ @@ -638,25 +638,25 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Lijaki" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Cilj" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Cilji" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Spremljajte svoje cilje za oglede strani in dogodke." } ], "label.greater-than": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Združeno" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Ime gostitelja" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Vključuje" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Vpogled" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Je napačno" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Je res" } ], "label.join": [ @@ -758,19 +758,19 @@ "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Potovanje" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Razumite, kako uporabniki krmarijo po vašem spletnem mestu." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Potovanja" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Zadnji klik" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Zadnjih " }, { "type": 1, @@ -836,13 +836,13 @@ }, { "type": 0, - "value": " months" + "value": " mesecev" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Zadnjič videno" } ], "label.leave": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Povezave" } ], "label.login": [ @@ -908,13 +908,13 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Srednje" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "Član" } ], "label.members": [ @@ -950,7 +950,7 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "Moj račun" } ], "label.my-websites": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "Brez" + "value": "Noben" } ], "label.number-of-records": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organsko iskanje" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organski nakupi" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organska družbena omrežja" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organski video" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Drugo" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Stran" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Plačani oglasi" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Plačano iskanje" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Plačani nakupi" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Plačana družbena omrežja" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Plačani video" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Pot" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Poti" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pikslov" } ], "label.powered-by": [ @@ -1174,19 +1174,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Prejšnji" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Prejšnje obdobje" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Prejšnje leto" } ], "label.profile": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Lastnosti" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Lastnost" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Napoten" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Preostalo" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Prihodek" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Oglejte si svoj prihodek skozi čas." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Izberi filter" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Seja" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Podatki seje" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Deli" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Viri" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Oznaka" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Oznake" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Vodja ekipe" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Nastavitve ekipe" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Pogoji" } ], "label.theme": [ diff --git a/public/intl/messages/sv-SE.json b/public/intl/messages/sv-SE.json index 36e799f7..014be980 100644 --- a/public/intl/messages/sv-SE.json +++ b/public/intl/messages/sv-SE.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Lägg till anslagstavla" } ], "label.add-description": [ @@ -38,13 +38,13 @@ "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Lägg till medlem" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Lägg till steg" } ], "label.add-website": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Partner" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Tillämpa" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Attribuering" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Se hur användare interagerar med din marknadsföring och vad som driver konverteringar." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Anslagstavlor" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampanjer" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanaler" } ], "label.cities": [ @@ -200,19 +200,19 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohort" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Jämför" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Jämför datum" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Innehåll" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Konvertering" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Konverteringsfrekvens" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Konverteringssteg" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Antal" } ], "label.countries": [ @@ -314,19 +314,19 @@ "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Skapad av" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Valuta" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Nuvarande" } ], "label.current-password": [ @@ -386,7 +386,7 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Radera rapport" } ], "label.delete-team": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Direkt" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Unikt ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Inkluderar inte" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Existerar inte" } ], "label.domain": [ @@ -500,7 +500,7 @@ "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Redigera medlem" } ], "label.email": [ @@ -518,13 +518,13 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Slutsteg" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "Ingångs-URL" } ], "label.event": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Händelsenamn" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Existerar" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Expandera" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Första klicket" } ], "label.first-seen": [ @@ -638,25 +638,25 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Trattar" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Mål" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Mål" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Följ dina mål för sidvisningar och händelser." } ], "label.greater-than": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Grupperad" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Värdnamn" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Inkluderar" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Insikt" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Är falskt" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Är sant" } ], "label.join": [ @@ -758,19 +758,19 @@ "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Resa" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Förstå hur användare navigerar på din webbplats." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Resor" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Sista klicket" } ], "label.last-days": [ @@ -828,7 +828,7 @@ "label.last-months": [ { "type": 0, - "value": "Last " + "value": "Senaste " }, { "type": 1, @@ -836,13 +836,13 @@ }, { "type": 0, - "value": " months" + "value": " månaderna" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Senast sedd" } ], "label.leave": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Länkar" } ], "label.login": [ @@ -914,7 +914,7 @@ "label.member": [ { "type": 0, - "value": "Member" + "value": "Medlem" } ], "label.members": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Modell" } ], "label.more": [ @@ -950,7 +950,7 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "Mitt konto" } ], "label.my-websites": [ @@ -974,7 +974,7 @@ "label.none": [ { "type": 0, - "value": "Inga" + "value": "Ingen" } ], "label.number-of-records": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organisk sökning" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organisk shopping" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organisk social" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organisk video" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Annat" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Sida" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Betalda annonser" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Betald sökning" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Betald shopping" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Betald social" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Betald video" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Sökväg" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Sökvägar" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pixlar" } ], "label.powered-by": [ @@ -1174,19 +1174,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Föregående" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Föregående period" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Föregående år" } ], "label.profile": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Egenskaper" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Egenskap" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Hänvisning" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Återstår" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Intäkter" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Se dina intäkter över tid." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Välj filter" } ], "label.select-role": [ @@ -1408,7 +1408,7 @@ "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Sessionsdata" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Dela" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Källor" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Tagg" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Taggar" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Teamledare" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Teaminställningar" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Villkor" } ], "label.theme": [ diff --git a/public/intl/messages/ta-IN.json b/public/intl/messages/ta-IN.json index f1d2d11a..780f2b32 100644 --- a/public/intl/messages/ta-IN.json +++ b/public/intl/messages/ta-IN.json @@ -251,7 +251,7 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, "value": "Conversion rate" diff --git a/public/intl/messages/th-TH.json b/public/intl/messages/th-TH.json index 6dcaa964..40ad9a70 100644 --- a/public/intl/messages/th-TH.json +++ b/public/intl/messages/th-TH.json @@ -251,7 +251,7 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, "value": "Conversion rate" diff --git a/public/intl/messages/tr-TR.json b/public/intl/messages/tr-TR.json index a0d6b90d..af603ec1 100644 --- a/public/intl/messages/tr-TR.json +++ b/public/intl/messages/tr-TR.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Pano ekle" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Ortak" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Uygula" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Atıf" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Kullanıcıların pazarlamanızla nasıl etkileşime girdiğini ve dönüşümleri neyin tetiklediğini görün." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Panolar" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Kampanyalar" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kanallar" } ], "label.cities": [ @@ -200,19 +200,19 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Kohort" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Karşılaştır" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Tarihleri karşılaştır" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "İçerik" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Dönüşüm" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Dönüşüm oranı" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Dönüşüm adımı" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Adet" } ], "label.countries": [ @@ -320,13 +320,13 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Para birimi" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Mevcut" } ], "label.current-password": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Doğrudan" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Benzersiz ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "İçermiyor" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Mevcut değil" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Olay adı" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Mevcut" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Genişlet" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "İlk tıklama" } ], "label.first-seen": [ @@ -638,25 +638,25 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Huniler" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Hedef" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Hedefler" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Sayfa görüntüleme ve olaylar için hedeflerinizi takip edin." } ], "label.greater-than": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Gruplandırılmış" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Sunucu adı" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "İçerir" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "İçgörü" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Yanlış" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Doğru" } ], "label.join": [ @@ -758,19 +758,19 @@ "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Yolculuk" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Kullanıcıların sitenizde nasıl gezindiğini anlayın." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Yolculuklar" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Son tıklama" } ], "label.last-days": [ @@ -842,7 +842,7 @@ "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Son görüldü" } ], "label.leave": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Bağlantılar" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Orta" } ], "label.member": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Organik arama" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Organik alışveriş" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Organik sosyal" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Organik video" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Diğer" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Sayfa" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Ücretli reklamlar" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Ücretli arama" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Ücretli alışveriş" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Ücretli sosyal" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Ücretli video" } ], "label.password": [ @@ -1146,19 +1146,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Yol" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Yollar" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pikseller" } ], "label.powered-by": [ @@ -1174,19 +1174,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Önceki" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Önceki dönem" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Önceki yıl" } ], "label.profile": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Özellikler" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Özellik" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Yönlendirme" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Kalan" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Gelir" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Gelirinizi zaman içinde inceleyin." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Filtre seç" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Oturum" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Oturum verisi" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Paylaş" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Kaynaklar" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Etiket" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Etiketler" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Takım yöneticisi" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Takım ayarları" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Koşullar" } ], "label.theme": [ diff --git a/public/intl/messages/uk-UA.json b/public/intl/messages/uk-UA.json index fe7d417a..2a3e48ec 100644 --- a/public/intl/messages/uk-UA.json +++ b/public/intl/messages/uk-UA.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Додати дошку" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Партнер" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Застосувати" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Атрибуція" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Дивіться, як користувачі взаємодіють з вашим маркетингом і що сприяє конверсіям." } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Дошки" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Кампанії" } ], "label.cancel": [ @@ -176,7 +176,7 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Канали" } ], "label.cities": [ @@ -200,19 +200,19 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Когорта" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "Порівняти" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "Порівняти дати" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "Вміст" } ], "label.continue": [ @@ -248,25 +248,25 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Конверсія" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Рівень конверсії" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Крок конверсії" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Кількість" } ], "label.countries": [ @@ -320,13 +320,13 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Валюта" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Поточний" } ], "label.current-password": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Прямий" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "Унікальний ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Не включає" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Не існує" } ], "label.domain": [ @@ -494,13 +494,13 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Редагувати панель" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Редагувати учасника" } ], "label.email": [ @@ -512,19 +512,19 @@ "label.enable-share-url": [ { "type": 0, - "value": "Enable share URL" + "value": "Увімкнути спільне посилання" } ], "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Кінцевий крок" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "Вхідний URL" } ], "label.event": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Назва події" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Існує" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Розгорнути" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Перший клік" } ], "label.first-seen": [ @@ -638,25 +638,25 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Воронки" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Мета" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Мети" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Відстежуйте свої цілі для переглядів сторінок і подій." } ], "label.greater-than": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Груповано" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Ім'я хоста" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Включає" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Інсайт" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Хибно" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Правдиво" } ], "label.join": [ @@ -758,19 +758,19 @@ "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Шлях" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Зрозумійте, як користувачі переміщаються вашим сайтом." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Шляхи" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Останній клік" } ], "label.last-days": [ @@ -842,7 +842,7 @@ "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Останній перегляд" } ], "label.leave": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "Посилання" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Середній" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Модель" } ], "label.more": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Органічний пошук" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Органічні покупки" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Органічні соцмережі" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Органічне відео" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Інше" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Сторінка" } ], "label.page-of": [ @@ -1110,31 +1110,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Платна реклама" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Платний пошук" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Платні покупки" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Платні соцмережі" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Платне відео" } ], "label.password": [ @@ -1158,7 +1158,7 @@ "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Пікселі" } ], "label.powered-by": [ @@ -1174,19 +1174,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Попередній" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Попередній період" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Попередній рік" } ], "label.profile": [ @@ -1198,13 +1198,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Властивості" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Властивість" } ], "label.queries": [ @@ -1234,7 +1234,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Реферал" } ], "label.referrer": [ @@ -1276,7 +1276,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Залишилось" } ], "label.remove": [ @@ -1330,13 +1330,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Дохід" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Перегляньте свій дохід за певний період." } ], "label.role": [ @@ -1384,7 +1384,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Вибрати фільтр" } ], "label.select-role": [ @@ -1402,13 +1402,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Сесія" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Дані сесії" } ], "label.sessions": [ @@ -1426,7 +1426,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Поділитися" } ], "label.share-url": [ @@ -1450,7 +1450,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Джерела" } ], "label.start-step": [ @@ -1480,13 +1480,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Тег" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Теги" } ], "label.team": [ @@ -1504,7 +1504,7 @@ "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Менеджер команди" } ], "label.team-member": [ @@ -1528,7 +1528,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Налаштування команди" } ], "label.team-view-only": [ @@ -1552,7 +1552,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Умови" } ], "label.theme": [ diff --git a/public/intl/messages/ur-PK.json b/public/intl/messages/ur-PK.json index 651b5c0a..f5f55b24 100644 --- a/public/intl/messages/ur-PK.json +++ b/public/intl/messages/ur-PK.json @@ -251,7 +251,7 @@ "value": "Conversion" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, "value": "Conversion rate" diff --git a/public/intl/messages/vi-VN.json b/public/intl/messages/vi-VN.json index a2b87271..5f969518 100644 --- a/public/intl/messages/vi-VN.json +++ b/public/intl/messages/vi-VN.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Mã truy cập" } ], "label.actions": [ @@ -14,37 +14,37 @@ "label.activity": [ { "type": 0, - "value": "Activity log" + "value": "Nhật ký hoạt động" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "Thêm" } ], "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "Thêm bảng" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Thêm mô tả" } ], "label.add-member": [ { "type": 0, - "value": "Add member" + "value": "Thêm thành viên" } ], "label.add-step": [ { "type": 0, - "value": "Add step" + "value": "Thêm bước" } ], "label.add-website": [ @@ -62,13 +62,13 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "Liên kết" } ], "label.after": [ { "type": 0, - "value": "After" + "value": "Sau" } ], "label.all": [ @@ -86,31 +86,31 @@ "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Phân tích" } ], "label.apply": [ { "type": 0, - "value": "Apply" + "value": "Áp dụng" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "Phân bổ" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "Xem cách người dùng tương tác với tiếp thị của bạn và điều gì thúc đẩy chuyển đổi." } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Trung bình" } ], "label.back": [ @@ -122,13 +122,13 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Trước" } ], "label.boards": [ { "type": 0, - "value": "Boards" + "value": "Bảng" } ], "label.bounce-rate": [ @@ -140,13 +140,13 @@ "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Phân tích chi tiết" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "Trình duyệt" } ], "label.browsers": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "Chiến dịch" } ], "label.cancel": [ @@ -176,49 +176,49 @@ "label.channels": [ { "type": 0, - "value": "Channels" + "value": "Kênh" } ], "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Thành phố" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "Thành phố" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Xóa tất cả" } ], "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "Nhóm người dùng" } ], "label.compare": [ { "type": 0, - "value": "Compare" + "value": "So sánh" } ], "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "So sánh ngày" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Xác nhận" } ], "label.confirm-password": [ @@ -230,43 +230,43 @@ "label.contains": [ { "type": 0, - "value": "Contains" + "value": "Chứa" } ], "label.content": [ { "type": 0, - "value": "Content" + "value": "Nội dung" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "Tiếp tục" } ], "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "Chuyển đổi" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "Tỷ lệ chuyển đổi" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "Bước chuyển đổi" } ], "label.count": [ { "type": 0, - "value": "Count" + "value": "Số lượng" } ], "label.countries": [ @@ -278,55 +278,55 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Quốc gia" } ], "label.create": [ { "type": 0, - "value": "Create" + "value": "Tạo" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Tạo báo cáo" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Tạo nhóm" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Tạo người dùng" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Đã tạo" } ], "label.created-by": [ { "type": 0, - "value": "Created By" + "value": "Tạo bởi" } ], "label.currency": [ { "type": 0, - "value": "Currency" + "value": "Tiền tệ" } ], "label.current": [ { "type": 0, - "value": "Current" + "value": "Hiện tại" } ], "label.current-password": [ @@ -350,13 +350,13 @@ "label.data": [ { "type": 0, - "value": "Data" + "value": "Dữ liệu" } ], "label.date": [ { "type": 0, - "value": "Date" + "value": "Ngày" } ], "label.date-range": [ @@ -368,7 +368,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Ngày" } ], "label.default-date-range": [ @@ -386,19 +386,19 @@ "label.delete-report": [ { "type": 0, - "value": "Delete report" + "value": "Xóa báo cáo" } ], "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Xóa nhóm" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Xóa người dùng" } ], "label.delete-website": [ @@ -410,7 +410,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Mô tả" } ], "label.desktop": [ @@ -422,13 +422,13 @@ "label.details": [ { "type": 0, - "value": "Details" + "value": "Chi tiết" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "Thiết bị" } ], "label.devices": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "Trực tiếp" } ], "label.dismiss": [ @@ -452,25 +452,25 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "ID riêng biệt" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Không chứa" } ], "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "Không bao gồm" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "Không tồn tại" } ], "label.domain": [ @@ -482,7 +482,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Rời bỏ" } ], "label.edit": [ @@ -494,13 +494,13 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Chỉnh sửa bảng điều khiển" } ], "label.edit-member": [ { "type": 0, - "value": "Edit member" + "value": "Chỉnh sửa thành viên" } ], "label.email": [ @@ -518,31 +518,31 @@ "label.end-step": [ { "type": 0, - "value": "End Step" + "value": "Bước kết thúc" } ], "label.entry": [ { "type": 0, - "value": "Entry URL" + "value": "URL vào" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Sự kiện" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Dữ liệu sự kiện" } ], "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "Tên sự kiện" } ], "label.events": [ @@ -554,43 +554,43 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "Tồn tại" } ], "label.exit": [ { "type": 0, - "value": "Exit URL" + "value": "URL thoát" } ], "label.expand": [ { "type": 0, - "value": "Expand" + "value": "Mở rộng" } ], "label.false": [ { "type": 0, - "value": "False" + "value": "Sai" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Trường" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Các trường" } ], "label.filter": [ { "type": 0, - "value": "Filter" + "value": "Bộ lọc" } ], "label.filter-combined": [ @@ -608,91 +608,91 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Bộ lọc" } ], "label.first-click": [ { "type": 0, - "value": "First click" + "value": "Nhấp đầu tiên" } ], "label.first-seen": [ { "type": 0, - "value": "First seen" + "value": "Lần đầu thấy" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Phễu" } ], "label.funnel-description": [ { "type": 0, - "value": "Understand the conversion and drop-off rate of users." + "value": "Hiểu tỷ lệ chuyển đổi và rời bỏ của người dùng." } ], "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "Phễu" } ], "label.goal": [ { "type": 0, - "value": "Goal" + "value": "Mục tiêu" } ], "label.goals": [ { "type": 0, - "value": "Goals" + "value": "Mục tiêu" } ], "label.goals-description": [ { "type": 0, - "value": "Track your goals for pageviews and events." + "value": "Theo dõi mục tiêu lượt xem trang và sự kiện." } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Lớn hơn" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Lớn hơn hoặc bằng" } ], "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "Nhóm lại" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "Tên máy chủ" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "Bao gồm" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "Thông tin chi tiết" } ], "label.insights": [ @@ -710,73 +710,73 @@ "label.is": [ { "type": 0, - "value": "Is" + "value": "Là" } ], "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "Sai" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Không là" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Chưa đặt" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Đã đặt" } ], "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "Đúng" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Tham gia" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Tham gia nhóm" } ], "label.journey": [ { "type": 0, - "value": "Journey" + "value": "Hành trình" } ], "label.journey-description": [ { "type": 0, - "value": "Understand how users navigate through your website." + "value": "Hiểu cách người dùng di chuyển qua website của bạn." } ], "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "Hành trình" } ], "label.language": [ { "type": 0, - "value": "Language" + "value": "Ngôn ngữ" } ], "label.languages": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "Nhấp cuối cùng" } ], "label.last-days": [ @@ -818,53 +818,49 @@ } ], "label.last-months": [ - { - "type": 0, - "value": "Last " - }, { "type": 1, "value": "x" }, { "type": 0, - "value": " months" + "value": " tháng gần nhất" } ], "label.last-seen": [ { "type": 0, - "value": "Last seen" + "value": "Lần cuối thấy" } ], "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Rời đi" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Rời nhóm" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Nhỏ hơn" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Nhỏ hơn hoặc bằng" } ], "label.links": [ { "type": 0, - "value": "Links" + "value": "Liên kết" } ], "label.login": [ @@ -882,43 +878,43 @@ "label.manage": [ { "type": 0, - "value": "Manage" + "value": "Quản lý" } ], "label.manager": [ { "type": 0, - "value": "Manager" + "value": "Quản lý viên" } ], "label.max": [ { "type": 0, - "value": "Max" + "value": "Tối đa" } ], "label.medium": [ { "type": 0, - "value": "Medium" + "value": "Trung bình" } ], "label.member": [ { "type": 0, - "value": "Member" + "value": "Thành viên" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Các thành viên" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "Tối thiểu" } ], "label.mobile": [ @@ -930,7 +926,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "Mô hình" } ], "label.more": [ @@ -942,13 +938,13 @@ "label.my-account": [ { "type": 0, - "value": "My account" + "value": "Tài khoản của tôi" } ], "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Website của tôi" } ], "label.name": [ @@ -966,7 +962,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Không có" } ], "label.number-of-records": [ @@ -1012,25 +1008,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "Tìm kiếm tự nhiên" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "Mua sắm tự nhiên" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "Mạng xã hội tự nhiên" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "Video tự nhiên" } ], "label.os": [ @@ -1042,7 +1038,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "Khác" } ], "label.overview": [ @@ -1060,7 +1056,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "Trang" } ], "label.page-of": [ @@ -1102,31 +1098,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "Quảng cáo trả phí" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "Tìm kiếm trả phí" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "Mua sắm trả phí" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "Mạng xã hội trả phí" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "Video trả phí" } ], "label.password": [ @@ -1138,19 +1134,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "Đường dẫn" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "Các đường dẫn" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "Pixel" } ], "label.powered-by": [ @@ -1166,19 +1162,19 @@ "label.previous": [ { "type": 0, - "value": "Previous" + "value": "Trước đó" } ], "label.previous-period": [ { "type": 0, - "value": "Previous period" + "value": "Giai đoạn trước" } ], "label.previous-year": [ { "type": 0, - "value": "Previous year" + "value": "Năm trước" } ], "label.profile": [ @@ -1190,13 +1186,13 @@ "label.properties": [ { "type": 0, - "value": "Properties" + "value": "Thuộc tính" } ], "label.property": [ { "type": 0, - "value": "Property" + "value": "Thuộc tính" } ], "label.queries": [ @@ -1226,7 +1222,7 @@ "label.referral": [ { "type": 0, - "value": "Referral" + "value": "Giới thiệu" } ], "label.referrer": [ @@ -1268,7 +1264,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "Còn lại" } ], "label.remove": [ @@ -1322,13 +1318,13 @@ "label.revenue": [ { "type": 0, - "value": "Revenue" + "value": "Doanh thu" } ], "label.revenue-description": [ { "type": 0, - "value": "Look into your revenue across time." + "value": "Xem doanh thu của bạn theo thời gian." } ], "label.role": [ @@ -1376,7 +1372,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "Chọn bộ lọc" } ], "label.select-role": [ @@ -1394,13 +1390,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "Phiên" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "Dữ liệu phiên" } ], "label.sessions": [ @@ -1418,7 +1414,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "Chia sẻ" } ], "label.share-url": [ @@ -1442,7 +1438,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "Nguồn" } ], "label.start-step": [ @@ -1472,55 +1468,55 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "Thẻ" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "Các thẻ" } ], "label.team": [ { "type": 0, - "value": "Team" + "value": "Nhóm" } ], "label.team-id": [ { "type": 0, - "value": "Team ID" + "value": "ID nhóm" } ], "label.team-manager": [ { "type": 0, - "value": "Team manager" + "value": "Quản lý nhóm" } ], "label.team-member": [ { "type": 0, - "value": "Team member" + "value": "Thành viên nhóm" } ], "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "Tên nhóm" } ], "label.team-owner": [ { "type": 0, - "value": "Team owner" + "value": "Chủ nhóm" } ], "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "Cài đặt nhóm" } ], "label.team-view-only": [ @@ -1544,7 +1540,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "Điều khoản" } ], "label.theme": [ diff --git a/public/intl/messages/zh-CN.json b/public/intl/messages/zh-CN.json index 88448580..d6b7dba7 100644 --- a/public/intl/messages/zh-CN.json +++ b/public/intl/messages/zh-CN.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "添加看板" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "联盟" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "应用" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "归因" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "查看用户如何与您的营销互动,以及是什么促成了转化。" } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "看板" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "活动" } ], "label.cancel": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "队列" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "比较日期" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "内容" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "转化" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "转化率" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "转化步骤" } ], "label.count": [ @@ -320,7 +320,7 @@ "label.currency": [ { "type": 0, - "value": "Currency" + "value": "货币" } ], "label.current": [ @@ -440,7 +440,7 @@ "label.direct": [ { "type": 0, - "value": "Direct" + "value": "直接" } ], "label.dismiss": [ @@ -452,7 +452,7 @@ "label.distinct-id": [ { "type": 0, - "value": "Distinct ID" + "value": "唯一ID" } ], "label.does-not-contain": [ @@ -464,13 +464,13 @@ "label.does-not-include": [ { "type": 0, - "value": "Does not include" + "value": "不包括" } ], "label.doest-not-exist": [ { "type": 0, - "value": "Does not exist" + "value": "不存在" } ], "label.domain": [ @@ -542,7 +542,7 @@ "label.event-name": [ { "type": 0, - "value": "Event name" + "value": "事件名称" } ], "label.events": [ @@ -554,7 +554,7 @@ "label.exists": [ { "type": 0, - "value": "Exists" + "value": "存在" } ], "label.exit": [ @@ -566,7 +566,7 @@ "label.expand": [ { "type": 0, - "value": "Expand" + "value": "展开" } ], "label.false": [ @@ -614,7 +614,7 @@ "label.first-click": [ { "type": 0, - "value": "First click" + "value": "首次点击" } ], "label.first-seen": [ @@ -638,7 +638,7 @@ "label.funnels": [ { "type": 0, - "value": "Funnels" + "value": "漏斗" } ], "label.goal": [ @@ -674,25 +674,25 @@ "label.grouped": [ { "type": 0, - "value": "Grouped" + "value": "分组" } ], "label.hostname": [ { "type": 0, - "value": "Hostname" + "value": "主机名" } ], "label.includes": [ { "type": 0, - "value": "Includes" + "value": "包括" } ], "label.insight": [ { "type": 0, - "value": "Insight" + "value": "洞察" } ], "label.insights": [ @@ -716,7 +716,7 @@ "label.is-false": [ { "type": 0, - "value": "Is false" + "value": "否" } ], "label.is-not": [ @@ -740,7 +740,7 @@ "label.is-true": [ { "type": 0, - "value": "Is true" + "value": "是" } ], "label.join": [ @@ -770,7 +770,7 @@ "label.journeys": [ { "type": 0, - "value": "Journeys" + "value": "用户路径" } ], "label.language": [ @@ -794,7 +794,7 @@ "label.last-click": [ { "type": 0, - "value": "Last click" + "value": "最后点击" } ], "label.last-days": [ @@ -872,7 +872,7 @@ "label.links": [ { "type": 0, - "value": "Links" + "value": "链接" } ], "label.login": [ @@ -908,7 +908,7 @@ "label.medium": [ { "type": 0, - "value": "Medium" + "value": "中等" } ], "label.member": [ @@ -938,7 +938,7 @@ "label.model": [ { "type": 0, - "value": "Model" + "value": "模型" } ], "label.more": [ @@ -1020,25 +1020,25 @@ "label.organic-search": [ { "type": 0, - "value": "Organic search" + "value": "自然搜索" } ], "label.organic-shopping": [ { "type": 0, - "value": "Organic shopping" + "value": "自然购物" } ], "label.organic-social": [ { "type": 0, - "value": "Organic social" + "value": "自然社交" } ], "label.organic-video": [ { "type": 0, - "value": "Organic video" + "value": "自然视频" } ], "label.os": [ @@ -1050,7 +1050,7 @@ "label.other": [ { "type": 0, - "value": "Other" + "value": "其他" } ], "label.overview": [ @@ -1068,7 +1068,7 @@ "label.page": [ { "type": 0, - "value": "Page" + "value": "页面" } ], "label.page-of": [ @@ -1114,31 +1114,31 @@ "label.paid-ads": [ { "type": 0, - "value": "Paid ads" + "value": "付费广告" } ], "label.paid-search": [ { "type": 0, - "value": "Paid search" + "value": "付费搜索" } ], "label.paid-shopping": [ { "type": 0, - "value": "Paid shopping" + "value": "付费购物" } ], "label.paid-social": [ { "type": 0, - "value": "Paid social" + "value": "付费社交" } ], "label.paid-video": [ { "type": 0, - "value": "Paid video" + "value": "付费视频" } ], "label.password": [ @@ -1150,19 +1150,19 @@ "label.path": [ { "type": 0, - "value": "Path" + "value": "路径" } ], "label.paths": [ { "type": 0, - "value": "Paths" + "value": "路径" } ], "label.pixels": [ { "type": 0, - "value": "Pixels" + "value": "像素" } ], "label.powered-by": [ @@ -1284,7 +1284,7 @@ "label.remaining": [ { "type": 0, - "value": "Remaining" + "value": "剩余" } ], "label.remove": [ @@ -1392,7 +1392,7 @@ "label.select-filter": [ { "type": 0, - "value": "Select filter" + "value": "选择筛选器" } ], "label.select-role": [ @@ -1410,13 +1410,13 @@ "label.session": [ { "type": 0, - "value": "Session" + "value": "会话" } ], "label.session-data": [ { "type": 0, - "value": "Session data" + "value": "会话数据" } ], "label.sessions": [ @@ -1434,7 +1434,7 @@ "label.share": [ { "type": 0, - "value": "Share" + "value": "分享" } ], "label.share-url": [ @@ -1458,7 +1458,7 @@ "label.sources": [ { "type": 0, - "value": "Sources" + "value": "来源" } ], "label.start-step": [ @@ -1488,13 +1488,13 @@ "label.tag": [ { "type": 0, - "value": "Tag" + "value": "标签" } ], "label.tags": [ { "type": 0, - "value": "Tags" + "value": "标签" } ], "label.team": [ @@ -1536,7 +1536,7 @@ "label.team-settings": [ { "type": 0, - "value": "Team settings" + "value": "团队设置" } ], "label.team-view-only": [ @@ -1560,7 +1560,7 @@ "label.terms": [ { "type": 0, - "value": "Terms" + "value": "条款" } ], "label.theme": [ diff --git a/public/intl/messages/zh-TW.json b/public/intl/messages/zh-TW.json index 03c88b31..68b5e220 100644 --- a/public/intl/messages/zh-TW.json +++ b/public/intl/messages/zh-TW.json @@ -26,7 +26,7 @@ "label.add-board": [ { "type": 0, - "value": "Add board" + "value": "新增看板" } ], "label.add-description": [ @@ -62,7 +62,7 @@ "label.affiliate": [ { "type": 0, - "value": "Affiliate" + "value": "聯盟" } ], "label.after": [ @@ -92,19 +92,19 @@ "label.apply": [ { "type": 0, - "value": "Apply" + "value": "套用" } ], "label.attribution": [ { "type": 0, - "value": "Attribution" + "value": "歸因" } ], "label.attribution-description": [ { "type": 0, - "value": "See how users engage with your marketing and what drives conversions." + "value": "查看使用者如何與您的行銷互動,以及什麼促成了轉換。" } ], "label.average": [ @@ -128,7 +128,7 @@ "label.boards": [ { "type": 0, - "value": "Boards" + "value": "看板" } ], "label.bounce-rate": [ @@ -158,7 +158,7 @@ "label.campaigns": [ { "type": 0, - "value": "Campaigns" + "value": "活動" } ], "label.cancel": [ @@ -200,7 +200,7 @@ "label.cohort": [ { "type": 0, - "value": "Cohort" + "value": "群組" } ], "label.compare": [ @@ -212,7 +212,7 @@ "label.compare-dates": [ { "type": 0, - "value": "Compare dates" + "value": "比較日期" } ], "label.confirm": [ @@ -236,7 +236,7 @@ "label.content": [ { "type": 0, - "value": "Content" + "value": "內容" } ], "label.continue": [ @@ -248,19 +248,19 @@ "label.conversion": [ { "type": 0, - "value": "Conversion" + "value": "轉換" } ], - "label.conversion-ratep": [ + "label.conversion-rate": [ { "type": 0, - "value": "Conversion rate" + "value": "轉換率" } ], "label.conversion-step": [ { "type": 0, - "value": "Conversion step" + "value": "轉換步驟" } ], "label.count": [ diff --git a/src/lang/am-ET.json b/src/lang/am-ET.json deleted file mode 100644 index 54f97a58..00000000 --- a/src/lang/am-ET.json +++ /dev/null @@ -1,337 +0,0 @@ -{ - "label.access-code": "Access code", - "label.actions": "Actions", - "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", - "label.add-website": "Add website", - "label.admin": "Administrator", - "label.affiliate": "Affiliate", - "label.after": "After", - "label.all": "All", - "label.all-time": "All time", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", - "label.back": "Back", - "label.before": "Before", - "label.boards": "Boards", - "label.bounce-rate": "Bounce rate", - "label.breakdown": "Breakdown", - "label.browser": "Browser", - "label.browsers": "Browsers", - "label.campaigns": "Campaigns", - "label.cancel": "Cancel", - "label.change-password": "Change password", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", - "label.confirm-password": "Confirm password", - "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", - "label.countries": "Countries", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", - "label.current-password": "Current password", - "label.custom-range": "Custom range", - "label.dashboard": "Dashboard", - "label.data": "Data", - "label.date": "Date", - "label.date-range": "Date range", - "label.day": "Day", - "label.default-date-range": "Default date range", - "label.delete": "Delete", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", - "label.delete-website": "Delete website", - "label.description": "Description", - "label.desktop": "Desktop", - "label.details": "Details", - "label.device": "Device", - "label.devices": "Devices", - "label.direct": "Direct", - "label.dismiss": "Dismiss", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", - "label.domain": "Domain", - "label.dropoff": "Dropoff", - "label.edit": "Edit", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", - "label.email": "Email", - "label.enable-share-url": "Enable share URL", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event Data", - "label.event-name": "Event name", - "label.events": "Events", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", - "label.filter": "Filter", - "label.filter-combined": "Combined", - "label.filter-raw": "Raw", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", - "label.language": "Language", - "label.languages": "Languages", - "label.laptop": "Laptop", - "label.last-click": "Last click", - "label.last-days": "Last {x} days", - "label.last-hours": "Last {x} hours", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", - "label.login": "Login", - "label.logout": "Logout", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", - "label.mobile": "Mobile", - "label.model": "Model", - "label.more": "More", - "label.my-account": "My account", - "label.my-websites": "My websites", - "label.name": "Name", - "label.new-password": "New password", - "label.none": "None", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", - "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", - "label.os": "OS", - "label.other": "Other", - "label.overview": "Overview", - "label.owner": "Owner", - "label.page": "Page", - "label.page-of": "Page {current} of {total}", - "label.page-views": "Page views", - "label.pageTitle": "Page title", - "label.pages": "Pages", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", - "label.password": "Password", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", - "label.powered-by": "Powered by {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", - "label.profile": "Profile", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", - "label.realtime": "Realtime", - "label.referral": "Referral", - "label.referrer": "Referrer", - "label.referrers": "Referrers", - "label.refresh": "Refresh", - "label.regenerate": "Regenerate", - "label.region": "Region", - "label.regions": "Regions", - "label.remaining": "Remaining", - "label.remove": "Remove", - "label.remove-member": "Remove member", - "label.reports": "Reports", - "label.required": "Required", - "label.reset": "Reset", - "label.reset-website": "Reset statistics", - "label.retention": "Retention", - "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", - "label.role": "Role", - "label.run-query": "Run query", - "label.save": "Save", - "label.screens": "Screens", - "label.search": "Search", - "label.select": "Select", - "label.select-date": "Select date", - "label.select-filter": "Select filter", - "label.select-role": "Select role", - "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", - "label.sessions": "Sessions", - "label.settings": "Settings", - "label.share": "Share", - "label.share-url": "Share URL", - "label.single-day": "Single day", - "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", - "label.sum": "Sum", - "label.tablet": "Tablet", - "label.tag": "Tag", - "label.tags": "Tags", - "label.team": "Team", - "label.team-id": "Team ID", - "label.team-manager": "Team manager", - "label.team-member": "Team member", - "label.team-name": "Team name", - "label.team-owner": "Team owner", - "label.team-settings": "Team settings", - "label.team-view-only": "Team view only", - "label.team-websites": "Team websites", - "label.teams": "Teams", - "label.terms": "Terms", - "label.theme": "Theme", - "label.this-month": "This month", - "label.this-week": "This week", - "label.this-year": "This year", - "label.timezone": "Timezone", - "label.title": "Title", - "label.today": "Today", - "label.toggle-charts": "Toggle charts", - "label.total": "Total", - "label.total-records": "Total records", - "label.tracking-code": "Tracking code", - "label.transactions": "Transactions", - "label.transfer": "Transfer", - "label.transfer-website": "Transfer website", - "label.true": "True", - "label.type": "Type", - "label.unique": "Unique", - "label.unique-visitors": "Unique visitors", - "label.uniqueCustomers": "Unique Customers", - "label.unknown": "Unknown", - "label.untitled": "Untitled", - "label.update": "Update", - "label.user": "User", - "label.username": "Username", - "label.users": "Users", - "label.utm": "UTM", - "label.utm-description": "Track your campaigns through UTM parameters.", - "label.value": "Value", - "label.view": "View", - "label.view-details": "View details", - "label.view-only": "View only", - "label.views": "Views", - "label.views-per-visit": "Views per visit", - "label.visit-duration": "Visit duration", - "label.visitors": "Visitors", - "label.visits": "Visits", - "label.website": "Website", - "label.website-id": "Website ID", - "label.websites": "Websites", - "label.window": "Window", - "label.yesterday": "Yesterday", - "message.action-confirmation": "Type {confirmation} in the box below to confirm.", - "message.active-users": "{x} current {x, plural, one {visitor} other {visitors}}", - "message.bad-request": "Bad request", - "message.collected-data": "Collected data", - "message.confirm-delete": "Are you sure you want to delete {target}?", - "message.confirm-leave": "Are you sure you want to leave {target}?", - "message.confirm-remove": "Are you sure you want to remove {target}?", - "message.confirm-reset": "Are you sure you want to reset {target}'s statistics?", - "message.delete-team-warning": "Deleting a team will also delete all team websites.", - "message.delete-website-warning": "All website data will be deleted.", - "message.error": "Something went wrong.", - "message.event-log": "{event} on {url}", - "message.forbidden": "Forbidden", - "message.go-to-settings": "Go to settings", - "message.incorrect-username-password": "Incorrect username/password.", - "message.invalid-domain": "Invalid domain. Do not include http/https.", - "message.min-password-length": "Minimum length of {n} characters", - "message.new-version-available": "A new version of Umami {version} is available!", - "message.no-data-available": "No data available.", - "message.no-event-data": "No event data is available.", - "message.no-match-password": "Passwords do not match.", - "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": "You do not have any websites configured.", - "message.not-found": "Not found", - "message.nothing-selected": "Nothing selected.", - "message.page-not-found": "Page not found.", - "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 settings will remain intact.", - "message.saved": "Saved.", - "message.sever-error": "Server error", - "message.share-url": "This is the publicly shared URL for {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.tracking-code": "To track stats for this website, place the following code in the ... section of your HTML.", - "message.transfer-team-website-to-user": "Transfer this website to your account?", - "message.transfer-user-website-to-team": "Select the team to transfer this website to.", - "message.transfer-website": "Transfer website ownership to your account or another team.", - "message.triggered-event": "Triggered event", - "message.unauthorized": "Unauthorized", - "message.user-deleted": "User deleted.", - "message.viewed-page": "Viewed page", - "message.visitor-log": "Visitor from {country} using {browser} on {os} {device}" -} diff --git a/src/lang/ar-SA.json b/src/lang/ar-SA.json index 253db02a..b5667c0b 100644 --- a/src/lang/ar-SA.json +++ b/src/lang/ar-SA.json @@ -3,7 +3,7 @@ "label.actions": "الإجراءات", "label.activity": "سجل الأحداث", "label.add": "أضِف", - "label.add-board": "Add board", + "label.add-board": "أضف لوحة", "label.add-description": "أضِف وصف", "label.add-member": "أضِف عضو", "label.add-step": "إضافة خطوة", @@ -14,35 +14,35 @@ "label.all": "الكل", "label.all-time": "كل الوقت", "label.analytics": "تحليلات", - "label.apply": "Apply", + "label.apply": "تطبيق", "label.attribution": "الإسناد", "label.attribution-description": "شاهد كيف يتفاعل المستخدمون مع حملاتك التسويقية وما الذي يحفز التحويلات.", "label.average": "المتوسط", "label.back": "للخلف", "label.before": "قبل", - "label.boards": "Boards", + "label.boards": "لوحات", "label.bounce-rate": "معدل الارتداد", "label.breakdown": "التصنيف", "label.browser": "المتصفح", "label.browsers": "المتصفحات", - "label.campaigns": "Campaigns", + "label.campaigns": "حملات", "label.cancel": "إلغاء", "label.change-password": "تغيير كلمة المرور", - "label.channels": "Channels", + "label.channels": "قنوات", "label.cities": "المدن", "label.city": "المدينة", "label.clear-all": "مسح الكل", - "label.cohort": "Cohort", + "label.cohort": "مجموعة", "label.compare": "المقارنة", - "label.compare-dates": "Compare dates", + "label.compare-dates": "قارن التواريخ", "label.confirm": "تأكيد", "label.confirm-password": "تأكيد كلمة المرور", "label.contains": "يحتوي على", - "label.content": "Content", + "label.content": "المحتوى", "label.continue": "تابع", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "تحويل", + "label.conversion-rate": "معدل التحويل", + "label.conversion-step": "خطوة التحويل", "label.count": "العدد", "label.countries": "الدول", "label.country": "الدولة", @@ -52,7 +52,7 @@ "label.create-user": "أنشِئ مستخدم", "label.created": "أُنشئت", "label.created-by": "أُنشئ من قبل", - "label.currency": "Currency", + "label.currency": "العملة", "label.current": "الحالي", "label.current-password": "كلمة المرور الحالية", "label.custom-range": "فترة مخصّصة", @@ -72,12 +72,12 @@ "label.details": "تفاصيل", "label.device": "الجهاز", "label.devices": "الأجهزة", - "label.direct": "Direct", + "label.direct": "مباشر", "label.dismiss": "تجاهل", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "معرّف مميز", "label.does-not-contain": "لا يحتوي على", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "لا يتضمن", + "label.doest-not-exist": "غير موجود", "label.domain": "النطاق", "label.dropoff": "إنزال", "label.edit": "تعديل", @@ -89,11 +89,11 @@ "label.entry": "رابط الدخول", "label.event": "الحدث", "label.event-data": "تاريخ الحدث", - "label.event-name": "Event name", + "label.event-name": "اسم الحدث", "label.events": "الأحداث", - "label.exists": "Exists", + "label.exists": "موجود", "label.exit": "رابط المغادرة", - "label.expand": "Expand", + "label.expand": "توسيع", "label.false": "خطأ", "label.field": "الحقل", "label.fields": "الحقول", @@ -101,37 +101,37 @@ "label.filter-combined": "مُجمّعة", "label.filter-raw": "خام", "label.filters": "التصفيات", - "label.first-click": "First click", + "label.first-click": "النقرة الأولى", "label.first-seen": "أول ظهور", "label.funnel": "قمع", "label.funnel-description": "فهم معدل التحويل والانقطاع عن المستخدمين.", - "label.funnels": "Funnels", + "label.funnels": "قمعات", "label.goal": "الهدف", "label.goals": "الأهداف", "label.goals-description": "تابع تحقق أهدافك المرتبطة بمشاهدات الصفحات والأحداث.", "label.greater-than": "أكبَر مِن", "label.greater-than-equals": "أكبَر مِن أو يساوي", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "مجمع", + "label.hostname": "اسم المضيف", + "label.includes": "يتضمن", + "label.insight": "رؤية معمقة", "label.insights": "نتائج التحليلات", "label.insights-description": "تعمق في بياناتك باستخدام الشرائح والتصفيات.", "label.is": "يساوي", - "label.is-false": "Is false", + "label.is-false": "غير صحيح", "label.is-not": "لا يساوي", "label.is-not-set": "لم ضُبط", "label.is-set": "ضُبط", - "label.is-true": "Is true", + "label.is-true": "صحيح", "label.join": "انضم", "label.join-team": "انضم للفريق", "label.journey": "رحلة المستخدم", "label.journey-description": "تعرّف على كيفية تنقّل المستخدمين داخل موقعك.", - "label.journeys": "Journeys", + "label.journeys": "رحلات المستخدم", "label.language": "اللغة", "label.languages": "اللغات", "label.laptop": "لابتوب", - "label.last-click": "Last click", + "label.last-click": "النقرة الأخيرة", "label.last-days": "آخر {x} يوم/ايام", "label.last-hours": "آخر {x} ساعة", "label.last-months": "آخر {x} شهر/أشهر", @@ -140,67 +140,67 @@ "label.leave-team": "مغادرة المجموعة", "label.less-than": "أقل مِن", "label.less-than-equals": "أقل مِن أو يساوي", - "label.links": "Links", + "label.links": "روابط", "label.login": "تسجيل الدخول", "label.logout": "تسجيل الخروج", "label.manage": "التحكم", "label.manager": "مدير", "label.max": "الحد الأقصى", - "label.medium": "Medium", + "label.medium": "وسيط", "label.member": "عضو", "label.members": "الأعضاء", "label.min": "الحد الأدنى", "label.mobile": "جوال", - "label.model": "Model", + "label.model": "نموذج", "label.more": "المزيد", "label.my-account": "حسابي", "label.my-websites": "مواقعي", "label.name": "الاسم", "label.new-password": "كلمة مرور جديدة", - "label.none": "غير معرّف", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", + "label.none": "لا شيء", + "label.number-of-records": "{x} {x, plural, one {سجل} other {سجلات}}", "label.ok": "نعم", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "بحث عضوي", + "label.organic-shopping": "تسوق عضوي", + "label.organic-social": "اجتماعي عضوي", + "label.organic-video": "فيديو عضوي", "label.os": "نظام التشغيل", - "label.other": "Other", + "label.other": "أخرى", "label.overview": "نظرة عامة", "label.owner": "المالك", - "label.page": "Page", + "label.page": "صفحة", "label.page-of": "صفحة {current} من {total}", "label.page-views": "مشاهدات الصفحة", "label.pageTitle": "عنوان الصفحة", - "label.pages": "الصفحات", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.pages": "صفحات", + "label.paid-ads": "إعلانات مدفوعة", + "label.paid-search": "بحث مدفوع", + "label.paid-shopping": "تسوق مدفوع", + "label.paid-social": "اجتماعي مدفوع", + "label.paid-video": "فيديو مدفوع", "label.password": "كلمة المرور", - "label.path": "المسار", - "label.paths": "المسارات", - "label.pixels": "Pixels", + "label.path": "مسار", + "label.paths": "مسارات", + "label.pixels": "بكسلات", "label.powered-by": "مشغل بواسطة {name}", "label.previous": "السابق", "label.previous-period": "الفترة السابقة", "label.previous-year": "العام السابق", "label.profile": "الملف الشخصي", - "label.properties": "الخصائص", - "label.property": "الخاصية", + "label.properties": "خصائص", + "label.property": "خاصية", "label.queries": "استعلامات", "label.query": "استعلام", - "label.query-parameters": "متغيرات الرابط", + "label.query-parameters": "معاملات الاستعلام", "label.realtime": "الوقت الفعلي", - "label.referral": "Referral", + "label.referral": "إحالة", "label.referrer": "المرجع", "label.referrers": "التحويلات", "label.refresh": "تحديث", "label.regenerate": "إعادة توليد", "label.region": "المنطقة", "label.regions": "المناطق", - "label.remaining": "Remaining", + "label.remaining": "متبقي", "label.remove": "أزِل", "label.remove-member": "احذف عضو", "label.reports": "التقارير", @@ -218,18 +218,18 @@ "label.search": "بحث", "label.select": "اختر", "label.select-date": "حدد التاريخ", - "label.select-filter": "Select filter", + "label.select-filter": "اختر تصفية", "label.select-role": "حدد الدور", "label.select-website": "حدد موقع", "label.session": "الزيارة", - "label.session-data": "Session data", + "label.session-data": "بيانات الجلسة", "label.sessions": "الزيارات", "label.settings": "الإعدادات", - "label.share": "Share", + "label.share": "مشاركة", "label.share-url": "مشاركة الرابط", "label.single-day": "يوم واحد", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "مصادر", "label.start-step": "الخطوة الأولى", "label.steps": "الخطوات", "label.sum": "المجموع", @@ -242,11 +242,11 @@ "label.team-member": "عضو الفريق", "label.team-name": "اسم الفريق", "label.team-owner": "مدير الفريق", - "label.team-settings": "Team settings", + "label.team-settings": "إعدادات الفريق", "label.team-view-only": "عرض الفريق فقط", "label.team-websites": "مواقع الفريق", "label.teams": "الفرق", - "label.terms": "Terms", + "label.terms": "مصطلحات", "label.theme": "السمة", "label.this-month": "الشهر الحالي", "label.this-week": "الاسبوع الحالي", diff --git a/src/lang/be-BY.json b/src/lang/be-BY.json index 5dcf77be..9e7fa18c 100644 --- a/src/lang/be-BY.json +++ b/src/lang/be-BY.json @@ -3,46 +3,46 @@ "label.actions": "Дзеянні", "label.activity": "Журнал актыўнасці", "label.add": "Дадаць", - "label.add-board": "Add board", + "label.add-board": "Дадаць дошку", "label.add-description": "Дадаць апісанне", "label.add-member": "Дадаць удзельніка", "label.add-step": "Дадаць крок", "label.add-website": "Дадаць сайт", "label.admin": "Адміністратар", - "label.affiliate": "Affiliate", + "label.affiliate": "Партнёр", "label.after": "Пасля", "label.all": "Усё", "label.all-time": "Увесь час", "label.analytics": "Аналітыка", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Ужыць", + "label.attribution": "Атрыбуцыя", + "label.attribution-description": "Глядзіце, як карыстальнікі ўзаемадзейнічаюць з вашым маркетынгам і што прыводзіць да канверсій.", "label.average": "Сярэдняе", "label.back": "Назад", "label.before": "Да", - "label.boards": "Boards", + "label.boards": "Дошкі", "label.bounce-rate": "Паказчык адмоваў", "label.breakdown": "Разбіўка", "label.browser": "Браўзер", "label.browsers": "Браўзеры", - "label.campaigns": "Campaigns", + "label.campaigns": "Кампаніі", "label.cancel": "Адмена", "label.change-password": "Змяніць пароль", - "label.channels": "Channels", + "label.channels": "Каналы", "label.cities": "Гарады", "label.city": "Горад", "label.clear-all": "Ачысціць усё", - "label.cohort": "Cohort", + "label.cohort": "Кагорта", "label.compare": "Параўнаць", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Параўнаць даты", "label.confirm": "Падцвердзіць", "label.confirm-password": "Падцвердзіць пароль", "label.contains": "Уключае", - "label.content": "Content", + "label.content": "Змест", "label.continue": "Працягнуць", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Канверсія", + "label.conversion-rate": "Канверсійная стаўка", + "label.conversion-step": "Крок канверсіі", "label.count": "Колькасць", "label.countries": "Краіны", "label.country": "Краіна", @@ -52,7 +52,7 @@ "label.create-user": "Стварыць карыстальніка", "label.created": "Створана", "label.created-by": "Створана", - "label.currency": "Currency", + "label.currency": "Валюта", "label.current": "Цяперашні", "label.current-password": "Цяперашні пароль", "label.custom-range": "Іншы дыяпазон", @@ -72,12 +72,12 @@ "label.details": "Дэталі", "label.device": "Прылада", "label.devices": "Прылады", - "label.direct": "Direct", + "label.direct": "Прама", "label.dismiss": "Адхіліць", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Унікальны ID", "label.does-not-contain": "Не ўключае", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Не ўключае", + "label.doest-not-exist": "Не існуе", "label.domain": "Дамен", "label.dropoff": "Адмовы", "label.edit": "Змяніць", @@ -89,11 +89,11 @@ "label.entry": "URL уваходу", "label.event": "Падзея", "label.event-data": "Дадзеныя падзеі", - "label.event-name": "Event name", + "label.event-name": "Назва падзеі", "label.events": "Падзеі", - "label.exists": "Exists", + "label.exists": "Існуе", "label.exit": "URL выхаду", - "label.expand": "Expand", + "label.expand": "Разгарнуць", "label.false": "Ложна", "label.field": "Поле", "label.fields": "Палі", @@ -101,37 +101,37 @@ "label.filter-combined": "Камбініраваны", "label.filter-raw": "Сырыя", "label.filters": "Фільтры", - "label.first-click": "First click", - "label.first-seen": "First seen", + "label.first-click": "Першы клік", + "label.first-seen": "Першы раз убачана", "label.funnel": "Варонка", "label.funnel-description": "Разумець паказчыкі канверсіі і адмоваў.", - "label.funnels": "Funnels", + "label.funnels": "Варонкі", "label.goal": "Мэта", "label.goals": "Мэты", "label.goals-description": "Сачыць за мэтамі па праглядах старонак і падзеях.", "label.greater-than": "Больш чым", "label.greater-than-equals": "Больш чым або роўна", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Групаваны", + "label.hostname": "Імя хаста", + "label.includes": "Уключае", + "label.insight": "Інсайт", "label.insights": "Інсайты", "label.insights-description": "Даследваць дадзеныя з дапамогай сегментаў і фільтраў.", "label.is": "З'яўляецца", - "label.is-false": "Is false", + "label.is-false": "Ложна", "label.is-not": "Не з'яўляецца", "label.is-not-set": "Не ўстаноўлена", "label.is-set": "Устаноўлена", - "label.is-true": "Is true", + "label.is-true": "Праўда", "label.join": "Далучыцца", "label.join-team": "Далучыцца да каманды", "label.journey": "Маршрут карыстальніка", "label.journey-description": "Разумець як карыстальнікі навігуюць па сайце.", - "label.journeys": "Journeys", + "label.journeys": "Маршруты", "label.language": "Мова", "label.languages": "Мовы", "label.laptop": "Ноўтбук", - "label.last-click": "Last click", + "label.last-click": "Апошні клік", "label.last-days": "Апошнія {x} дзён", "label.last-hours": "Апошнія {x} гадзіны", "label.last-months": "Апошнія {x} месяцаў", @@ -140,18 +140,18 @@ "label.leave-team": "Пакінуць каманду", "label.less-than": "Менш чым", "label.less-than-equals": "Менш чым або роўна", - "label.links": "Links", + "label.links": "Спасылкі", "label.login": "Увайсці", "label.logout": "Выйсці", "label.manage": "Кіраваць", "label.manager": "Кіраўнік", "label.max": "Максімум", - "label.medium": "Medium", + "label.medium": "Сярэдні", "label.member": "Удзельнік", "label.members": "Удзельнікі", "label.min": "Мінімум", "label.mobile": "Мабільны", - "label.model": "Model", + "label.model": "Мадэль", "label.more": "Болей", "label.my-account": "Мой уліковы запіс", "label.my-websites": "Мае сайты", @@ -160,47 +160,47 @@ "label.none": "Няма", "label.number-of-records": "{x} {x, plural, one {запіс} other {запісаў}}", "label.ok": "ОК", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Арганічны пошук", + "label.organic-shopping": "Арганічныя пакупкі", + "label.organic-social": "Арганічныя сацыяльныя сеткі", + "label.organic-video": "Арганічнае відэа", "label.os": "Аперацыйная сістэма", - "label.other": "Other", + "label.other": "Іншае", "label.overview": "Агляд", "label.owner": "Уласнік", - "label.page": "Page", + "label.page": "Старонка", "label.page-of": "Старонка {current} з {total}", "label.page-views": "Прагляды старонкі", "label.pageTitle": "Загаловак старонкі", "label.pages": "Старонкі", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Платная рэклама", + "label.paid-search": "Платаны пошук", + "label.paid-shopping": "Платныя пакупкі", + "label.paid-social": "Платныя сацыяльныя сеткі", + "label.paid-video": "Платнае відэа", "label.password": "Пароль", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Шлях", + "label.paths": "Шляхи", + "label.pixels": "Пікселі", "label.powered-by": "Зроблена {name}", "label.previous": "Папярэдні", "label.previous-period": "Папярэдні перыяд", "label.previous-year": "Папярэдні год", "label.profile": "Профіль", - "label.properties": "Properties", + "label.properties": "Уласцівасці", "label.property": "Уласцівасць", "label.queries": "Запыты", "label.query": "Запыт", "label.query-parameters": "Параметры запыту", "label.realtime": "У рэяльным часе", - "label.referral": "Referral", + "label.referral": "Рэферал", "label.referrer": "Рэферэр", "label.referrers": "Рэферэры", "label.refresh": "Аднавіць", "label.regenerate": "Рэгенераваць", "label.region": "Рэгіён", "label.regions": "Рэгіёны", - "label.remaining": "Remaining", + "label.remaining": "Засталося", "label.remove": "Выдаліць", "label.remove-member": "Выдаліць удзельніка", "label.reports": "Справаздачы", @@ -218,18 +218,18 @@ "label.search": "Пошук", "label.select": "Выбраць", "label.select-date": "Выбраць дату", - "label.select-filter": "Select filter", + "label.select-filter": "Выбраць фільтр", "label.select-role": "Выбраць ролю", "label.select-website": "Выбраць сайт", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Сесія", + "label.session-data": "Дадзеныя сесіі", "label.sessions": "Сесіі", "label.settings": "Налады", - "label.share": "Share", + "label.share": "Падзяліцца", "label.share-url": "Падзяліцца спасылкай", "label.single-day": "Адзін дзень", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Крыніцы", "label.start-step": "Першы кроку", "label.steps": "Крокі", "label.sum": "Сума", @@ -242,11 +242,11 @@ "label.team-member": "Удзельнік каманды", "label.team-name": "Назва каманды", "label.team-owner": "Уласнік каманды", - "label.team-settings": "Team settings", + "label.team-settings": "Налады каманды", "label.team-view-only": "Толькі для каманднага прагляду", "label.team-websites": "Сайты каманды", "label.teams": "Каманды", - "label.terms": "Terms", + "label.terms": "Тэрміны", "label.theme": "Тэма", "label.this-month": "Гэты месяц", "label.this-week": "Гэты тыдзень", diff --git a/src/lang/bg-BG.json b/src/lang/bg-BG.json index 1934ce3e..3cc7db77 100644 --- a/src/lang/bg-BG.json +++ b/src/lang/bg-BG.json @@ -3,47 +3,47 @@ "label.actions": "Действия", "label.activity": "Активностти", "label.add": "Добави", - "label.add-board": "Add board", + "label.add-board": "Добави дъска", "label.add-description": "Добави описание", "label.add-member": "Добави член", "label.add-step": "Добави стъпка", "label.add-website": "Добави уебсайт", "label.admin": "Администратор", - "label.affiliate": "Affiliate", + "label.affiliate": "Партньор", "label.after": "След", "label.all": "Всички", "label.all-time": "За всички времена", "label.analytics": "Анализи", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Приложи", + "label.attribution": "Атрибуция", + "label.attribution-description": "Вижте как потребителите взаимодействат с вашия маркетинг и какво води до конверсии.", "label.average": "Средно", "label.back": "Назад", "label.before": "Преди", - "label.boards": "Boards", + "label.boards": "Дъски", "label.bounce-rate": "Kоефициент на отказ", "label.breakdown": "Разбивка", "label.browser": "Браузър", "label.browsers": "Браузъри", - "label.campaigns": "Campaigns", + "label.campaigns": "Кампании", "label.cancel": "Отмени", "label.change-password": "Смени парола", - "label.channels": "Channels", + "label.channels": "Канали", "label.cities": "Градове", "label.city": "Град", "label.clear-all": "Изчисти всички", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", + "label.cohort": "Кохорта", + "label.compare": "Сравни", + "label.compare-dates": "Сравни дати", "label.confirm": "Потвърди", "label.confirm-password": "Потвърди парола", "label.contains": "Съдържа", - "label.content": "Content", + "label.content": "Съдържание", "label.continue": "Продължи", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "Конверсия", + "label.conversion-rate": "Процент на конверсия", + "label.conversion-step": "Стъпка на конверсия", + "label.count": "Брой", "label.countries": "Държави", "label.country": "Държава", "label.create": "Създай", @@ -52,8 +52,8 @@ "label.create-user": "Създай потребител", "label.created": "Създадено", "label.created-by": "Създадено от", - "label.currency": "Currency", - "label.current": "Current", + "label.currency": "Валута", + "label.current": "Текущ", "label.current-password": "Текуща парола", "label.custom-range": "Обхват", "label.dashboard": "Табло", @@ -72,28 +72,28 @@ "label.details": "Детайли", "label.device": "Устройство", "label.devices": "Устройства", - "label.direct": "Direct", + "label.direct": "Директно", "label.dismiss": "Отхвърли", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Уникален ID", "label.does-not-contain": "Не съдържа", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Не включва", + "label.doest-not-exist": "Не съществува", "label.domain": "Домейн", "label.dropoff": "Отпадане", "label.edit": "Редактирай", "label.edit-dashboard": "Редактирай табло", "label.edit-member": "Редактирай член", - "label.email": "Email", + "label.email": "Имейл", "label.enable-share-url": "Активирай Линк за споделяне", - "label.end-step": "End Step", - "label.entry": "Entry URL", + "label.end-step": "Крайна стъпка", + "label.entry": "URL на вход", "label.event": "Събитие", "label.event-data": "Данни за събитие", - "label.event-name": "Event name", + "label.event-name": "Име на събитие", "label.events": "Събития", - "label.exists": "Exists", + "label.exists": "Съществува", "label.exit": "Exit URL", - "label.expand": "Expand", + "label.expand": "Разшири", "label.false": "Грешно", "label.field": "Поле", "label.fields": "Полета", @@ -101,37 +101,37 @@ "label.filter-combined": "Комбиниран", "label.filter-raw": "Суров", "label.filters": "Филтри", - "label.first-click": "First click", - "label.first-seen": "First seen", + "label.first-click": "Първо кликване", + "label.first-seen": "Първо видяно", "label.funnel": "Фуния", "label.funnel-description": "Разберете процента на конверсия и отпадане на потребителите.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", + "label.funnels": "Фунии", + "label.goal": "Цел", + "label.goals": "Цели", + "label.goals-description": "Следете целите си за прегледи на страници и събития.", "label.greater-than": "По-голямо от", "label.greater-than-equals": "По-голямо или равно на", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Групирано", + "label.hostname": "Име на хост", + "label.includes": "Включва", + "label.insight": "Прозрение", "label.insights": "Изводи", "label.insights-description": "Навлезте по-дълбоко в данните си, като използвате сегменти и филтри.", "label.is": "Е", - "label.is-false": "Is false", + "label.is-false": "Грешно", "label.is-not": "Не е", "label.is-not-set": "Не е зададено", "label.is-set": "Зададено е", - "label.is-true": "Is true", + "label.is-true": "Вярно", "label.join": "Присъедини се", "label.join-team": "Присъедини се към екип", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.journey": "Пътешествие", + "label.journey-description": "Разберете как потребителите навигират във вашия уебсайт.", + "label.journeys": "Пътешествия", "label.language": "Език", "label.languages": "Езици", "label.laptop": "Лаптоп", - "label.last-click": "Last click", + "label.last-click": "Последно кликване", "label.last-days": "Последните {x} дни", "label.last-hours": "Последните {x} часа", "label.last-months": "Последните {x} месеца", @@ -140,18 +140,18 @@ "label.leave-team": "Напусни екип", "label.less-than": "По-малко от", "label.less-than-equals": "По-малко или равно на", - "label.links": "Links", + "label.links": "Връзки", "label.login": "Вход", "label.logout": "Изход", "label.manage": "Управлявай", - "label.manager": "Manager", + "label.manager": "Мениджър", "label.max": "Максимум", - "label.medium": "Medium", + "label.medium": "Среден", "label.member": "Член", "label.members": "Членове", "label.min": "Минимум", "label.mobile": "Мобилен", - "label.model": "Model", + "label.model": "Модел", "label.more": "Още", "label.my-account": "Моят акаунт", "label.my-websites": "Моите уебсайтове", @@ -160,47 +160,47 @@ "label.none": "Няма", "label.number-of-records": "{x} {x, plural, one {един} other {други}}", "label.ok": "Добре", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Органично търсене", + "label.organic-shopping": "Органично пазаруване", + "label.organic-social": "Органични социални мрежи", + "label.organic-video": "Органично видео", "label.os": "ОС", - "label.other": "Other", + "label.other": "Друго", "label.overview": "Общ преглед", "label.owner": "Собственик", - "label.page": "Page", + "label.page": "Страница", "label.page-of": "Страница {current} от {total}", "label.page-views": "Прегледи на страницата", "label.pageTitle": "Заглавие на страница", "label.pages": "Страници", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Платени реклами", + "label.paid-search": "Платено търсене", + "label.paid-shopping": "Платено пазаруване", + "label.paid-social": "Платени социални мрежи", + "label.paid-video": "Платено видео", "label.password": "Парола", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Път", + "label.paths": "Пътища", + "label.pixels": "Пиксели", "label.powered-by": "Поддържано от {name}", "label.previous": "Previous", "label.previous-period": "Previous period", "label.previous-year": "Previous year", "label.profile": "Профил", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Свойства", + "label.property": "Свойство", "label.queries": "Запитвания", "label.query": "Запитване", "label.query-parameters": "Параметри на търсене", "label.realtime": "В реално време", - "label.referral": "Referral", + "label.referral": "Реферал", "label.referrer": "Референт", "label.referrers": "Референти", "label.refresh": "Обнови", "label.regenerate": "Регенерирай", "label.region": "Регион", "label.regions": "Региони", - "label.remaining": "Remaining", + "label.remaining": "Оставащи", "label.remove": "Премахни", "label.remove-member": "Премахни член", "label.reports": "Отчети", @@ -218,35 +218,35 @@ "label.search": "Търсене", "label.select": "Избери", "label.select-date": "Избери дата", - "label.select-filter": "Select filter", + "label.select-filter": "Избери филтър", "label.select-role": "Избери роля", "label.select-website": "Избери уебсайт", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Сесия", + "label.session-data": "Данни за сесия", "label.sessions": "Сесии", "label.settings": "Настройки", - "label.share": "Share", + "label.share": "Сподели", "label.share-url": "Сподели Линк", "label.single-day": "Един ден", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", + "label.sources": "Източници", + "label.start-step": "Начална стъпка", "label.steps": "Стъпки", "label.sum": "Сума", "label.tablet": "Таблет", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Етикет", + "label.tags": "Етикети", "label.team": "Екип", "label.team-id": "ID на екип", - "label.team-manager": "Team manager", + "label.team-manager": "Мениджър на екип", "label.team-member": "Член на екипа", "label.team-name": "Име на екипа", "label.team-owner": "Собственик на екипа", - "label.team-settings": "Team settings", + "label.team-settings": "Настройки на екипа", "label.team-view-only": "Видимо само за членове на екипа", "label.team-websites": "Уебсайтове на екипа", "label.teams": "Екипи", - "label.terms": "Terms", + "label.terms": "Термини", "label.theme": "Тема", "label.this-month": "Този месец", "label.this-week": "Тази седмица", diff --git a/src/lang/bn-BD.json b/src/lang/bn-BD.json index 5aa00473..77123fa2 100644 --- a/src/lang/bn-BD.json +++ b/src/lang/bn-BD.json @@ -3,47 +3,47 @@ "label.actions": "অ্যাকশনস", "label.activity": "একটিভিটি দেখুন", "label.add": "যুক্ত করুন", - "label.add-board": "Add board", + "label.add-board": "বোর্ড যুক্ত করুন", "label.add-description": "বর্ননা যোগ করুন", "label.add-member": "সদস্য যোগ করুন", "label.add-step": "পদ যোগ করুন", "label.add-website": "ওয়েবসাইট যুক্ত করুন", "label.admin": "অ্যাডমিন", - "label.affiliate": "Affiliate", + "label.affiliate": "সহযোগী", "label.after": "পরে", "label.all": "সবগুলো", "label.all-time": "সব সময়", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.analytics": "বিশ্লেষণ", + "label.apply": "প্রয়োগ করুন", + "label.attribution": "অ্যাট্রিবিউশন", + "label.attribution-description": "দেখুন ব্যবহারকারীরা কীভাবে আপনার মার্কেটিংয়ের সাথে যুক্ত হয় এবং কীভাবে রূপান্তর ঘটে।", + "label.average": "গড়", "label.back": "পেছনে", "label.before": "পূর্বে", - "label.boards": "Boards", + "label.boards": "বোর্ডসমূহ", "label.bounce-rate": "উপরে উঠার হার", "label.breakdown": "ভাঙ্গন", "label.browser": "ব্রাউজার", "label.browsers": "ব্রাউজার সমূহ", - "label.campaigns": "Campaigns", + "label.campaigns": "প্রচারণা", "label.cancel": "বাতিল", "label.change-password": "পাসওয়ার্ড পরিবর্তন করুন", - "label.channels": "Channels", + "label.channels": "চ্যানেলসমূহ", "label.cities": "শহরসমূহ", "label.city": "শহর", "label.clear-all": "সব মুছে ফেলুন", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", + "label.cohort": "কোহর্ট", + "label.compare": "তুলনা করুন", + "label.compare-dates": "তারিখ তুলনা করুন", "label.confirm": "নিশ্চিত করুন", "label.confirm-password": "পাসওয়ার্ড নিশ্চিত করুন", "label.contains": "রয়েছে", - "label.content": "Content", + "label.content": "বিষয়বস্তু", "label.continue": "পরবর্তিতে", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "রূপান্তর", + "label.conversion-rate": "রূপান্তর হার", + "label.conversion-step": "রূপান্তর ধাপ", + "label.count": "গণনা", "label.countries": "দেশসমূহ", "label.country": "দেশ", "label.create": "তৈরি করুন", @@ -51,156 +51,156 @@ "label.create-team": "দল তৈরি করুন", "label.create-user": "ব্যবহারকারী তৈরি করুন", "label.created": "তৈরি করা হয়েছে", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.created-by": "তৈরি করেছেন", + "label.currency": "মুদ্রা", + "label.current": "বর্তমান", "label.current-password": "বর্তমান পাসওয়ার্ড", "label.custom-range": "কাস্টম রেঞ্জ", "label.dashboard": "ড্যাশবোর্ড", - "label.data": "Data", - "label.date": "Date", + "label.data": "ডেটা", + "label.date": "তারিখ", "label.date-range": "তারিখের পরিসীমা", - "label.day": "Day", + "label.day": "দিন", "label.default-date-range": "ডিফল্ট তারিখের পরিসীমা", "label.delete": "মুছে ফেলুন", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "রিপোর্ট মুছুন", + "label.delete-team": "দল মুছুন", + "label.delete-user": "ব্যবহারকারী মুছুন", "label.delete-website": "ওয়েবসাইট মুছুন", - "label.description": "Description", + "label.description": "বর্ণনা", "label.desktop": "ডেস্কটপ", - "label.details": "Details", - "label.device": "Device", + "label.details": "বিস্তারিত", + "label.device": "ডিভাইস", "label.devices": "ডিভাইস গুলো", - "label.direct": "Direct", + "label.direct": "সরাসরি", "label.dismiss": "বাতিল", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "স্বতন্ত্র আইডি", + "label.does-not-contain": "ধারণ করে না", + "label.does-not-include": "অন্তর্ভুক্ত নয়", + "label.doest-not-exist": "অস্তিত্ব নেই", "label.domain": "ডোমেইন", - "label.dropoff": "Dropoff", + "label.dropoff": "ছেড়ে যাওয়া", "label.edit": "সম্পাদনা করুন", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", + "label.edit-dashboard": "ড্যাশবোর্ড সম্পাদনা করুন", + "label.edit-member": "সদস্য সম্পাদনা করুন", "label.email": "Email", "label.enable-share-url": "শেয়ার ইউআরএল শেয়ার করুন", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "শেষ ধাপ", + "label.entry": "প্রবেশ URL", + "label.event": "ইভেন্ট", + "label.event-data": "ইভেন্ট ডেটা", + "label.event-name": "ইভেন্টের নাম", "label.events": "ঘটনা", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", - "label.filter": "Filter", + "label.exists": "অস্তিত্ব আছে", + "label.exit": "প্রস্থান URL", + "label.expand": "বিস্তৃত করুন", + "label.false": "মিথ্যা", + "label.field": "ক্ষেত্র", + "label.fields": "ক্ষেত্রসমূহ", + "label.filter": "ফিল্টার", "label.filter-combined": "সম্মিলিত", "label.filter-raw": "অপরিশোধিত", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.filters": "ফিল্টারসমূহ", + "label.first-click": "প্রথম ক্লিক", + "label.first-seen": "প্রথম দেখা", + "label.funnel": "ফানেল", + "label.funnel-description": "ব্যবহারকারীদের রূপান্তর ও ছেড়ে যাওয়ার হার বুঝুন।", + "label.funnels": "ফানেলসমূহ", + "label.goal": "লক্ষ্য", + "label.goals": "লক্ষ্যসমূহ", + "label.goals-description": "পৃষ্ঠাদর্শন ও ইভেন্টের লক্ষ্য ট্র্যাক করুন।", + "label.greater-than": "এর চেয়ে বেশি", + "label.greater-than-equals": "এর চেয়ে বেশি বা সমান", + "label.grouped": "গ্রুপ করা", + "label.hostname": "হোস্টনেম", + "label.includes": "অন্তর্ভুক্ত", + "label.insight": "অন্তর্দৃষ্টি", "label.insights": "Insights", "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.is": "হয়", + "label.is-false": "মিথ্যা", + "label.is-not": "নয়", + "label.is-not-set": "নির্ধারিত নয়", + "label.is-set": "নির্ধারিত", + "label.is-true": "সত্য", + "label.join": "যোগ দিন", + "label.join-team": "দলে যোগ দিন", + "label.journey": "যাত্রা", + "label.journey-description": "ব্যবহারকারীরা কীভাবে আপনার ওয়েবসাইটে নেভিগেট করে তা বুঝুন।", + "label.journeys": "যাত্রাসমূহ", "label.language": "ভাষা", "label.languages": "ভাষা", "label.laptop": "ল্যাপটপ", - "label.last-click": "Last click", + "label.last-click": "শেষ ক্লিক", "label.last-days": "শেষ {x} দিন", "label.last-hours": "শেষ {x} ঘন্টা", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "শেষ {x} মাস", + "label.last-seen": "শেষ দেখা", + "label.leave": "ত্যাগ করুন", + "label.leave-team": "দল ত্যাগ করুন", + "label.less-than": "এর চেয়ে কম", + "label.less-than-equals": "এর চেয়ে কম বা সমান", + "label.links": "লিঙ্কসমূহ", "label.login": "লগিন", "label.logout": "লগ আউট", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.manage": "পরিচালনা করুন", + "label.manager": "পরিচালক", + "label.max": "সর্বাধিক", + "label.medium": "মাঝারি", + "label.member": "সদস্য", + "label.members": "সদস্যগণ", + "label.min": "সর্বনিম্ন", "label.mobile": "মুঠোফোন", - "label.model": "Model", + "label.model": "মডেল", "label.more": "আরও", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "আমার অ্যাকাউন্ট", + "label.my-websites": "আমার ওয়েবসাইটসমূহ", "label.name": "নাম", "label.new-password": "নতুন পাসওয়ার্ড", "label.none": "কিছুই না", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "অর্গানিক সার্চ", + "label.organic-shopping": "অর্গানিক শপিং", + "label.organic-social": "অর্গানিক সোশ্যাল", + "label.organic-video": "অর্গানিক ভিডিও", "label.os": "OS", - "label.other": "Other", + "label.other": "অন্যান্য", "label.overview": "Overview", "label.owner": "মালিক", - "label.page": "Page", + "label.page": "পৃষ্ঠা", "label.page-of": "Page {current} of {total}", "label.page-views": "পৃষ্ঠা পরিদর্শন গুলো", "label.pageTitle": "Page title", "label.pages": "পৃষ্ঠাগুলি", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "পেইড বিজ্ঞাপন", + "label.paid-search": "পেইড সার্চ", + "label.paid-shopping": "পেইড শপিং", + "label.paid-social": "পেইড সোশ্যাল", + "label.paid-video": "পেইড ভিডিও", "label.password": "পাসওয়ার্ড", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "পথ", + "label.paths": "পথসমূহ", + "label.pixels": "পিক্সেল", "label.powered-by": "{name} দ্বারা চালিত", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "পূর্ববর্তী", + "label.previous-period": "পূর্ববর্তী সময়কাল", + "label.previous-year": "গত বছর", "label.profile": "প্রোফাইল", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "বৈশিষ্ট্যসমূহ", + "label.property": "বৈশিষ্ট্য", "label.queries": "Queries", "label.query": "Query", "label.query-parameters": "Query parameters", "label.realtime": "সরাসরি", - "label.referral": "Referral", + "label.referral": "রেফারেল", "label.referrer": "Referrer", "label.referrers": "রেফারার্স", "label.refresh": "রিফ্রেশ", "label.regenerate": "Regenerate", "label.region": "Region", "label.regions": "Regions", - "label.remaining": "Remaining", + "label.remaining": "বাকি আছে", "label.remove": "Remove", "label.remove-member": "Remove member", "label.reports": "Reports", @@ -209,8 +209,8 @@ "label.reset-website": "ওয়েবসাইট রিসেট করুন", "label.retention": "Retention", "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "আয়", + "label.revenue-description": "সময়ের সাথে সাথে আপনার আয় দেখুন।", "label.role": "Role", "label.run-query": "Run query", "label.save": "সংরক্ষণ", @@ -218,35 +218,35 @@ "label.search": "Search", "label.select": "Select", "label.select-date": "Select date", - "label.select-filter": "Select filter", + "label.select-filter": "ফিল্টার নির্বাচন করুন", "label.select-role": "Select role", "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "সেশন", + "label.session-data": "সেশন ডেটা", "label.sessions": "Sessions", "label.settings": "সেটিংস", - "label.share": "Share", - "label.share-url": "ইউআরএল শেয়ার করুন", + "label.share": "শেয়ার করুন", + "label.share-url": "এটি {target} এর জন্য প্রকাশ্যে শেয়ার করার ইউআরএল।", "label.single-day": "একদিন", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "উৎসসমূহ", "label.start-step": "Start Step", "label.steps": "Steps", "label.sum": "Sum", "label.tablet": "ট্যাবলেট", - "label.tag": "Tag", - "label.tags": "Tags", - "label.team": "Team", - "label.team-id": "Team ID", - "label.team-manager": "Team manager", - "label.team-member": "Team member", - "label.team-name": "Team name", - "label.team-owner": "Team owner", - "label.team-settings": "Team settings", + "label.tag": "ট্যাগ", + "label.tags": "ট্যাগসমূহ", + "label.team": "দল", + "label.team-id": "দল আইডি", + "label.team-manager": "দল ব্যবস্থাপক", + "label.team-member": "দলের সদস্য", + "label.team-name": "দলের নাম", + "label.team-owner": "দলের মালিক", + "label.team-settings": "দলের সেটিংস", "label.team-view-only": "Team view only", "label.team-websites": "Team websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "শর্তাবলী", "label.theme": "থিম", "label.this-month": "এই মাস", "label.this-week": "এই সপ্তাহ", diff --git a/src/lang/bs-BA.json b/src/lang/bs-BA.json index 5ae76432..d6d665fb 100644 --- a/src/lang/bs-BA.json +++ b/src/lang/bs-BA.json @@ -3,47 +3,47 @@ "label.actions": "Akcije", "label.activity": "Log aktivnosti", "label.add": "Dodaj", - "label.add-board": "Add board", + "label.add-board": "Dodaj ploču", "label.add-description": "Dodaj opis", "label.add-member": "Dodaj člana", "label.add-step": "Dodaj korak", "label.add-website": "Dodaj web stranicu", "label.admin": "Administrator", - "label.affiliate": "Affiliate", + "label.affiliate": "Partner", "label.after": "Nakon", "label.all": "Sve", "label.all-time": "Cijelo vrijeme", "label.analytics": "Analitike", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Primijeni", + "label.attribution": "Atribucija", + "label.attribution-description": "Pogledajte kako korisnici komuniciraju s vašim marketingom i šta dovodi do konverzija.", "label.average": "Prosjek", "label.back": "Nazad", "label.before": "Prije", - "label.boards": "Boards", - "label.bounce-rate": "Bounce rate", + "label.boards": "Ploče", + "label.bounce-rate": "Stopa napuštanja", "label.breakdown": "Pregled po kategorijama", "label.browser": "Browser", "label.browsers": "Browseri", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampanje", "label.cancel": "Otkaži", "label.change-password": "Promijeni šifru", - "label.channels": "Channels", + "label.channels": "Kanali", "label.cities": "Gradovi", "label.city": "Grad", "label.clear-all": "Očisti sve", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", + "label.cohort": "Kohorta", + "label.compare": "Uporedi", + "label.compare-dates": "Uporedi datume", "label.confirm": "Potvrdi", "label.confirm-password": "Potvrdi šifru", "label.contains": "Sadrži", - "label.content": "Content", + "label.content": "Sadržaj", "label.continue": "Nastavi", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "Konverzija", + "label.conversion-rate": "Stopa konverzije", + "label.conversion-step": "Korak konverzije", + "label.count": "Broj", "label.countries": "Zemlje", "label.country": "Zemlja", "label.create": "Kreiraj", @@ -52,8 +52,8 @@ "label.create-user": "Kreiraj korisnika", "label.created": "Kreiraj", "label.created-by": "Kreirao", - "label.currency": "Currency", - "label.current": "Current", + "label.currency": "Valuta", + "label.current": "Trenutno", "label.current-password": "Trenutna šifra", "label.custom-range": "Proizvoljni raspon", "label.dashboard": "Dashboard", @@ -72,28 +72,28 @@ "label.details": "Detalji", "label.device": "Uređaj", "label.devices": "Uređaji", - "label.direct": "Direct", + "label.direct": "Direktno", "label.dismiss": "Odbaci", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Jedinstveni ID", "label.does-not-contain": "Ne sadrži", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Ne uključuje", + "label.doest-not-exist": "Ne postoji", "label.domain": "Domena", - "label.dropoff": "Dropoff", + "label.dropoff": "Odlazak", "label.edit": "Uredi", "label.edit-dashboard": "Uredi dashboard", "label.edit-member": "Uredi člana", - "label.email": "Email", + "label.email": "E-mail", "label.enable-share-url": "Omogući URL za dijeljenje", - "label.end-step": "End Step", - "label.entry": "Entry URL", + "label.end-step": "Završni korak", + "label.entry": "URL ulaza", "label.event": "Događaj", "label.event-data": "Podaci o događaju", - "label.event-name": "Event name", + "label.event-name": "Naziv događaja", "label.events": "Događaji", - "label.exists": "Exists", + "label.exists": "Postoji", "label.exit": "Exit URL", - "label.expand": "Expand", + "label.expand": "Proširi", "label.false": "Ne", "label.field": "Polje", "label.fields": "Polja", @@ -101,37 +101,37 @@ "label.filter-combined": "Kombinovano", "label.filter-raw": "Sirovo", "label.filters": "Filtri", - "label.first-click": "First click", - "label.first-seen": "First seen", + "label.first-click": "Prvi klik", + "label.first-seen": "Prvi put viđeno", "label.funnel": "Lijevak", "label.funnel-description": "Razumite koverziju i drop-off učestalost korisnika.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", + "label.funnels": "Lijevci", + "label.goal": "Cilj", + "label.goals": "Ciljevi", + "label.goals-description": "Pratite svoje ciljeve za prikaze stranica i događaje.", "label.greater-than": "Veće od", "label.greater-than-equals": "Veće od ili jednako", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Grupisano", + "label.hostname": "Naziv hosta", + "label.includes": "Uključuje", + "label.insight": "Uvid", "label.insights": "Uvidi", "label.insights-description": "Zaronite dublje u vaše podatke korištenjem segmenata i filtera", "label.is": "Jeste", - "label.is-false": "Is false", + "label.is-false": "Nije tačno", "label.is-not": "Nije", "label.is-not-set": "Nije setano", "label.is-set": "Jeste setano", - "label.is-true": "Is true", + "label.is-true": "Tačno", "label.join": "Učlani se", "label.join-team": "Učlani se u tim", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.journey": "Putovanje", + "label.journey-description": "Saznajte kako korisnici navigiraju vašom web stranicom.", + "label.journeys": "Putovanja", "label.language": "Jezik", "label.languages": "Jezici", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Zadnji klik", "label.last-days": "Zadnjih {x} dana", "label.last-hours": "Zadnjih {x} sati", "label.last-months": "Zadnjih {x} mjeseci", @@ -140,13 +140,13 @@ "label.leave-team": "Napusti tim", "label.less-than": "Manje od", "label.less-than-equals": "Manje od ili jednako", - "label.links": "Links", + "label.links": "Linkovi", "label.login": "Login", "label.logout": "Logout", "label.manage": "Manage", - "label.manager": "Manager", + "label.manager": "Menadžer", "label.max": "Max", - "label.medium": "Medium", + "label.medium": "Srednje", "label.member": "Član", "label.members": "Članovi", "label.min": "Min", @@ -157,60 +157,60 @@ "label.my-websites": "Moje web stranice", "label.name": "Ime", "label.new-password": "Nova šifra", - "label.none": "None", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", + "label.none": "Nijedno", + "label.number-of-records": "{x} {x, plural, one {zapis} other {zapisa}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organska pretraga", + "label.organic-shopping": "Organska kupovina", + "label.organic-social": "Organske društvene mreže", + "label.organic-video": "Organski video", "label.os": "OS", - "label.other": "Other", + "label.other": "Drugo", "label.overview": "Pregled", "label.owner": "Vlasnik", - "label.page": "Page", + "label.page": "Stranica", "label.page-of": "Strana {current} od {total}", "label.page-views": "Pregleda stranica", "label.pageTitle": "Naslov stranice", "label.pages": "Stranice", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Plaćeni oglasi", + "label.paid-search": "Plaćena pretraga", + "label.paid-shopping": "Plaćena kupovina", + "label.paid-social": "Plaćene društvene mreže", + "label.paid-video": "Plaćeni video", "label.password": "Šifra", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Putanja", + "label.paths": "Putanje", + "label.pixels": "Pikseli", "label.powered-by": "Omogućeno s {name}", "label.previous": "Previous", "label.previous-period": "Previous period", "label.previous-year": "Previous year", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queryji", - "label.query": "Query", - "label.query-parameters": "Query parametri", + "label.properties": "Svojstva", + "label.property": "Svojstvo", + "label.queries": "Upiti", + "label.query": "Upit", + "label.query-parameters": "Parametri upita", "label.realtime": "Realno vrijeme", - "label.referral": "Referral", - "label.referrer": "Referrer", - "label.referrers": "Referrers", - "label.refresh": "Refresh", + "label.referral": "Preporuka", + "label.referrer": "Preporučilac", + "label.referrers": "Preporučioci", + "label.refresh": "Osvježi", "label.regenerate": "Regeneriši", "label.region": "Region", "label.regions": "Regioni", - "label.remaining": "Remaining", + "label.remaining": "Preostalo", "label.remove": "Ukloni", "label.remove-member": "Ukloni člana", "label.reports": "Izvještaji", - "label.required": "Required", + "label.required": "Obavezno", "label.reset": "Resetuj", "label.reset-website": "Resetuj web stranicu", - "label.retention": "Retention", + "label.retention": "Zadržavanje", "label.retention-description": "Izmjeri 'ljepljivost' svoje web stranice praćenjem koliko često set korisnici vraćaju.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Prihod", + "label.revenue-description": "Pogledajte svoje prihode tokom vremena.", "label.role": "Rola", "label.run-query": "Pokreni query", "label.save": "Sačuvaj", @@ -218,35 +218,35 @@ "label.search": "Traži", "label.select": "Odaberi", "label.select-date": "Odaberi datum", - "label.select-filter": "Select filter", + "label.select-filter": "Odaberi filter", "label.select-role": "Odaberi rolu", "label.select-website": "Odaberi web stranicu", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Sesija", + "label.session-data": "Podaci o sesiji", "label.sessions": "Sesije", "label.settings": "Postavke", - "label.share": "Share", - "label.share-url": "Share URL", + "label.share": "Podijeli", + "label.share-url": "URL za dijeljenje", "label.single-day": "Jedan dan", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", + "label.sources": "Izvori", + "label.start-step": "Početni korak", "label.steps": "Koraci", "label.sum": "Suma", "label.tablet": "Tablet", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Oznaka", + "label.tags": "Oznake", "label.team": "Tim", "label.team-id": "Tim ID", - "label.team-manager": "Team manager", + "label.team-manager": "Menadžer tima", "label.team-member": "Član tima", "label.team-name": "Naziv tima", "label.team-owner": "Vlasnik tima", - "label.team-settings": "Team settings", + "label.team-settings": "Postavke tima", "label.team-view-only": "Samo tim može vidjeti", "label.team-websites": "Timske web stranice", "label.teams": "Timovi", - "label.terms": "Terms", + "label.terms": "Pojmovi", "label.theme": "Teme", "label.this-month": "Ovaj mjesec", "label.this-week": "Ova sedmica", diff --git a/src/lang/ca-ES.json b/src/lang/ca-ES.json index 4b8f988b..9264de7c 100644 --- a/src/lang/ca-ES.json +++ b/src/lang/ca-ES.json @@ -3,46 +3,46 @@ "label.actions": "Accions", "label.activity": "Registre d'activitat", "label.add": "Afegir", - "label.add-board": "Add board", + "label.add-board": "Afegir tauler", "label.add-description": "Afegir descripció", "label.add-member": "Afegir membre", "label.add-step": "Afegir pas", "label.add-website": "Afegir lloc web", "label.admin": "Administrador", - "label.affiliate": "Affiliate", + "label.affiliate": "Afiliat", "label.after": "Després", "label.all": "Tots", "label.all-time": "Sempre", "label.analytics": "Analítiques", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Aplica", + "label.attribution": "Atribució", + "label.attribution-description": "Vegeu com els usuaris interactuen amb el vostre màrqueting i què impulsa les conversions.", "label.average": "Mitjana", "label.back": "Enrere", "label.before": "Abans", - "label.boards": "Boards", + "label.boards": "Taulers", "label.bounce-rate": "Percentatge de rebot", "label.breakdown": "Desglossament", "label.browser": "Navegador", "label.browsers": "Navegadors", - "label.campaigns": "Campaigns", + "label.campaigns": "Campanyes", "label.cancel": "Cancel·la", "label.change-password": "Canvia la contrasenya", - "label.channels": "Channels", + "label.channels": "Canals", "label.cities": "Ciutats", "label.city": "Ciutat", "label.clear-all": "Netejar tot", "label.cohort": "Cohort", "label.compare": "Comparar", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Comparar dates", "label.confirm": "Confirmar", "label.confirm-password": "Confirma la contrasenya", "label.contains": "Conté", - "label.content": "Content", + "label.content": "Contingut", "label.continue": "Continuar", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Conversió", + "label.conversion-rate": "Taxa de conversió", + "label.conversion-step": "Pas de conversió", "label.count": "Recompte", "label.countries": "Països", "label.country": "País", @@ -52,7 +52,7 @@ "label.create-user": "Crear usuari", "label.created": "Creat", "label.created-by": "Creat Per", - "label.currency": "Currency", + "label.currency": "Moneda", "label.current": "Actual", "label.current-password": "Contrasenya actual", "label.custom-range": "Rang personalitzat", @@ -72,12 +72,12 @@ "label.details": "Detalls", "label.device": "Dispositiu", "label.devices": "Dispositius", - "label.direct": "Direct", + "label.direct": "Directe", "label.dismiss": "Descarta", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "ID distintiu", "label.does-not-contain": "No conté", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "No inclou", + "label.doest-not-exist": "No existeix", "label.domain": "Domini", "label.dropoff": "Abandonament", "label.edit": "Edita", @@ -89,11 +89,11 @@ "label.entry": "URL d'entrada", "label.event": "Esdeveniment", "label.event-data": "Dades de l'esdeveniment", - "label.event-name": "Event name", + "label.event-name": "Nom de l'esdeveniment", "label.events": "Esdeveniments", - "label.exists": "Exists", + "label.exists": "Existeix", "label.exit": "URL de sortida", - "label.expand": "Expand", + "label.expand": "Expandeix", "label.false": "Fals", "label.field": "Camp", "label.fields": "Camps", @@ -101,37 +101,37 @@ "label.filter-combined": "Combinat", "label.filter-raw": "En cru", "label.filters": "Filtres", - "label.first-click": "First click", + "label.first-click": "Primer clic", "label.first-seen": "Vist per primer cop", "label.funnel": "Embut", "label.funnel-description": "Entengui la taxa de conversió i abandonament dels usuaris.", - "label.funnels": "Funnels", + "label.funnels": "Embuts", "label.goal": "Meta", "label.goals": "Metes", "label.goals-description": "Feu un seguiment de les seves metes per a pàgines vistes i esdeveniments.", "label.greater-than": "Més gran que", "label.greater-than-equals": "Més gran que o igual a", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Agrupat", + "label.hostname": "Nom de host", + "label.includes": "Inclou", + "label.insight": "Visió", "label.insights": "Insights", "label.insights-description": "Aprofundeixi en les seves dades mitjançant l'ús de segments i filtres.", "label.is": "És igual a", - "label.is-false": "Is false", + "label.is-false": "És fals", "label.is-not": "No és igual a", "label.is-not-set": "No està establert", "label.is-set": "Està establert", - "label.is-true": "Is true", + "label.is-true": "És cert", "label.join": "Unir", "label.join-team": "Unir-se al equip", "label.journey": "Trajecte", "label.journey-description": "Entengui com naveguen els usuaris pel seu lloc web.", - "label.journeys": "Journeys", + "label.journeys": "Trajectes", "label.language": "Idioma", "label.languages": "Idiomes", "label.laptop": "Portàtil", - "label.last-click": "Last click", + "label.last-click": "Últim clic", "label.last-days": "Últims {x} dies", "label.last-hours": "Últimes {x} hores", "label.last-months": "Últims {x} mesos", @@ -140,13 +140,13 @@ "label.leave-team": "Abandonar equip", "label.less-than": "Menor que", "label.less-than-equals": "Menor que o igual a", - "label.links": "Links", + "label.links": "Enllaços", "label.login": "Connecta't", "label.logout": "Desconnecta't", "label.manage": "Administrar", - "label.manager": "Manager", + "label.manager": "Responsable", "label.max": "Màx", - "label.medium": "Medium", + "label.medium": "Mitjà", "label.member": "Membre", "label.members": "Membres", "label.min": "Mín", @@ -160,24 +160,24 @@ "label.none": "Cap", "label.number-of-records": "{x} {x, plural, one {registre} other {registres}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Cerca orgànica", + "label.organic-shopping": "Compra orgànica", + "label.organic-social": "Social orgànic", + "label.organic-video": "Vídeo orgànic", "label.os": "SO", - "label.other": "Other", + "label.other": "Altres", "label.overview": "Resum", "label.owner": "Propietari", - "label.page": "Page", + "label.page": "Pàgina", "label.page-of": "Pàgina {current} de {total}", "label.page-views": "Pàgines vistes", "label.pageTitle": "Títol de la pàgina", "label.pages": "Pàgines", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Anuncis de pagament", + "label.paid-search": "Cerca de pagament", + "label.paid-shopping": "Compra de pagament", + "label.paid-social": "Social de pagament", + "label.paid-video": "Vídeo de pagament", "label.password": "Contrasenya", "label.path": "Camí", "label.paths": "Camins", @@ -193,14 +193,14 @@ "label.query": "Consulta", "label.query-parameters": "Paràmetres de consulta", "label.realtime": "Temps real", - "label.referral": "Referral", + "label.referral": "Referència", "label.referrer": "Referent", "label.referrers": "Referents", "label.refresh": "Refresca", "label.regenerate": "Regenerar", "label.region": "Regió", "label.regions": "Regions", - "label.remaining": "Remaining", + "label.remaining": "Restant", "label.remove": "Treure", "label.remove-member": "Eliminar membre", "label.reports": "Informes", @@ -218,35 +218,35 @@ "label.search": "Buscar", "label.select": "Seleccionar", "label.select-date": "Seleccionar data", - "label.select-filter": "Select filter", + "label.select-filter": "Seleccionar filtre", "label.select-role": "Seleccionar rol", "label.select-website": "Seleccionar lloc web", "label.session": "Sessió", - "label.session-data": "Session data", + "label.session-data": "Dades de sessió", "label.sessions": "Sessions", "label.settings": "Configuració", - "label.share": "Share", + "label.share": "Comparteix", "label.share-url": "Enllaç per compartir", "label.single-day": "Un sol dia", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Fonts", "label.start-step": "Pas inicial", "label.steps": "Pasos", "label.sum": "Suma", "label.tablet": "Tauleta", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Etiqueta", + "label.tags": "Etiquetes", "label.team": "Equip", "label.team-id": "ID del equip", "label.team-manager": "Responsable d'equip", "label.team-member": "Membre de l'equip", "label.team-name": "Nom de l'equip", "label.team-owner": "Propietari de l'equip", - "label.team-settings": "Team settings", + "label.team-settings": "Configuració de l'equip", "label.team-view-only": "Vista només de l'equip", "label.team-websites": "Llocs web de l'equip", "label.teams": "Equips", - "label.terms": "Terms", + "label.terms": "Termes", "label.theme": "Tema", "label.this-month": "Aquest mes", "label.this-week": "Aquesta setmana", diff --git a/src/lang/cs-CZ.json b/src/lang/cs-CZ.json index 05e18f81..bf6ae63e 100644 --- a/src/lang/cs-CZ.json +++ b/src/lang/cs-CZ.json @@ -3,46 +3,46 @@ "label.actions": "Akce", "label.activity": "Log aktivity", "label.add": "Přidat", - "label.add-board": "Add board", + "label.add-board": "Přidat nástěnku", "label.add-description": "Přidat popis", "label.add-member": "Přidat člena", "label.add-step": "Přidat krok", "label.add-website": "Přidat web", "label.admin": "Administrátor", - "label.affiliate": "Affiliate", + "label.affiliate": "Partner", "label.after": "Po", "label.all": "Vše", "label.all-time": "Celá doba", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.analytics": "Analytika", + "label.apply": "Použít", + "label.attribution": "Atribuce", + "label.attribution-description": "Podívejte se, jak uživatelé interagují s vaším marketingem a co vede ke konverzím.", "label.average": "Průměr", "label.back": "Zpět", "label.before": "Před", - "label.boards": "Boards", + "label.boards": "Nástěnky", "label.bounce-rate": "Okamžité opuštění", - "label.breakdown": "Breakdown", + "label.breakdown": "Rozpis", "label.browser": "Prohlížeč", "label.browsers": "Prohlížeče", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampaně", "label.cancel": "Zrušit", "label.change-password": "Změnit heslo", - "label.channels": "Channels", + "label.channels": "Kanály", "label.cities": "Města", "label.city": "Město", "label.clear-all": "Vyčistit vše", - "label.cohort": "Cohort", + "label.cohort": "Kohorta", "label.compare": "Porovnat", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Porovnat data", "label.confirm": "Potvrdit", "label.confirm-password": "Potvrdit heslo", "label.contains": "Obsahuje", - "label.content": "Content", + "label.content": "Obsah", "label.continue": "Pokračovat", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Konverze", + "label.conversion-rate": "Míra konverze", + "label.conversion-step": "Krok konverze", "label.count": "Počet", "label.countries": "Státy", "label.country": "Stát", @@ -52,7 +52,7 @@ "label.create-user": "Vytvořit uživatele", "label.created": "Vytvořeno", "label.created-by": "Created By", - "label.currency": "Currency", + "label.currency": "Měna", "label.current": "Aktuální", "label.current-password": "Aktuální heslo", "label.custom-range": "Vlastní rozsah", @@ -72,81 +72,81 @@ "label.details": "Detaily", "label.device": "Zařízení", "label.devices": "Zařízení", - "label.direct": "Direct", + "label.direct": "Přímý", "label.dismiss": "Odejít", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Jedinečné ID", "label.does-not-contain": "Neobsahuje", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Nezahrnuje", + "label.doest-not-exist": "Neexistuje", "label.domain": "Doména", - "label.dropoff": "Dropoff", + "label.dropoff": "Opuštění", "label.edit": "Upravit", "label.edit-dashboard": "Upravit dashboard", "label.edit-member": "Upravit člena", - "label.email": "Email", + "label.email": "E-mail", "label.enable-share-url": "Povolit sdílení URL", - "label.end-step": "End Step", + "label.end-step": "Konečný krok", "label.entry": "Vstupní URL", "label.event": "Událost", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.event-data": "Data události", + "label.event-name": "Název události", "label.events": "Události", - "label.exists": "Exists", + "label.exists": "Existuje", "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", + "label.expand": "Rozbalit", + "label.false": "Nepravda", "label.field": "Pole", - "label.fields": "Fields", + "label.fields": "Pole", "label.filter": "Filtr", "label.filter-combined": "Kombinace", "label.filter-raw": "Nezpracované", "label.filters": "Filtry", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", + "label.first-click": "První kliknutí", + "label.first-seen": "Poprvé viděno", + "label.funnel": "Trychtýř", "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", + "label.funnels": "Trychtýře", "label.goal": "Cíl", "label.goals": "Cíle", "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.greater-than": "Větší než", + "label.greater-than-equals": "Větší nebo rovno", + "label.grouped": "Seskupeno", + "label.hostname": "Název hostitele", + "label.includes": "Zahrnuje", + "label.insight": "Pohled", + "label.insights": "Pohledy", + "label.insights-description": "Ponořte se hlouběji do svých dat pomocí segmentů a filtrů.", + "label.is": "Je", + "label.is-false": "Nepravda", + "label.is-not": "Není", + "label.is-not-set": "Není nastaveno", + "label.is-set": "Nastaveno", + "label.is-true": "Pravda", + "label.join": "Připojit se", + "label.join-team": "Připojit se k týmu", + "label.journey": "Cesta", + "label.journey-description": "Zjistěte, jak uživatelé procházejí vaším webem.", + "label.journeys": "Cesty", "label.language": "Jazyk", "label.languages": "Jazyky", "label.laptop": "Přenosný počítač", - "label.last-click": "Last click", + "label.last-click": "Poslední kliknutí", "label.last-days": "Posledních {x} dnů", "label.last-hours": "Posledních {x} hodin", "label.last-months": "Posledních {x} měsíců", "label.last-seen": "Last seen", "label.leave": "Opustit", "label.leave-team": "Opustit tým", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.less-than": "Méně než", + "label.less-than-equals": "Méně nebo rovno", + "label.links": "Odkazy", "label.login": "Přihlásit", "label.logout": "Odhlásit", "label.manage": "Spravovat", "label.manager": "Správce", "label.max": "Max", - "label.medium": "Medium", + "label.medium": "Střední", "label.member": "Člen", "label.members": "Členové", "label.min": "Min", @@ -157,97 +157,97 @@ "label.my-websites": "Mé weby", "label.name": "Jméno", "label.new-password": "Nové heslo", - "label.none": "None", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", + "label.none": "Žádný", + "label.number-of-records": "{x} {x, plural, one {záznam} other {záznamů}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organické vyhledávání", + "label.organic-shopping": "Organický nákup", + "label.organic-social": "Organická sociální síť", + "label.organic-video": "Organické video", "label.os": "OS", - "label.other": "Other", + "label.other": "Jiné", "label.overview": "Přehled", "label.owner": "Vlastník", - "label.page": "Page", - "label.page-of": "Page {current} of {total}", + "label.page": "Stránka", + "label.page-of": "Stránka {current} z {total}", "label.page-views": "Zobrazení stránek", "label.pageTitle": "Název stránky", "label.pages": "Stránky", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Placené reklamy", + "label.paid-search": "Placené vyhledávání", + "label.paid-shopping": "Placený nákup", + "label.paid-social": "Placená sociální síť", + "label.paid-video": "Placené video", "label.password": "Heslo", "label.path": "Cesta", "label.paths": "Cesty", - "label.pixels": "Pixels", + "label.pixels": "Pixely", "label.powered-by": "Běží na {name}", "label.previous": "Previous", "label.previous-period": "Previous period", "label.previous-year": "Previous year", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.properties": "Vlastnosti", + "label.property": "Vlastnost", + "label.queries": "Dotazy", + "label.query": "Dotaz", + "label.query-parameters": "Parametry dotazu", "label.realtime": "Aktuálně", - "label.referral": "Referral", - "label.referrer": "Referrer", - "label.referrers": "Odkazy", + "label.referral": "Doporučení", + "label.referrer": "Odkazující", + "label.referrers": "Odkazující", "label.refresh": "Obnovit", - "label.regenerate": "Regenerate", + "label.regenerate": "Regenerovat", "label.region": "Region", - "label.regions": "Regions", - "label.remaining": "Remaining", - "label.remove": "Remove", - "label.remove-member": "Remove member", - "label.reports": "Reports", - "label.required": "Vyžadováno", - "label.reset": "Reset", - "label.reset-website": "Reset statistics", - "label.retention": "Retention", - "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.regions": "Regiony", + "label.remaining": "Zbývá", + "label.remove": "Odstranit", + "label.remove-member": "Odstranit člena", + "label.reports": "Hlášení", + "label.required": "Povinné", + "label.reset": "Resetovat", + "label.reset-website": "Resetovat statistiky", + "label.retention": "Udržení", + "label.retention-description": "Měřte přilnavost svého webu sledováním, jak často se uživatelé vracejí.", + "label.revenue": "Příjem", + "label.revenue-description": "Podívejte se na své příjmy v průběhu času.", "label.role": "Role", - "label.run-query": "Run query", + "label.run-query": "Spustit dotaz", "label.save": "Uložit", - "label.screens": "Screens", - "label.search": "Search", - "label.select": "Select", - "label.select-date": "Select date", - "label.select-filter": "Select filter", - "label.select-role": "Select role", - "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", - "label.sessions": "Sessions", + "label.screens": "Obrazovky", + "label.search": "Hledat", + "label.select": "Vybrat", + "label.select-date": "Vybrat datum", + "label.select-filter": "Vybrat filtr", + "label.select-role": "Vybrat roli", + "label.select-website": "Vybrat web", + "label.session": "Relace", + "label.session-data": "Data relace", + "label.sessions": "Relace", "label.settings": "Nastavení", - "label.share": "Share", - "label.share-url": "Sdílet URL", + "label.share": "Sdílet", + "label.share-url": "URL pro sdílení", "label.single-day": "Jeden den", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", - "label.sum": "Sum", + "label.sources": "Zdroje", + "label.start-step": "Počáteční krok", + "label.steps": "Kroky", + "label.sum": "Součet", "label.tablet": "Tablet", - "label.tag": "Tag", - "label.tags": "Tags", - "label.team": "Team", - "label.team-id": "Team ID", - "label.team-manager": "Team manager", - "label.team-member": "Team member", - "label.team-name": "Team name", - "label.team-owner": "Team owner", - "label.team-settings": "Team settings", - "label.team-view-only": "Team view only", - "label.team-websites": "Team websites", - "label.teams": "Teams", - "label.terms": "Terms", - "label.theme": "Theme", + "label.tag": "Štítek", + "label.tags": "Štítky", + "label.team": "Tým", + "label.team-id": "ID týmu", + "label.team-manager": "Manažer týmu", + "label.team-member": "Člen týmu", + "label.team-name": "Název týmu", + "label.team-owner": "Vlastník týmu", + "label.team-settings": "Nastavení týmu", + "label.team-view-only": "Pouze pro zobrazení týmu", + "label.team-websites": "Weby týmu", + "label.teams": "Týmy", + "label.terms": "Termíny", + "label.theme": "Téma", "label.this-month": "Tento měsíc", "label.this-week": "Tento týden", "label.this-year": "Tento rok", diff --git a/src/lang/da-DK.json b/src/lang/da-DK.json index 2ea9d53b..9141f51c 100644 --- a/src/lang/da-DK.json +++ b/src/lang/da-DK.json @@ -1,252 +1,252 @@ { - "label.access-code": "Access code", + "label.access-code": "Adgangskode", "label.actions": "Handlinger", - "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.activity": "Aktivitetslog", + "label.add": "Tilføj", + "label.add-board": "Tilføj tavle", + "label.add-description": "Tilføj beskrivelse", + "label.add-member": "Tilføj medlem", + "label.add-step": "Tilføj trin", "label.add-website": "Tilføj hjemmeside", "label.admin": "Administrator", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "Partner", + "label.after": "Efter", "label.all": "Alle", "label.all-time": "Altid", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.analytics": "Analyser", + "label.apply": "Anvend", + "label.attribution": "Attribuering", + "label.attribution-description": "Se, hvordan brugere interagerer med din markedsføring, og hvad der driver konverteringer.", + "label.average": "Gennemsnit", "label.back": "Tilbage", - "label.before": "Before", - "label.boards": "Boards", + "label.before": "Før", + "label.boards": "Tavler", "label.bounce-rate": "Afvisningsprocent", - "label.breakdown": "Breakdown", + "label.breakdown": "Opdeling", "label.browser": "Browser", "label.browsers": "Browsere", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampagner", "label.cancel": "Afvis", "label.change-password": "Skift adgangskode", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "Kanaler", + "label.cities": "Byer", + "label.city": "By", + "label.clear-all": "Ryd alt", + "label.cohort": "Kohorte", + "label.compare": "Sammenlign", + "label.compare-dates": "Sammenlign datoer", + "label.confirm": "Bekræft", "label.confirm-password": "Godkendt adgangskode", "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.content": "Indhold", + "label.continue": "Fortsæt", + "label.conversion": "Konvertering", + "label.conversion-rate": "Konverteringsrate", + "label.conversion-step": "Konverteringstrin", + "label.count": "Antal", "label.countries": "Lande", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "Land", + "label.create": "Opret", + "label.create-report": "Opret rapport", + "label.create-team": "Opret team", + "label.create-user": "Opret bruger", + "label.created": "Oprettet", + "label.created-by": "Oprettet af", + "label.currency": "Valuta", + "label.current": "Nuværende", "label.current-password": "Nuværende adgangskode", "label.custom-range": "Tilpasset interval", "label.dashboard": "Betjeningspanel", "label.data": "Data", - "label.date": "Date", + "label.date": "Dato", "label.date-range": "Datointerval", - "label.day": "Day", + "label.day": "Dag", "label.default-date-range": "Standard datointerval", "label.delete": "Slet", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "Slet rapport", + "label.delete-team": "Slet team", + "label.delete-user": "Slet bruger", "label.delete-website": "Slet hjemmeside", - "label.description": "Description", - "label.desktop": "Desktop", - "label.details": "Details", - "label.device": "Device", + "label.description": "Beskrivelse", + "label.desktop": "Skrivebord", + "label.details": "Detaljer", + "label.device": "Enhed", "label.devices": "Enheder", - "label.direct": "Direct", + "label.direct": "Direkte", "label.dismiss": "Afvis", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "Unikt ID", + "label.does-not-contain": "Indeholder ikke", + "label.does-not-include": "Inkluderer ikke", + "label.doest-not-exist": "Findes ikke", "label.domain": "Domæne", - "label.dropoff": "Dropoff", + "label.dropoff": "Frafald", "label.edit": "Rediger", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", - "label.email": "Email", + "label.edit-dashboard": "Rediger betjeningspanel", + "label.edit-member": "Rediger medlem", + "label.email": "E-mail", "label.enable-share-url": "Aktivér delings-URL", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "Sluttrin", + "label.entry": "Indgangs-URL", + "label.event": "Hændelse", + "label.event-data": "Hændelsesdata", + "label.event-name": "Hændelsesnavn", "label.events": "Hændelser", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", + "label.exists": "Findes", + "label.exit": "Udgangs-URL", + "label.expand": "Udvid", + "label.false": "Falsk", + "label.field": "Felt", + "label.fields": "Felter", "label.filter": "Filter", "label.filter-combined": "Kombineret", "label.filter-raw": "Rå", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.filters": "Filtre", + "label.first-click": "Første klik", + "label.first-seen": "Først set", + "label.funnel": "Tragt", + "label.funnel-description": "Forstå brugernes konverterings- og frafaldsrate.", + "label.funnels": "Tragte", + "label.goal": "Mål", + "label.goals": "Mål", + "label.goals-description": "Følg dine mål for sidevisninger og hændelser.", + "label.greater-than": "Større end", + "label.greater-than-equals": "Større end eller lig med", + "label.grouped": "Gruperet", + "label.hostname": "Værtsnavn", + "label.includes": "Inkluderer", + "label.insight": "Indsigt", + "label.insights": "Indsigter", + "label.insights-description": "Dyk dybere ned i dine data ved at bruge segmenter og filtre.", + "label.is": "Er", + "label.is-false": "Er falsk", + "label.is-not": "Er ikke", + "label.is-not-set": "Er ikke sat", + "label.is-set": "Er sat", + "label.is-true": "Er sandt", + "label.join": "Deltag", + "label.join-team": "Deltag i team", + "label.journey": "Rejse", + "label.journey-description": "Forstå hvordan brugere navigerer på din hjemmeside.", + "label.journeys": "Rejser", "label.language": "Sprog", "label.languages": "Sprog", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Sidste klik", "label.last-days": "Sidste {x} dage", "label.last-hours": "Sidste {x} timer", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", + "label.last-months": "Sidste {x} måneder", + "label.last-seen": "Sidst set", + "label.leave": "Forlad", + "label.leave-team": "Forlad team", + "label.less-than": "Mindre end", + "label.less-than-equals": "Mindre end eller lig med", "label.links": "Links", "label.login": "Log ind", "label.logout": "Log ud", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", + "label.manage": "Administrer", + "label.manager": "Leder", + "label.max": "Maks", "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", + "label.member": "Medlem", + "label.members": "Medlemmer", "label.min": "Min", "label.mobile": "Mobil", "label.model": "Model", "label.more": "Mere", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "Min konto", + "label.my-websites": "Mine hjemmesider", "label.name": "Navn", "label.new-password": "Ny adgangskode", - "label.none": "None", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", + "label.none": "Ingen", + "label.number-of-records": "{x} {x, plural, one {post} other {poster}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organisk søgning", + "label.organic-shopping": "Organisk shopping", + "label.organic-social": "Organisk social", + "label.organic-video": "Organisk video", "label.os": "OS", - "label.other": "Other", - "label.overview": "Overview", + "label.other": "Andet", + "label.overview": "Oversigt", "label.owner": "Ejer", - "label.page": "Page", - "label.page-of": "Page {current} of {total}", + "label.page": "Side", + "label.page-of": "Side {current} af {total}", "label.page-views": "Sidevisninger", - "label.pageTitle": "Page title", + "label.pageTitle": "Sidetitel", "label.pages": "Sider", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Betalte annoncer", + "label.paid-search": "Betalt søgning", + "label.paid-shopping": "Betalt shopping", + "label.paid-social": "Betalt social", + "label.paid-video": "Betalt video", "label.password": "Adgangskode", - "label.path": "Path", - "label.paths": "Paths", + "label.path": "Sti", + "label.paths": "Stier", "label.pixels": "Pixels", "label.powered-by": "Drevet af {name}", "label.previous": "Previous", "label.previous-period": "Previous period", "label.previous-year": "Previous year", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.properties": "Egenskaber", + "label.property": "Egenskab", + "label.queries": "Forespørgsler", + "label.query": "Forespørgsel", + "label.query-parameters": "Forespørgselsparametre", "label.realtime": "Realtid", - "label.referral": "Referral", - "label.referrer": "Referrer", + "label.referral": "Henvisning", + "label.referrer": "Henviser", "label.referrers": "Henvisninger", "label.refresh": "Opdater", - "label.regenerate": "Regenerate", + "label.regenerate": "Gendan", "label.region": "Region", - "label.regions": "Regions", - "label.remaining": "Remaining", - "label.remove": "Remove", - "label.remove-member": "Remove member", - "label.reports": "Reports", + "label.regions": "Regioner", + "label.remaining": "Tilbageværende", + "label.remove": "Fjern", + "label.remove-member": "Fjern medlem", + "label.reports": "Rapporter", "label.required": "Påkrævet", "label.reset": "Nulstil", - "label.reset-website": "Nulstil statistikker", - "label.retention": "Retention", - "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", - "label.role": "Role", - "label.run-query": "Run query", + "label.reset-website": "Nulstil statistik", + "label.retention": "Fastholdelse", + "label.retention-description": "Mål hvor ofte brugere vender tilbage til din hjemmeside.", + "label.revenue": "Indtægt", + "label.revenue-description": "Se din indtægt over tid.", + "label.role": "Rolle", + "label.run-query": "Kør forespørgsel", "label.save": "Gem", - "label.screens": "Screens", - "label.search": "Search", - "label.select": "Select", - "label.select-date": "Select date", - "label.select-filter": "Select filter", - "label.select-role": "Select role", - "label.select-website": "Select website", + "label.screens": "Skærme", + "label.search": "Søg", + "label.select": "Vælg", + "label.select-date": "Vælg dato", + "label.select-filter": "Vælg filter", + "label.select-role": "Vælg rolle", + "label.select-website": "Vælg hjemmeside", "label.session": "Session", - "label.session-data": "Session data", - "label.sessions": "Sessions", + "label.session-data": "Sessionsdata", + "label.sessions": "Sessioner", "label.settings": "Indstillinger", - "label.share": "Share", + "label.share": "Del", "label.share-url": "Del URL", "label.single-day": "Enkelt dag", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", + "label.sources": "Kilder", + "label.start-step": "Starttrin", + "label.steps": "Trin", "label.sum": "Sum", "label.tablet": "Tablet", "label.tag": "Tag", "label.tags": "Tags", "label.team": "Team", "label.team-id": "Team ID", - "label.team-manager": "Team manager", - "label.team-member": "Team member", - "label.team-name": "Team name", - "label.team-owner": "Team owner", - "label.team-settings": "Team settings", - "label.team-view-only": "Team view only", - "label.team-websites": "Team websites", + "label.team-manager": "Teamleder", + "label.team-member": "Teammedlem", + "label.team-name": "Teamnavn", + "label.team-owner": "Teamejer", + "label.team-settings": "Teamindstillinger", + "label.team-view-only": "Kun visning af team", + "label.team-websites": "Teamets hjemmesider", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Vilkår", "label.theme": "Tema", "label.this-month": "Denne måned", "label.this-week": "Denne uge", diff --git a/src/lang/de-CH.json b/src/lang/de-CH.json index 600f4c7f..7e2fcf39 100644 --- a/src/lang/de-CH.json +++ b/src/lang/de-CH.json @@ -3,20 +3,20 @@ "label.actions": "Aktione", "label.activity": "Aktivitätsverlauf", "label.add": "hinzuefüege", - "label.add-board": "Add board", + "label.add-board": "Board hinzuefüege", "label.add-description": "Beschriibig hinzuefüege", "label.add-member": "Mitglied hinzuefüege", "label.add-step": "Schritt hinzuefüege", "label.add-website": "Websiite hinzuefüege", "label.admin": "Administrator", - "label.affiliate": "Affiliate", + "label.affiliate": "Partnerprogramm", "label.after": "Nach", "label.all": "Alli", "label.all-time": "Gsamte Zitruum", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.analytics": "Analytik", + "label.apply": "Aawände", + "label.attribution": "Zuordnig", + "label.attribution-description": "Lueg wie d'Benutzer mit dim Marketing interagiere und was zu Umwandlige führt.", "label.average": "Durchschnitt", "label.back": "Zrugg", "label.before": "Vor", @@ -25,24 +25,24 @@ "label.breakdown": "Uufschlüsselig", "label.browser": "Browser", "label.browsers": "Browser", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampagne", "label.cancel": "Abbreche", "label.change-password": "Passwort ändere", - "label.channels": "Channels", + "label.channels": "Kanäle", "label.cities": "Städt", "label.city": "Stadt", "label.clear-all": "Alles lösche", - "label.cohort": "Cohort", + "label.cohort": "Gruppe", "label.compare": "Vergliiche", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Datum vergleiche", "label.confirm": "Bestätige", "label.confirm-password": "Passwort widerhole", "label.contains": "Enthaltet", - "label.content": "Content", + "label.content": "Inhalt", "label.continue": "Wiiter", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Umwandlig", + "label.conversion-rate": "Umwandligsrate", + "label.conversion-step": "Umwandligsschritt", "label.count": "Azahl", "label.countries": "Länder", "label.country": "Land", @@ -51,8 +51,8 @@ "label.create-team": "Team erstelle", "label.create-user": "Benutzer erstelle", "label.created": "Erstellt", - "label.created-by": "Created By", - "label.currency": "Currency", + "label.created-by": "Erstellt vo", + "label.currency": "Währung", "label.current": "Aktuell", "label.current-password": "Aktuells Passwort", "label.custom-range": "Benutzerdefinierte Bereich", @@ -72,12 +72,12 @@ "label.details": "Details", "label.device": "Grät", "label.devices": "Grät", - "label.direct": "Direct", + "label.direct": "Direkt", "label.dismiss": "Verwärfe", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Eindeutigi ID", "label.does-not-contain": "Enthaltet nid", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Isch nid debii", + "label.doest-not-exist": "Existiert nid", "label.domain": "Domain", "label.dropoff": "Absprung", "label.edit": "Bearbeite", @@ -89,11 +89,11 @@ "label.entry": "Iigangs URL", "label.event": "Ereigniss", "label.event-data": "Ereigniss Date", - "label.event-name": "Event name", + "label.event-name": "Ereignissname", "label.events": "Ereigniss", - "label.exists": "Exists", + "label.exists": "Existiert", "label.exit": "Uusgangs URL", - "label.expand": "Expand", + "label.expand": "Uusklappe", "label.false": "Falsch", "label.field": "Fäld", "label.fields": "Fälder", @@ -101,7 +101,7 @@ "label.filter-combined": "Kombiniert", "label.filter-raw": "Rohdate", "label.filters": "Filters", - "label.first-click": "First click", + "label.first-click": "Erste Klick", "label.first-seen": "Erstmal gse", "label.funnel": "Tunnel", "label.funnel-description": "Verstönd Sie d Konversions- und Abspruungsrate vo Nutzer.", @@ -111,27 +111,27 @@ "label.goals-description": "verfolged Sie Ihri Ziel für Siitenufrüef und Ereigniss.", "label.greater-than": "Grösser als", "label.greater-than-equals": "Grösser oder gliich", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Gruppiert", + "label.hostname": "Hostnam", + "label.includes": "Isch debii", + "label.insight": "Iiblick", "label.insights": "Iiblick", "label.insights-description": "Vertüfed Sie sich i Ihri Date, mit Hilf vo Segment und Filter.", "label.is": "Isch", - "label.is-false": "Is false", + "label.is-false": "Isch falsch", "label.is-not": "Isch nid", "label.is-not-set": "Isch ned gsetzt", "label.is-set": "Isch gsetzt", - "label.is-true": "Is true", + "label.is-true": "Isch wahr", "label.join": "Biträte", "label.join-team": "Team biträte", "label.journey": "Reis", "label.journey-description": "Verstönd Sie, wie Nutzer dur Ihri Website navigiered.", - "label.journeys": "Journeys", + "label.journeys": "Reise", "label.language": "Sprach", "label.languages": "Sprache", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Letzte Klick", "label.last-days": "Letzti {x} Täg", "label.last-hours": "Letzti {x} Stunde", "label.last-months": "Letzti {x} Mönet", @@ -160,47 +160,47 @@ "label.none": "Keis", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organischi Suechi", + "label.organic-shopping": "Organischi Iikauf", + "label.organic-social": "Organischi Social Media", + "label.organic-video": "Organischi Video", "label.os": "OS", - "label.other": "Other", + "label.other": "Anderi", "label.overview": "Übersicht", "label.owner": "Bsitzer", - "label.page": "Page", + "label.page": "Siite", "label.page-of": "Siite {current} vo {total}", "label.page-views": "Siitenufrüef", "label.pageTitle": "Siitetitel", "label.pages": "Siite", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Bezahlti Werbung", + "label.paid-search": "Bezahlti Suechi", + "label.paid-shopping": "Bezahlti Iikauf", + "label.paid-social": "Bezahlti Social Media", + "label.paid-video": "Bezahlti Video", "label.password": "Passwort", "label.path": "Pfad", "label.paths": "Pfade", - "label.pixels": "Pixels", + "label.pixels": "Pixel", "label.powered-by": "Betriibe dur {name}", "label.previous": "Vorherig", "label.previous-period": "Vorherigi Periode", "label.previous-year": "Vorherigs Jahr", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Eigeschafte", + "label.property": "Eigeschafte", "label.queries": "Abfrage", "label.query": "Abfrag", "label.query-parameters": "Abfragparameter", "label.realtime": "Echtzit", - "label.referral": "Referral", + "label.referral": "Empfehlig", "label.referrer": "Verwiiser", "label.referrers": "Verwiisendi", "label.refresh": "Aktualisiere", "label.regenerate": "Erneuere", "label.region": "Region", "label.regions": "Regionä", - "label.remaining": "Remaining", + "label.remaining": "Verblibe", "label.remove": "Entferne", "label.remove-member": "Mitglied entferne", "label.reports": "Brichte", @@ -218,35 +218,35 @@ "label.search": "Sueche", "label.select": "Auswähle", "label.select-date": "Datä uuswähle", - "label.select-filter": "Select filter", + "label.select-filter": "Filter uuswähle", "label.select-role": "Rollä uuswähle", "label.select-website": "Websiite uuswähle", "label.session": "Sitzig", - "label.session-data": "Session data", + "label.session-data": "Sitzigsdate", "label.sessions": "Sitzige", "label.settings": "Istellige", - "label.share": "Share", + "label.share": "Teile", "label.share-url": "Freigab-URL", "label.single-day": "Ein Tag", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Quälle", "label.start-step": "Startschritt", "label.steps": "Schritt", "label.sum": "Summe", "label.tablet": "Tablet", "label.tag": "Tag", - "label.tags": "Tags", + "label.tags": "Stichwort", "label.team": "Team", "label.team-id": "Team ID", "label.team-manager": "Team Manager", "label.team-member": "Team Mitglied", "label.team-name": "Team Name", "label.team-owner": "Team Bsitzer", - "label.team-settings": "Team settings", + "label.team-settings": "Team Istellige", "label.team-view-only": "Nur für Teammitglieder sichtbar", "label.team-websites": "Team Websiite", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Bedingige", "label.theme": "Thema", "label.this-month": "Dä Monet", "label.this-week": "Diä Wuuche", diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json index 8ef7468a..c5070a81 100644 --- a/src/lang/de-DE.json +++ b/src/lang/de-DE.json @@ -3,20 +3,20 @@ "label.actions": "Aktionen", "label.activity": "Aktivitätsverlauf", "label.add": "Hinzufügen", - "label.add-board": "Add board", + "label.add-board": "Board hinzufügen", "label.add-description": "Beschreibung hinzufügen", "label.add-member": "Mitglied hinzufügen", "label.add-step": "Schritt hinzufügen", "label.add-website": "Website hinzufügen", "label.admin": "Administrator", - "label.affiliate": "Affiliate", + "label.affiliate": "Partnerprogramm", "label.after": "Nach", "label.all": "Alle", "label.all-time": "Gesamter Zeitraum", "label.analytics": "Analysen", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Anwenden", + "label.attribution": "Zuordnung", + "label.attribution-description": "Sehen Sie, wie Nutzer mit Ihrem Marketing interagieren und was zu Konversionen führt.", "label.average": "Durchschnitt", "label.back": "Zurück", "label.before": "Vor", @@ -25,24 +25,24 @@ "label.breakdown": "Aufschlüsselung", "label.browser": "Browser", "label.browsers": "Browser", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampagnen", "label.cancel": "Abbrechen", "label.change-password": "Passwort ändern", - "label.channels": "Channels", + "label.channels": "Kanäle", "label.cities": "Städte", "label.city": "Stadt", "label.clear-all": "Alles löschen", - "label.cohort": "Cohort", + "label.cohort": "Gruppe", "label.compare": "Vergleichen", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Daten vergleichen", "label.confirm": "Bestätigen", "label.confirm-password": "Passwort wiederholen", "label.contains": "Enthält", - "label.content": "Content", + "label.content": "Inhalt", "label.continue": "Weiter", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Konversion", + "label.conversion-rate": "Konversionsrate", + "label.conversion-step": "Konversionsschritt", "label.count": "Anzahl", "label.countries": "Länder", "label.country": "Land", @@ -52,7 +52,7 @@ "label.create-user": "Benutzer erstellen", "label.created": "Erstellt", "label.created-by": "Erstellt von", - "label.currency": "Currency", + "label.currency": "Währung", "label.current": "Aktuell", "label.current-password": "Derzeitiges Passwort", "label.custom-range": "Benutzerdefinierter Bereich", @@ -72,12 +72,12 @@ "label.details": "Details", "label.device": "Gerät", "label.devices": "Geräte", - "label.direct": "Direct", + "label.direct": "Direkt", "label.dismiss": "Verwerfen", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Eindeutige ID", "label.does-not-contain": "Enthält nicht", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Nicht enthalten", + "label.doest-not-exist": "Existiert nicht", "label.domain": "Domain", "label.dropoff": "Absprung", "label.edit": "Bearbeiten", @@ -89,11 +89,11 @@ "label.entry": "Eingangs-URL", "label.event": "Ereignis", "label.event-data": "Ereignisdaten", - "label.event-name": "Event name", + "label.event-name": "Ereignisname", "label.events": "Ereignisse", - "label.exists": "Exists", + "label.exists": "Existiert", "label.exit": "Ausgangs-URL", - "label.expand": "Expand", + "label.expand": "Erweitern", "label.false": "Falsch", "label.field": "Feld", "label.fields": "Felder", @@ -101,7 +101,7 @@ "label.filter-combined": "Kombiniert", "label.filter-raw": "Rohdaten", "label.filters": "Filter", - "label.first-click": "First click", + "label.first-click": "Erster Klick", "label.first-seen": "Erstmalig gesehen", "label.funnel": "Trichter", "label.funnel-description": "Verstehen Sie die Konversions- und Absprungrate Ihrer Nutzer.", @@ -111,27 +111,27 @@ "label.goals-description": "Verfolgen Sie Ihre Ziele für Seitenaufrufe und Ereignisse.", "label.greater-than": "Größer als", "label.greater-than-equals": "Größer oder gleich", - "label.grouped": "Grouped", + "label.grouped": "Gruppiert", "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.includes": "Enthält", + "label.insight": "Einblick", "label.insights": "Einblicke", "label.insights-description": "Vertiefen Sie sich mit Hilfe von Segmenten und Filtern in Ihre Daten.", "label.is": "Ist", - "label.is-false": "Is false", + "label.is-false": "Ist falsch", "label.is-not": "Ist nicht", "label.is-not-set": "Ist nicht gesetzt", "label.is-set": "Ist gesetzt", - "label.is-true": "Is true", + "label.is-true": "Ist wahr", "label.join": "Beitreten", "label.join-team": "Team beitreten", "label.journey": "Reise", "label.journey-description": "Verstehen Sie, wie Nutzer auf Ihrer Website navigieren.", - "label.journeys": "Journeys", + "label.journeys": "Reisen", "label.language": "Sprache", "label.languages": "Sprachen", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Letzter Klick", "label.last-days": "Letzten {x} Tage", "label.last-hours": "Letzten {x} Stunden", "label.last-months": "Letzten {x} Monate", @@ -160,47 +160,47 @@ "label.none": "Keine", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organische Suche", + "label.organic-shopping": "Organisches Shopping", + "label.organic-social": "Organisches Social Media", + "label.organic-video": "Organisches Video", "label.os": "OS", - "label.other": "Other", + "label.other": "Andere", "label.overview": "Übersicht", "label.owner": "Besitzer", - "label.page": "Page", + "label.page": "Seite", "label.page-of": "Seite {current} von {total}", "label.page-views": "Seitenaufrufe", "label.pageTitle": "Seitentitel", "label.pages": "Seiten", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Bezahlte Anzeigen", + "label.paid-search": "Bezahlte Suche", + "label.paid-shopping": "Bezahltes Shopping", + "label.paid-social": "Bezahltes Social Media", + "label.paid-video": "Bezahltes Video", "label.password": "Passwort", "label.path": "Pfad", "label.paths": "Pfade", - "label.pixels": "Pixels", + "label.pixels": "Pixel", "label.powered-by": "Betrieben durch {name}", "label.previous": "Vorherig", "label.previous-period": "Vorherige Periode", "label.previous-year": "Vorheriges Jahr", "label.profile": "Profil", "label.properties": "Eigenschaften", - "label.property": "Eigentum", + "label.property": "Eigenschaft", "label.queries": "Abfragen", "label.query": "Abfrage", "label.query-parameters": "Abfrageparameter", "label.realtime": "Echtzeit", - "label.referral": "Referral", + "label.referral": "Empfehlung", "label.referrer": "Übermittler", "label.referrers": "Übermittler", "label.refresh": "Aktualisieren", "label.regenerate": "Erneuern", "label.region": "Region", "label.regions": "Regionen", - "label.remaining": "Remaining", + "label.remaining": "Verbleibend", "label.remove": "Entfernen", "label.remove-member": "Mitglied entfernen", "label.reports": "Berichte", @@ -218,35 +218,35 @@ "label.search": "Suche", "label.select": "Auswählen", "label.select-date": "Datum auswählen", - "label.select-filter": "Select filter", + "label.select-filter": "Filter auswählen", "label.select-role": "Rolle auswählen", "label.select-website": "Website auswählen", "label.session": "Sitzung", - "label.session-data": "Session data", + "label.session-data": "Sitzungsdaten", "label.sessions": "Sitzungen", "label.settings": "Einstellungen", - "label.share": "Share", + "label.share": "Teilen", "label.share-url": "Freigabe-URL", "label.single-day": "Ein Tag", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Quellen", "label.start-step": "Startschritt", "label.steps": "Schritte", "label.sum": "Summe", "label.tablet": "Tablet", "label.tag": "Tag", - "label.tags": "Tags", + "label.tags": "Stichworte", "label.team": "Team", "label.team-id": "Team-ID", "label.team-manager": "Team-Manager", "label.team-member": "Team-Mitglied", "label.team-name": "Name des Teams", "label.team-owner": "Team-Eigentümer", - "label.team-settings": "Team settings", + "label.team-settings": "Team-Einstellungen", "label.team-view-only": "Nur für Team-Mitglieder sichtbar", "label.team-websites": "Team-Websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Bedingungen", "label.theme": "Thema", "label.this-month": "Diesen Monat", "label.this-week": "Diese Woche", diff --git a/src/lang/el-GR.json b/src/lang/el-GR.json index 557bc721..82de9f47 100644 --- a/src/lang/el-GR.json +++ b/src/lang/el-GR.json @@ -41,7 +41,7 @@ "label.content": "Content", "label.continue": "Continue", "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", + "label.conversion-rate": "Conversion rate", "label.conversion-step": "Conversion step", "label.count": "Count", "label.countries": "Χώρες", diff --git a/src/lang/en-GB.json b/src/lang/en-GB.json index ee8eae20..09ad528f 100644 --- a/src/lang/en-GB.json +++ b/src/lang/en-GB.json @@ -41,7 +41,7 @@ "label.content": "Content", "label.continue": "Continue", "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", + "label.conversion-rate": "Conversion rate", "label.conversion-step": "Conversion step", "label.count": "Count", "label.countries": "Countries", diff --git a/src/lang/en-US.json b/src/lang/en-US.json index bb5749d3..f7352769 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -41,7 +41,7 @@ "label.content": "Content", "label.continue": "Continue", "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", + "label.conversion-rate": "Conversion rate", "label.conversion-step": "Conversion step", "label.count": "Count", "label.countries": "Countries", diff --git a/src/lang/es-ES.json b/src/lang/es-ES.json index 914f5f4d..e4eed919 100644 --- a/src/lang/es-ES.json +++ b/src/lang/es-ES.json @@ -3,46 +3,46 @@ "label.actions": "Acciones", "label.activity": "Registro de actividad", "label.add": "Añadir", - "label.add-board": "Add board", + "label.add-board": "Añadir tablero", "label.add-description": "Añadir descripción", "label.add-member": "Añadir miembro", "label.add-step": "Añadir paso", "label.add-website": "Nuevo sitio web", "label.admin": "Administrador", - "label.affiliate": "Affiliate", + "label.affiliate": "Afiliado", "label.after": "Después", "label.all": "Todos", "label.all-time": "Todos los tiempos", "label.analytics": "Analíticas", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Aplicar", + "label.attribution": "Atribución", + "label.attribution-description": "Vea cómo los usuarios interactúan con su marketing y qué impulsa las conversiones.", "label.average": "Media", "label.back": "Atrás", "label.before": "Antes", - "label.boards": "Boards", + "label.boards": "Tableros", "label.bounce-rate": "Porcentaje de rebote", "label.breakdown": "Desglose", "label.browser": "Navegador", "label.browsers": "Navegadores", - "label.campaigns": "Campaigns", + "label.campaigns": "Campañas", "label.cancel": "Cancelar", "label.change-password": "Cambiar contraseña", - "label.channels": "Channels", + "label.channels": "Canales", "label.cities": "Ciudades", "label.city": "Ciudad", "label.clear-all": "Limpiar todo", - "label.cohort": "Cohort", + "label.cohort": "Cohorte", "label.compare": "Comparar", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Comparar fechas", "label.confirm": "Confirmar", "label.confirm-password": "Confirmar contraseña", "label.contains": "Contiene", - "label.content": "Content", + "label.content": "Contenido", "label.continue": "Continuar", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Conversión", + "label.conversion-rate": "Tasa de conversión", + "label.conversion-step": "Paso de conversión", "label.count": "Contar", "label.countries": "Países", "label.country": "País", @@ -52,7 +52,7 @@ "label.create-user": "Crear usuario", "label.created": "Creado", "label.created-by": "Creado por", - "label.currency": "Currency", + "label.currency": "Moneda", "label.current": "Actual", "label.current-password": "Contraseña actual", "label.custom-range": "Intervalo personalizado", @@ -72,12 +72,12 @@ "label.details": "Detalles", "label.device": "Dispositivo", "label.devices": "Dispositivos", - "label.direct": "Direct", + "label.direct": "Directo", "label.dismiss": "Cerrar", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "ID distinto", "label.does-not-contain": "No contiene", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "No incluye", + "label.doest-not-exist": "No existe", "label.domain": "Dominio", "label.dropoff": "Abandono", "label.edit": "Editar", @@ -89,11 +89,11 @@ "label.entry": "URL de entrada", "label.event": "Evento", "label.event-data": "Datos de evento", - "label.event-name": "Event name", + "label.event-name": "Nombre del evento", "label.events": "Eventos", - "label.exists": "Exists", + "label.exists": "Existe", "label.exit": "URL de salida", - "label.expand": "Expand", + "label.expand": "Expandir", "label.false": "Falso", "label.field": "Campo", "label.fields": "Campos", @@ -101,106 +101,106 @@ "label.filter-combined": "Combinado", "label.filter-raw": "En crudo", "label.filters": "Filtros", - "label.first-click": "First click", - "label.first-seen": "First seen", + "label.first-click": "Primer clic", + "label.first-seen": "Primera vez visto", "label.funnel": "Embudo", "label.funnel-description": "Comprender conversión y abandono de usuarios.", - "label.funnels": "Funnels", + "label.funnels": "Embudos", "label.goal": "Objetivo", "label.goals": "Objetivos", "label.goals-description": "Realice un seguimiento de sus objetivos de páginas vistas y eventos.", "label.greater-than": "Mayor que", "label.greater-than-equals": "Mayor que o igual a", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", + "label.grouped": "Agrupado", + "label.hostname": "Nombre de host", + "label.includes": "Incluye", + "label.insight": "Perspectiva", + "label.insights": "Perspectivas", "label.insights-description": "Profundice en sus datos mediante el uso de segmentos y filtros.", "label.is": "Es igual a", - "label.is-false": "Is false", + "label.is-false": "Es falso", "label.is-not": "No es igual a", "label.is-not-set": "No está establecido", "label.is-set": "Está establecido", - "label.is-true": "Is true", + "label.is-true": "Es verdadero", "label.join": "Unir", "label.join-team": "Unirse al equipo", "label.journey": "Viaje", "label.journey-description": "Comprenda cómo los usuarios navegan por su sitio web.", - "label.journeys": "Journeys", + "label.journeys": "Viajes", "label.language": "Idioma", "label.languages": "Idiomas", "label.laptop": "Portátil", - "label.last-click": "Last click", + "label.last-click": "Último clic", "label.last-days": "Últimos {x} días", "label.last-hours": "Últimas {x} horas", "label.last-months": "Últimos {x} meses", - "label.last-seen": "Last seen", + "label.last-seen": "Última vez visto", "label.leave": "Abandonar", "label.leave-team": "Abandonar equipo", "label.less-than": "Menor que", "label.less-than-equals": "Menor que o igual a", - "label.links": "Links", + "label.links": "Enlaces", "label.login": "Iniciar sesión", "label.logout": "Cerrar sesión", "label.manage": "Administrar", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", + "label.manager": "Gerente", + "label.max": "Máximo", + "label.medium": "Medio", "label.member": "Miembro", "label.members": "Miembros", - "label.min": "Min", + "label.min": "Mínimo", "label.mobile": "Móvil", - "label.model": "Model", + "label.model": "Modelo", "label.more": "Más", "label.my-account": "Mi cuenta", "label.my-websites": "Mis sitios web", "label.name": "Nombre", "label.new-password": "Nueva contraseña", "label.none": "Ninguno", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", + "label.number-of-records": "{x} {x, plural, one {registro} other {registros}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Búsqueda orgánica", + "label.organic-shopping": "Compras orgánicas", + "label.organic-social": "Social orgánico", + "label.organic-video": "Video orgánico", "label.os": "Sistema", - "label.other": "Other", + "label.other": "Otro", "label.overview": "Resumen", "label.owner": "Propietario", - "label.page": "Page", + "label.page": "Página", "label.page-of": "Página {current} de {total}", "label.page-views": "Vistas", "label.pageTitle": "Título de página", "label.pages": "Páginas", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Anuncios pagados", + "label.paid-search": "Búsqueda pagada", + "label.paid-shopping": "Compras pagadas", + "label.paid-social": "Social pagado", + "label.paid-video": "Video pagado", "label.password": "Contraseña", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Ruta", + "label.paths": "Rutas", + "label.pixels": "Píxeles", "label.powered-by": "Analíticas de {name}", "label.previous": "Anterior", "label.previous-period": "Periodo anterior", "label.previous-year": "Año anterior", "label.profile": "Perfil", - "label.properties": "Properties", + "label.properties": "Propiedades", "label.property": "Propiedad", "label.queries": "Consultas", "label.query": "Consulta", - "label.query-parameters": "Parámetros de petición", + "label.query-parameters": "Parámetros de consulta", "label.realtime": "Tiempo real", - "label.referral": "Referral", + "label.referral": "Referencia", "label.referrer": "Referido", "label.referrers": "Referido desde", "label.refresh": "Actualizar", "label.regenerate": "Regenerar", "label.region": "Región", "label.regions": "Regiones", - "label.remaining": "Remaining", + "label.remaining": "Restante", "label.remove": "Quitar", "label.remove-member": "Eliminar miembro", "label.reports": "Informes", @@ -209,8 +209,8 @@ "label.reset-website": "Reiniciar analíticas", "label.retention": "Retención", "label.retention-description": "Medir la frecuencia con la que los usuarios vuelven a tu sitio web.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Ingresos", + "label.revenue-description": "Consulte sus ingresos a lo largo del tiempo.", "label.role": "Rol", "label.run-query": "Ejecutar consulta", "label.save": "Guardar", @@ -218,35 +218,35 @@ "label.search": "Buscar", "label.select": "Seleccionar", "label.select-date": "Seleccionar fecha", - "label.select-filter": "Select filter", + "label.select-filter": "Seleccionar filtro", "label.select-role": "Seleccionar rol", "label.select-website": "Seleccionar sitio web", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Sesión", + "label.session-data": "Datos de sesión", "label.sessions": "Sesiones", "label.settings": "Ajustes", - "label.share": "Share", + "label.share": "Compartir", "label.share-url": "Compartir URL", "label.single-day": "Un solo día", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Paso inical", + "label.sources": "Fuentes", + "label.start-step": "Paso inicial", "label.steps": "Pasos", "label.sum": "Suma", "label.tablet": "Tableta", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Etiqueta", + "label.tags": "Etiquetas", "label.team": "Equipo", "label.team-id": "ID del equipo", "label.team-manager": "Jefe de equipo", "label.team-member": "Miembro del equipo", "label.team-name": "Nombre del equipo", "label.team-owner": "Admin. del equipo", - "label.team-settings": "Team settings", + "label.team-settings": "Configuración del equipo", "label.team-view-only": "Vista solo del equipo", "label.team-websites": "Sitios web del equipo", "label.teams": "Equipos", - "label.terms": "Terms", + "label.terms": "Términos", "label.theme": "Tema", "label.this-month": "Este mes", "label.this-week": "Esta semana", diff --git a/src/lang/fa-IR.json b/src/lang/fa-IR.json index 4ab9365b..05e70cfb 100644 --- a/src/lang/fa-IR.json +++ b/src/lang/fa-IR.json @@ -3,46 +3,46 @@ "label.actions": "اقدامات", "label.activity": "فعالیت", "label.add": "افزودن", - "label.add-board": "Add board", + "label.add-board": "افزودن برد", "label.add-description": "افزودن توضیحات", "label.add-member": "افزودن عضو", "label.add-step": "افزودن قدم", "label.add-website": "افزودن وب‌سایت", "label.admin": "مدیر", - "label.affiliate": "Affiliate", + "label.affiliate": "همکار فروش", "label.after": "بعد", "label.all": "همه", "label.all-time": "تمامی زمان‌ها", "label.analytics": "تجزیه و تحلیل", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "اعمال", + "label.attribution": "انتساب", + "label.attribution-description": "ببینید کاربران چگونه با بازاریابی شما تعامل دارند و چه چیزی باعث تبدیل می‌شود.", "label.average": "میانگین", "label.back": "بازگشت", "label.before": "قبل از", - "label.boards": "Boards", + "label.boards": "بردها", "label.bounce-rate": "نرخ ریزش", "label.breakdown": "تفکیک", "label.browser": "مرورگر", "label.browsers": "مرورگرها", - "label.campaigns": "Campaigns", + "label.campaigns": "کمپین‌ها", "label.cancel": "انصراف", "label.change-password": "تغییر رمز", - "label.channels": "Channels", + "label.channels": "کانال‌ها", "label.cities": "شهرها", "label.city": "شهر", "label.clear-all": "پاک کردن همه", - "label.cohort": "Cohort", + "label.cohort": "گروه", "label.compare": "مقایسه", - "label.compare-dates": "Compare dates", + "label.compare-dates": "مقایسه تاریخ‌ها", "label.confirm": "تأیید", "label.confirm-password": "تأیید رمز", "label.contains": "شامل", - "label.content": "Content", + "label.content": "محتوا", "label.continue": "ادامه", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "تبدیل", + "label.conversion-rate": "نرخ تبدیل", + "label.conversion-step": "گام تبدیل", "label.count": "تعداد", "label.countries": "کشورها", "label.country": "کشور", @@ -52,7 +52,7 @@ "label.create-user": "ایجاد کاربر", "label.created": "ایجاد شد", "label.created-by": "ایجاد شده توسط", - "label.currency": "Currency", + "label.currency": "واحد پول", "label.current": "فعلی", "label.current-password": "رمز فعلی", "label.custom-range": "محدوده‌ی دلخواه", @@ -72,28 +72,28 @@ "label.details": "جزئیات", "label.device": "دستگاه", "label.devices": "دستگاه‌ها", - "label.direct": "Direct", + "label.direct": "مستقیم", "label.dismiss": "رد کردن", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "شناسه یکتا", "label.does-not-contain": "شامل نمی‌شود", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "شامل نمی‌شود", + "label.doest-not-exist": "وجود ندارد", "label.domain": "دامنه", "label.dropoff": "رها کردن", "label.edit": "ویرایش", "label.edit-dashboard": "ویرایش داشبورد", "label.edit-member": "ویرایش عضو", - "label.email": "Email", + "label.email": "ایمیل", "label.enable-share-url": "فعال کردن اشتراک گذاری آدرس اینترنتی", "label.end-step": "قدم پایانی", "label.entry": "آدرس اینترنتی ورودی", "label.event": "رویداد", "label.event-data": "داده‌های رویداد", - "label.event-name": "Event name", + "label.event-name": "نام رویداد", "label.events": "رویدادها", - "label.exists": "Exists", + "label.exists": "وجود دارد", "label.exit": "آدرس اینترنتی خروجی", - "label.expand": "Expand", + "label.expand": "گسترش", "label.false": "نادرست", "label.field": "فیلد", "label.fields": "فیلد‌ها", @@ -101,37 +101,37 @@ "label.filter-combined": "ترکیب شده", "label.filter-raw": "خام", "label.filters": "فیلترها", - "label.first-click": "First click", + "label.first-click": "اولین کلیک", "label.first-seen": "اولین بار دیده شده", "label.funnel": "فانل", "label.funnel-description": "نرخ تبدیل و رها کردن کاربران را درک کنید.", - "label.funnels": "Funnels", + "label.funnels": "قیف‌ها", "label.goal": "هدف", "label.goals": "اهداف", "label.goals-description": "اهداف خود را برای بازدید از صفحه و رویدادها دنبال کنید.", "label.greater-than": "بزرگ‌تر از", "label.greater-than-equals": "بزرگ‌تر یا مساوی", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "گروه‌بندی شده", + "label.hostname": "نام میزبان", + "label.includes": "شامل می‌شود", + "label.insight": "بینش", "label.insights": "بینش", "label.insights-description": "با استفاده از بخش‌ها و فیلترها، در داده‌های خود عمیق‌تر شوید.", "label.is": "برابر است با", - "label.is-false": "Is false", + "label.is-false": "نادرست است", "label.is-not": "برابر نیست با", "label.is-not-set": "تعیین نشده", "label.is-set": "تعیین شده", - "label.is-true": "Is true", + "label.is-true": "درست است", "label.join": "پیوستن", "label.join-team": "پیوستن به تیم", "label.journey": "مسیر", "label.journey-description": "درک کنید که کاربران چگونه در وب‌سایت شما حرکت می کنند.", - "label.journeys": "Journeys", + "label.journeys": "مسیرها", "label.language": "زبان", "label.languages": "زبان‌ها", "label.laptop": "لپ‌تاپ", - "label.last-click": "Last click", + "label.last-click": "آخرین کلیک", "label.last-days": "{x} روز گذشته", "label.last-hours": "{x} ساعت گذشته", "label.last-months": "{x} ماه گذشته", @@ -140,18 +140,18 @@ "label.leave-team": "ترک تیم", "label.less-than": "کمتر از", "label.less-than-equals": "کمتر یا مساوی", - "label.links": "Links", + "label.links": "لینک‌ها", "label.login": "ورود", "label.logout": "خروج", "label.manage": "مدیریت", "label.manager": "مدیر", "label.max": "حداکثر", - "label.medium": "Medium", + "label.medium": "متوسط", "label.member": "عضو", "label.members": "اعضا", "label.min": "حداقل", "label.mobile": "موبایل", - "label.model": "Model", + "label.model": "مدل", "label.more": "بیشتر", "label.my-account": "حساب کاربری من", "label.my-websites": "وب‌سایت‌های من", @@ -160,28 +160,28 @@ "label.none": "هیچ", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "تایید", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "جستجوی ارگانیک", + "label.organic-shopping": "خرید ارگانیک", + "label.organic-social": "شبکه اجتماعی ارگانیک", + "label.organic-video": "ویدیوی ارگانیک", "label.os": "سیستم عامل", - "label.other": "Other", + "label.other": "سایر", "label.overview": "بررسی کلی", "label.owner": "مالک", - "label.page": "Page", + "label.page": "صفحه", "label.page-of": "صفحه {current} از {total}", "label.page-views": "بازدید صفحه", "label.pageTitle": "عنوان صفحه", "label.pages": "صفحه‌ها", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "تبلیغات پولی", + "label.paid-search": "جستجوی پولی", + "label.paid-shopping": "خرید پولی", + "label.paid-social": "شبکه اجتماعی پولی", + "label.paid-video": "ویدیوی پولی", "label.password": "رمز", "label.path": "مسیر", "label.paths": "مسیرها", - "label.pixels": "Pixels", + "label.pixels": "پیکسل‌ها", "label.powered-by": "قدرت گرفته توسط {name}", "label.previous": "قبلی", "label.previous-period": "دوره‌ی قبل", @@ -193,14 +193,14 @@ "label.query": "کوئری", "label.query-parameters": "پارامترهای کوئری", "label.realtime": "آمار زنده", - "label.referral": "Referral", + "label.referral": "ارجاع", "label.referrer": "ارجاع دهنده", "label.referrers": "ارجاع دهندگان", "label.refresh": "به‌روزرسانی", "label.regenerate": "تولید مجدد", "label.region": "منطقه", "label.regions": "مناطق", - "label.remaining": "Remaining", + "label.remaining": "باقی‌مانده", "label.remove": "حذف", "label.remove-member": "حذف عضو", "label.reports": "گزارش‌ها", @@ -218,35 +218,35 @@ "label.search": "جستجو", "label.select": "انتخاب", "label.select-date": "انتخاب تاریخ", - "label.select-filter": "Select filter", + "label.select-filter": "انتخاب فیلتر", "label.select-role": "انتخاب نقش", "label.select-website": "انتخاب وب‌سایت", "label.session": "نشست", - "label.session-data": "Session data", + "label.session-data": "داده‌های نشست", "label.sessions": "نشست‌ها", "label.settings": "تنظیمات", - "label.share": "Share", + "label.share": "اشتراک‌گذاری", "label.share-url": "به اشتراک گذاری آدرس اینترنتی", "label.single-day": "یک روز", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "منابع", "label.start-step": "قدم شروع", "label.steps": "قدم‌ها", "label.sum": "جمع", "label.tablet": "تبلت", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "برچسب", + "label.tags": "برچسب‌ها", "label.team": "تیم", "label.team-id": "شناسه تیم", "label.team-manager": "مدیر تیم", "label.team-member": "عضو تیم", "label.team-name": "نام تیم", "label.team-owner": "مالک تیم", - "label.team-settings": "Team settings", + "label.team-settings": "تنظیمات تیم", "label.team-view-only": "فقط مشاهده‌ی تیم", "label.team-websites": "وب‌سایت‌های تیم", "label.teams": "تیم‌ها", - "label.terms": "Terms", + "label.terms": "شرایط", "label.theme": "تم", "label.this-month": "این ماه", "label.this-week": "این هفته", diff --git a/src/lang/fi-FI.json b/src/lang/fi-FI.json index d2491ced..cacc1d91 100644 --- a/src/lang/fi-FI.json +++ b/src/lang/fi-FI.json @@ -1,206 +1,206 @@ { - "label.access-code": "Access code", + "label.access-code": "Pääsykoodi", "label.actions": "Toiminnat", - "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.activity": "Toimintaloki", + "label.add": "Lisää", + "label.add-board": "Lisää taulu", + "label.add-description": "Lisää kuvaus", + "label.add-member": "Lisää jäsen", + "label.add-step": "Lisää vaihe", "label.add-website": "Lisää verkkosivu", "label.admin": "Järjestelmänvalvoja", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "Kumppani", + "label.after": "Jälkeen", "label.all": "Kaikki", "label.all-time": "Alusta lähtien", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.analytics": "Analytiikka", + "label.apply": "Käytä", + "label.attribution": "Attribuutio", + "label.attribution-description": "Katso, miten käyttäjät ovat vuorovaikutuksessa markkinointisi kanssa ja mikä johtaa konversioihin.", + "label.average": "Keskiarvo", "label.back": "Takaisin", - "label.before": "Before", - "label.boards": "Boards", + "label.before": "Ennen", + "label.boards": "Taulut", "label.bounce-rate": "Välitön poistuminen", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.breakdown": "Erittele", + "label.browser": "Selain", "label.browsers": "Selaimet", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampanjat", "label.cancel": "Peruuta", "label.change-password": "Vaihda salasana", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "Kanavat", + "label.cities": "Kaupungit", + "label.city": "Kaupunki", + "label.clear-all": "Tyhjennä kaikki", + "label.cohort": "Kohortti", + "label.compare": "Vertaa", + "label.compare-dates": "Vertaa päivämääriä", + "label.confirm": "Vahvista", "label.confirm-password": "Vahvista salasana", "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.content": "Sisältö", + "label.continue": "Jatka", + "label.conversion": "Konversio", + "label.conversion-rate": "Konversioprosentti", + "label.conversion-step": "Konversiovaihe", + "label.count": "Lukumäärä", "label.countries": "Maat", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "Maa", + "label.create": "Luo", + "label.create-report": "Luo raportti", + "label.create-team": "Luo tiimi", + "label.create-user": "Luo käyttäjä", + "label.created": "Luotu", + "label.created-by": "Luonut", + "label.currency": "Valuutta", + "label.current": "Nykyinen", "label.current-password": "Nykyinen salasana", "label.custom-range": "Mukautettu ajanjakso", "label.dashboard": "Ohjauspaneeli", "label.data": "Data", - "label.date": "Date", + "label.date": "Päivämäärä", "label.date-range": "Ajanjakso", - "label.day": "Day", + "label.day": "Päivä", "label.default-date-range": "Oletusajanjakso", "label.delete": "Poista", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "Poista raportti", + "label.delete-team": "Poista tiimi", + "label.delete-user": "Poista käyttäjä", "label.delete-website": "Poista verkkosivu", - "label.description": "Description", + "label.description": "Kuvaus", "label.desktop": "Pöytäkone", - "label.details": "Details", - "label.device": "Device", + "label.details": "Tiedot", + "label.device": "Laite", "label.devices": "Laitteet", - "label.direct": "Direct", + "label.direct": "Suora", "label.dismiss": "Hylkää", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "Yksilöllinen ID", + "label.does-not-contain": "Ei sisällä", + "label.does-not-include": "Ei sisällä", + "label.doest-not-exist": "Ei ole olemassa", "label.domain": "Verkkotunnus", - "label.dropoff": "Dropoff", + "label.dropoff": "Poistuminen", "label.edit": "Muokkaa", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", - "label.email": "Email", + "label.edit-dashboard": "Muokkaa ohjauspaneelia", + "label.edit-member": "Muokkaa jäsentä", + "label.email": "Sähköposti", "label.enable-share-url": "Ota jakamisen URL-osoite käyttöön", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "Loppuvaihe", + "label.entry": "Tulo-URL", + "label.event": "Tapahtuma", + "label.event-data": "Tapahtumatiedot", + "label.event-name": "Tapahtuman nimi", "label.events": "Tapahtumat", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", + "label.exists": "On olemassa", + "label.exit": "Poistumis-URL", + "label.expand": "Laajenna", + "label.false": "Epätosi", + "label.field": "Kenttä", + "label.fields": "Kentät", "label.filter": "Filter", "label.filter-combined": "Yhdistetty", "label.filter-raw": "Käsittelemätön", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.filters": "Suodattimet", + "label.first-click": "Ensimmäinen klikkaus", + "label.first-seen": "Ensimmäinen havainto", + "label.funnel": "Suppilo", + "label.funnel-description": "Ymmärrä käyttäjien konversio- ja poistumisprosentti.", + "label.funnels": "Suppilot", + "label.goal": "Tavoite", + "label.goals": "Tavoitteet", + "label.goals-description": "Seuraa sivun katselujen ja tapahtumien tavoitteitasi.", + "label.greater-than": "Suurempi kuin", + "label.greater-than-equals": "Suurempi tai yhtä suuri kuin", + "label.grouped": "Ryhmitelty", + "label.hostname": "Isäntänimi", + "label.includes": "Sisältää", + "label.insight": "Oivallus", + "label.insights": "Oivallukset", + "label.insights-description": "Sukella syvemmälle tietoihisi käyttämällä segmenttejä ja suodattimia.", + "label.is": "On", + "label.is-false": "On epätosi", + "label.is-not": "Ei ole", + "label.is-not-set": "Ei asetettu", + "label.is-set": "Asetettu", + "label.is-true": "On tosi", + "label.join": "Liity", + "label.join-team": "Liity tiimiin", + "label.journey": "Polku", + "label.journey-description": "Ymmärrä, miten käyttäjät navigoivat sivustollasi.", + "label.journeys": "Polut", "label.language": "Kieli", "label.languages": "Kielet", "label.laptop": "Kannettava tietokone", - "label.last-click": "Last click", + "label.last-click": "Viimeinen klikkaus", "label.last-days": "Viimeisimmät {x} päivää", "label.last-hours": "Viimeisimmät {x} tuntia", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "Viimeiset {x} kuukautta", + "label.last-seen": "Viimeksi nähty", + "label.leave": "Poistu", + "label.leave-team": "Poistu tiimistä", + "label.less-than": "Vähemmän kuin", + "label.less-than-equals": "Vähemmän tai yhtä suuri kuin", + "label.links": "Linkit", "label.login": "Kirjaudu sisään", "label.logout": "Kirjaudu ulos", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.manage": "Hallinnoi", + "label.manager": "Päällikkö", + "label.max": "Maksimi", + "label.medium": "Keskitaso", + "label.member": "Jäsen", + "label.members": "Jäsenet", + "label.min": "Minimi", "label.mobile": "Puhelin", "label.model": "Model", "label.more": "Lisää", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "Oma tili", + "label.my-websites": "Omat verkkosivut", "label.name": "Nimi", "label.new-password": "Uusi salasana", - "label.none": "None", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", + "label.none": "Ei mitään", + "label.number-of-records": "{x} {x, plural, one {tietue} other {tietuetta}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Orgaaninen haku", + "label.organic-shopping": "Orgaaninen ostaminen", + "label.organic-social": "Orgaaninen sosiaalinen", + "label.organic-video": "Orgaaninen video", "label.os": "OS", - "label.other": "Other", - "label.overview": "Overview", + "label.other": "Muu", + "label.overview": "Yleiskatsaus", "label.owner": "Omistaja", - "label.page": "Page", - "label.page-of": "Page {current} of {total}", + "label.page": "Sivu", + "label.page-of": "Sivu {current} / {total}", "label.page-views": "Sivun näyttökerrat", - "label.pageTitle": "Page title", + "label.pageTitle": "Sivun otsikko", "label.pages": "Sivut", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Maksetut mainokset", + "label.paid-search": "Maksettu haku", + "label.paid-shopping": "Maksettu ostaminen", + "label.paid-social": "Maksettu sosiaalinen", + "label.paid-video": "Maksettu video", "label.password": "Salasana", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Polku", + "label.paths": "Polut", + "label.pixels": "Pikselit", "label.powered-by": "Voimanlähteenä {name}", "label.previous": "Previous", "label.previous-period": "Previous period", "label.previous-year": "Previous year", "label.profile": "Profiili", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.properties": "Ominaisuudet", + "label.property": "Ominaisuus", + "label.queries": "Kyselyt", + "label.query": "Kysely", + "label.query-parameters": "Kyselyn parametrit", "label.realtime": "Juuri nyt", - "label.referral": "Referral", + "label.referral": "Viittaus", "label.referrer": "Referrer", "label.referrers": "Viittaajat", "label.refresh": "Päivitä", "label.regenerate": "Regenerate", "label.region": "Region", "label.regions": "Regions", - "label.remaining": "Remaining", + "label.remaining": "Jäljellä", "label.remove": "Remove", "label.remove-member": "Remove member", "label.reports": "Reports", @@ -209,44 +209,44 @@ "label.reset-website": "Nollaa tilastot", "label.retention": "Retention", "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Tulot", + "label.revenue-description": "Katso tulosi ajan mittaan.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Tallenna", - "label.screens": "Screens", + "label.screens": "Näytöt", "label.search": "Search", "label.select": "Select", "label.select-date": "Select date", - "label.select-filter": "Select filter", + "label.select-filter": "Valitse suodatin", "label.select-role": "Select role", "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Istunto", + "label.session-data": "Istuntotiedot", "label.sessions": "Sessions", "label.settings": "Asetukset", - "label.share": "Share", + "label.share": "Jaa", "label.share-url": "Jaa URL", "label.single-day": "Yksi päivä", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", + "label.sources": "Lähteet", + "label.start-step": "Aloitusvaihe", + "label.steps": "Vaiheet", "label.sum": "Sum", "label.tablet": "Tabletti", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Tunniste", + "label.tags": "Tunnisteet", "label.team": "Team", "label.team-id": "Team ID", "label.team-manager": "Team manager", "label.team-member": "Team member", "label.team-name": "Team name", "label.team-owner": "Team owner", - "label.team-settings": "Team settings", + "label.team-settings": "Tiimin asetukset", "label.team-view-only": "Team view only", "label.team-websites": "Team websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Ehdot", "label.theme": "Teema", "label.this-month": "Tämä kuukausi", "label.this-week": "Tämä viikko", diff --git a/src/lang/fo-FO.json b/src/lang/fo-FO.json index 90a15ad2..0e5f60eb 100644 --- a/src/lang/fo-FO.json +++ b/src/lang/fo-FO.json @@ -1,253 +1,253 @@ { - "label.access-code": "Access code", + "label.access-code": "Aðgangskoda", "label.actions": "Gerðir", "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.add": "Legg afturat", + "label.add-board": "Legg borð afturat", + "label.add-description": "Legg lýsing afturat", + "label.add-member": "Legg lim afturat", + "label.add-step": "Legg stig afturat", "label.add-website": "Legg heimasíðu afturat", "label.admin": "Fyrisitari", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "Samband", + "label.after": "Eftir", "label.all": "Alt", - "label.all-time": "All time", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.all-time": "Allur tíðin", + "label.analytics": "Greining", + "label.apply": "Nýt", + "label.attribution": "Áseting", + "label.attribution-description": "Síggj hvussu brúkarar samskifta við marknaðarføringina og hvat førir til umvendingar.", + "label.average": "Miðal", "label.back": "Aftur", - "label.before": "Before", - "label.boards": "Boards", + "label.before": "Áðrenn", + "label.boards": "Borð", "label.bounce-rate": "Bounce prosenttal", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.breakdown": "Sundurgreining", + "label.browser": "Kagi", "label.browsers": "Kagar", - "label.campaigns": "Campaigns", + "label.campaigns": "Herferðir", "label.cancel": "Strika", "label.change-password": "Skift loyniorð", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "Rásir", + "label.cities": "Býir", + "label.city": "Býur", + "label.clear-all": "Tøm alt", + "label.cohort": "Bólkur", + "label.compare": "Samanber", + "label.compare-dates": "Samanber dato", + "label.confirm": "Staðfest", "label.confirm-password": "Vátta loyniorð", - "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.contains": "Inniheldur", + "label.content": "Innihald", + "label.continue": "Halt fram", + "label.conversion": "Umvending", + "label.conversion-rate": "Umvendingarprosent", + "label.conversion-step": "Umvendingarstigur", + "label.count": "Tal", "label.countries": "Lond", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "Land", + "label.create": "Stovna", + "label.create-report": "Stovna frágreiðing", + "label.create-team": "Stovna lið", + "label.create-user": "Stovna brúkara", + "label.created": "Stovnaður", + "label.created-by": "Stovnaður av", + "label.currency": "Gjaldoyra", + "label.current": "Núverandi", "label.current-password": "Núverandi loyniorð", "label.custom-range": "Tillaga spenni", "label.dashboard": "Yvirlitsskíggi", - "label.data": "Data", - "label.date": "Date", + "label.data": "Dáta", + "label.date": "Dato", "label.date-range": "Vel dato", - "label.day": "Day", + "label.day": "Dagur", "label.default-date-range": "Forsett dato", "label.delete": "Sletta", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "Strika frágreiðing", + "label.delete-team": "Strika lið", + "label.delete-user": "Strika brúkara", "label.delete-website": "Sletta heimasíðu", - "label.description": "Description", + "label.description": "Lýsing", "label.desktop": "Borðtelda", - "label.details": "Details", - "label.device": "Device", + "label.details": "Nærri upplýsingar", + "label.device": "Tól", "label.devices": "Tóleindir", - "label.direct": "Direct", + "label.direct": "Beinleiðis", "label.dismiss": "Lat fara", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "Sermerkt ID", + "label.does-not-contain": "Inniheldur ikki", + "label.does-not-include": "Er ikki við", + "label.doest-not-exist": "Er ikki til", "label.domain": "Økisnavn", "label.dropoff": "Dropoff", "label.edit": "Ger broyting", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", - "label.email": "Email", + "label.edit-dashboard": "Ritstjórna yvirlitsskíggja", + "label.edit-member": "Ritstjórna lim", + "label.email": "Teldupostur", "label.enable-share-url": "Virkja deili leinki", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "Endastigur", + "label.entry": "Inngangs URL", + "label.event": "Tiltak", + "label.event-data": "Tiltaksdata", + "label.event-name": "Tiltaksnavn", "label.events": "Hendingar/tiltøk", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", - "label.filter": "Filter", + "label.exists": "Er til", + "label.exit": "Útgangs URL", + "label.expand": "Víðka", + "label.false": "Falskt", + "label.field": "Øki", + "label.fields": "Øki", + "label.filter": "Sía", "label.filter-combined": "Samansett", "label.filter-raw": "Óviðgjørt", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", - "label.language": "Language", - "label.languages": "Languages", + "label.filters": "Síur", + "label.first-click": "Fyrsta trýst", + "label.first-seen": "Fyrst sæddur", + "label.funnel": "Traktari", + "label.funnel-description": "Fá yvirlit yvir umvendingar og fráfall hjá brúkarum.", + "label.funnels": "Traktarar", + "label.goal": "Mál", + "label.goals": "Mál", + "label.goals-description": "Fylg við málum fyri síðuvísingar og tiltøk.", + "label.greater-than": "Størri enn", + "label.greater-than-equals": "Størri ella javnt", + "label.grouped": "Bólkað", + "label.hostname": "Vertnavn", + "label.includes": "Inniheldur", + "label.insight": "Innlit", + "label.insights": "Innlit", + "label.insights-description": "Fá meira innlit í tínar dátur við at brúka bólkar og síur.", + "label.is": "Er", + "label.is-false": "Er falskt", + "label.is-not": "Er ikki", + "label.is-not-set": "Er ikki sett", + "label.is-set": "Er sett", + "label.is-true": "Er satt", + "label.join": "Luttak", + "label.join-team": "Luttak í liði", + "label.journey": "Ferð", + "label.journey-description": "Fá yvirlit yvir hvussu brúkarar ferðast á heimasíðuni.", + "label.journeys": "Ferðir", + "label.language": "Mál", + "label.languages": "Mál", "label.laptop": "Fartelda", - "label.last-click": "Last click", + "label.last-click": "Seinasta trýst", "label.last-days": "Seinastu {x} dagarnar", "label.last-hours": "Seinastu {x} tímarnar", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "Seinastu {x} mánaðirnar", + "label.last-seen": "Síðst sæddur", + "label.leave": "Far burtur", + "label.leave-team": "Far úr liði", + "label.less-than": "Minni enn", + "label.less-than-equals": "Minni ella javnt", + "label.links": "Leinkjur", "label.login": "Rita inn", "label.logout": "Rita út", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.manage": "Stýra", + "label.manager": "Stjóri", + "label.max": "Mest", + "label.medium": "Miðal", + "label.member": "Limur", + "label.members": "Limir", + "label.min": "Minst", "label.mobile": "Telefon", "label.model": "Model", "label.more": "Meira", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "Mín konto", + "label.my-websites": "Mínar heimasíður", "label.name": "Navn", "label.new-password": "Nýtt loyniorð", - "label.none": "None", + "label.none": "Eingin", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organisk leiting", + "label.organic-shopping": "Organisk keyp", + "label.organic-social": "Organisk sosial miðla", + "label.organic-video": "Organisk video", "label.os": "OS", - "label.other": "Other", - "label.overview": "Overview", - "label.owner": "Owner", - "label.page": "Page", - "label.page-of": "Page {current} of {total}", + "label.other": "Annað", + "label.overview": "Yvirlit", + "label.owner": "Eigari", + "label.page": "Síða", + "label.page-of": "Síða {current} av {total}", "label.page-views": "Opnaðar síðir", - "label.pageTitle": "Page title", + "label.pageTitle": "Síðuheiti", "label.pages": "Síðir", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Goldnar lýsingar", + "label.paid-search": "Goldin leiting", + "label.paid-shopping": "Goldið keyp", + "label.paid-social": "Goldin sosial miðla", + "label.paid-video": "Goldið video", "label.password": "Loyniorð", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", - "label.powered-by": "Powered by {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.path": "Leið", + "label.paths": "Leiðir", + "label.pixels": "Pikslur", + "label.powered-by": "Rikið av {name}", + "label.previous": "Fyrra", + "label.previous-period": "Fyrra tíðarskeið", + "label.previous-year": "Fyrra ár", "label.profile": "Vangi", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.properties": "Eginleikar", + "label.property": "Eginleiki", + "label.queries": "Fyrispurningar", + "label.query": "Fyrispurningur", + "label.query-parameters": "Fyrispurningsparametrar", "label.realtime": "Beinleiðis", - "label.referral": "Referral", - "label.referrer": "Referrer", + "label.referral": "Ávísing", + "label.referrer": "Ávísari", "label.referrers": "Framsendingar", - "label.refresh": "Endurskapa", - "label.regenerate": "Regenerate", - "label.region": "Region", - "label.regions": "Regions", - "label.remaining": "Remaining", - "label.remove": "Remove", - "label.remove-member": "Remove member", - "label.reports": "Reports", - "label.required": "Kravt", + "label.refresh": "Dagfør", + "label.regenerate": "Endurskapa", + "label.region": "Øki", + "label.regions": "Øki", + "label.remaining": "Eftir", + "label.remove": "Fjern", + "label.remove-member": "Fjern lim", + "label.reports": "Frágreiðingar", + "label.required": "Kravið", "label.reset": "Nulstilla", - "label.reset-website": "Reset statistics", - "label.retention": "Retention", - "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", - "label.role": "Role", - "label.run-query": "Run query", + "label.reset-website": "Nulstilla heimasíðu", + "label.retention": "Hald", + "label.retention-description": "Mát hvussu ofta brúkarar koma aftur á tína síðu.", + "label.revenue": "Inntøka", + "label.revenue-description": "Fá yvirlit yvir inntøku yvir tíð.", + "label.role": "Leiklutur", + "label.run-query": "Koyr fyrispurning", "label.save": "Goym", - "label.screens": "Screens", - "label.search": "Search", - "label.select": "Select", - "label.select-date": "Select date", - "label.select-filter": "Select filter", - "label.select-role": "Select role", - "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", - "label.sessions": "Sessions", + "label.screens": "Skíggjar", + "label.search": "Leita", + "label.select": "Vel", + "label.select-date": "Vel dato", + "label.select-filter": "Vel síu", + "label.select-role": "Vel leiklut", + "label.select-website": "Vel heimasíðu", + "label.session": "Seta", + "label.session-data": "Setudáta", + "label.sessions": "Setur", "label.settings": "Stillingar", - "label.share": "Share", + "label.share": "Deil", "label.share-url": "Deil leinku", "label.single-day": "Einkultur dagur", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", - "label.sum": "Sum", + "label.sources": "Keldur", + "label.start-step": "Byrjanarstigur", + "label.steps": "Stig", + "label.sum": "Samanlagt", "label.tablet": "Teldil", - "label.tag": "Tag", - "label.tags": "Tags", - "label.team": "Team", - "label.team-id": "Team ID", - "label.team-manager": "Team manager", - "label.team-member": "Team member", - "label.team-name": "Team name", - "label.team-owner": "Team owner", - "label.team-settings": "Team settings", - "label.team-view-only": "Team view only", - "label.team-websites": "Team websites", - "label.teams": "Teams", - "label.terms": "Terms", - "label.theme": "Theme", + "label.tag": "Merki", + "label.tags": "Merki", + "label.team": "Lið", + "label.team-id": "Lið ID", + "label.team-manager": "Liðleiðari", + "label.team-member": "Liðlimur", + "label.team-name": "Liðnavn", + "label.team-owner": "Liðeigari", + "label.team-settings": "Liðstillingar", + "label.team-view-only": "Bert til at síggja lið", + "label.team-websites": "Lið heimasíður", + "label.teams": "Lið", + "label.terms": "Treytir", + "label.theme": "Evni", "label.this-month": "Hendan mánan", "label.this-week": "Hesa vikuna", "label.this-year": "Hetta árið", diff --git a/src/lang/fr-FR.json b/src/lang/fr-FR.json index c57b9a72..e1f0e945 100644 --- a/src/lang/fr-FR.json +++ b/src/lang/fr-FR.json @@ -3,7 +3,7 @@ "label.actions": "Actions", "label.activity": "Journal d'activité", "label.add": "Ajouter", - "label.add-board": "Add board", + "label.add-board": "Ajouter un tableau", "label.add-description": "Ajouter une description", "label.add-member": "Ajouter un membre", "label.add-step": "Ajouter une étape", @@ -13,14 +13,14 @@ "label.after": "Après", "label.all": "Tout", "label.all-time": "Toutes les données", - "label.analytics": "Analytics", - "label.apply": "Apply", + "label.analytics": "Analytique", + "label.apply": "Appliquer", "label.attribution": "Attribution", "label.attribution-description": "Découvrez comment les utilisateurs s'engagent avec votre marketing et ce qui génère des conversions.", "label.average": "Moyenne", "label.back": "Retour", "label.before": "Avant", - "label.boards": "Boards", + "label.boards": "Tableaux", "label.bounce-rate": "Taux de rebond", "label.breakdown": "Répartition", "label.browser": "Navigateur", @@ -32,16 +32,16 @@ "label.cities": "Villes", "label.city": "Ville", "label.clear-all": "Réinitialiser", - "label.cohort": "Cohort", + "label.cohort": "Cohorte", "label.compare": "Comparer", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Comparer les dates", "label.confirm": "Confirmer", "label.confirm-password": "Confirmation du mot de passe", "label.contains": "Contient", "label.content": "Contenu", "label.continue": "Continuer", "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", + "label.conversion-rate": "Taux de conversion", "label.conversion-step": "Étape de conversion", "label.count": "Compte", "label.countries": "Pays", @@ -74,10 +74,10 @@ "label.devices": "Appareils", "label.direct": "Direct", "label.dismiss": "Ignorer", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "ID distinct", "label.does-not-contain": "Ne contient pas", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "N'inclut pas", + "label.doest-not-exist": "N'existe pas", "label.domain": "Domaine", "label.dropoff": "Abandons", "label.edit": "Modifier", @@ -89,11 +89,11 @@ "label.entry": "Chemin d'entrée", "label.event": "Évènement", "label.event-data": "Données d'évènements", - "label.event-name": "Event name", + "label.event-name": "Nom de l'évènement", "label.events": "Évènements", - "label.exists": "Exists", + "label.exists": "Existe", "label.exit": "Chemin de sortie", - "label.expand": "Expand", + "label.expand": "Développer", "label.false": "Faux", "label.field": "Champ", "label.fields": "Champs", @@ -101,37 +101,37 @@ "label.filter-combined": "Combiné", "label.filter-raw": "Brut", "label.filters": "Filtres", - "label.first-click": "First click", + "label.first-click": "Premier clic", "label.first-seen": "Vu pour la première fois", "label.funnel": "Entonnoir", "label.funnel-description": "Comprenez les taux de conversions et d'abandons des utilisateurs.", - "label.funnels": "Funnels", + "label.funnels": "Entonnoirs", "label.goal": "Objectif", "label.goals": "Objectifs", "label.goals-description": "Suivez vos objectifs en matière de pages vues et d'événements.", "label.greater-than": "Supérieur à", "label.greater-than-equals": "Supérieur ou égal à", "label.grouped": "Groupé", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", + "label.hostname": "Nom d'hôte", + "label.includes": "Inclut", + "label.insight": "Aperçu", + "label.insights": "Aperçus", "label.insights-description": "Analysez précisément vos données en utilisant des segments et des filtres.", "label.is": "Est", - "label.is-false": "Is false", + "label.is-false": "Est faux", "label.is-not": "N'est pas", "label.is-not-set": "N'est pas défini", "label.is-set": "Est défini", - "label.is-true": "Is true", + "label.is-true": "Est vrai", "label.join": "Rejoindre", "label.join-team": "Rejoindre une équipe", "label.journey": "Parcours", "label.journey-description": "Comprennez comment les utilisateurs naviguent sur votre site.", - "label.journeys": "Journeys", + "label.journeys": "Parcours", "label.language": "Langue", "label.languages": "Langues", "label.laptop": "Portable", - "label.last-click": "Last click", + "label.last-click": "Dernier clic", "label.last-days": "{x} derniers jours", "label.last-hours": "{x} dernières heures", "label.last-months": "{x} derniers mois", @@ -140,13 +140,13 @@ "label.leave-team": "Quitter l'équipe", "label.less-than": "Inférieur à", "label.less-than-equals": "Inférieur ou égal à", - "label.links": "Links", + "label.links": "Liens", "label.login": "Connexion", "label.logout": "Déconnexion", "label.manage": "Gérer", - "label.manager": "Manager", + "label.manager": "Gestionnaire", "label.max": "Max", - "label.medium": "Support", + "label.medium": "Moyen", "label.member": "Membre", "label.members": "Membres", "label.min": "Min", @@ -161,7 +161,7 @@ "label.number-of-records": "{x} {x, plural, one {enregistrement} other {enregistrements}}", "label.ok": "OK", "label.organic-search": "Recherche organique", - "label.organic-shopping": "E-commerce organique", + "label.organic-shopping": "Achat organique", "label.organic-social": "Réseau social organique", "label.organic-video": "Vidéo organique", "label.os": "OS", @@ -175,7 +175,7 @@ "label.pages": "Pages", "label.paid-ads": "Publicités payantes", "label.paid-search": "Recherche payante", - "label.paid-shopping": "E-commerce payant", + "label.paid-shopping": "Achat payant", "label.paid-social": "Réseau social payant", "label.paid-video": "Vidéo payante", "label.password": "Mot de passe", @@ -200,7 +200,7 @@ "label.regenerate": "Régénérer", "label.region": "Région", "label.regions": "Régions", - "label.remaining": "Remaining", + "label.remaining": "Restant", "label.remove": "Retirer", "label.remove-member": "Retirer le membre", "label.reports": "Rapports", @@ -209,23 +209,23 @@ "label.reset-website": "Réinitialiser les statistiques", "label.retention": "Rétention", "label.retention-description": "Mesurez l'attractivité de votre site en suivant la fréquence de retour des utilisateurs.", - "label.revenue": "Recettes", - "label.revenue-description": "Examinez vos recettes et comment dépensent vos utilisateurs.", + "label.revenue": "Revenus", + "label.revenue-description": "Consultez vos revenus au fil du temps.", "label.role": "Rôle", "label.run-query": "Exécuter la requête", "label.save": "Enregistrer", - "label.screens": "Résolutions d'écran", + "label.screens": "Écrans", "label.search": "Rechercher", "label.select": "Sélectionner", "label.select-date": "Choisir une période", - "label.select-filter": "Select filter", + "label.select-filter": "Sélectionner un filtre", "label.select-role": "Choisir un rôle", "label.select-website": "Choisir un site", "label.session": "Session", - "label.session-data": "Session data", + "label.session-data": "Données de session", "label.sessions": "Sessions", "label.settings": "Paramètres", - "label.share": "Share", + "label.share": "Partager", "label.share-url": "URL de partage", "label.single-day": "Journée", "label.sms": "SMS", @@ -234,8 +234,8 @@ "label.steps": "Étapes", "label.sum": "Somme", "label.tablet": "Tablette", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Étiquette", + "label.tags": "Étiquettes", "label.team": "Équipe", "label.team-id": "ID d'équipe", "label.team-manager": "Manager de l'équipe", diff --git a/src/lang/ga-ES.json b/src/lang/ga-ES.json index db202f49..a2b23cab 100644 --- a/src/lang/ga-ES.json +++ b/src/lang/ga-ES.json @@ -3,56 +3,56 @@ "label.actions": "Accións", "label.activity": "Rexistro de actividade", "label.add": "Engadir", - "label.add-board": "Add board", + "label.add-board": "Engadir taboleiro", "label.add-description": "Engadir descrición", "label.add-member": "Engadir membro", "label.add-step": "Engadir paso", "label.add-website": "Engadir sitio web", "label.admin": "Administrador/a", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "Afiliado", + "label.after": "Despois", "label.all": "Todo", "label.all-time": "Sempre", "label.analytics": "Analíticas", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Aplicar", + "label.attribution": "Atribución", + "label.attribution-description": "Vexa como os usuarios interactúan co seu márketing e que impulsa as conversións.", "label.average": "Media", "label.back": "Atrás", "label.before": "Antes", - "label.boards": "Boards", + "label.boards": "Taboleiros", "label.bounce-rate": "Proporción de rebote", "label.breakdown": "Desglose", "label.browser": "Navegador", "label.browsers": "Navegadores", - "label.campaigns": "Campaigns", + "label.campaigns": "Campañas", "label.cancel": "Cancelar", "label.change-password": "Mudar contrasinal", - "label.channels": "Channels", + "label.channels": "Canles", "label.cities": "Cidades", "label.city": "Cidade", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", + "label.clear-all": "Limpar todo", + "label.cohort": "Cohorte", "label.compare": "Comparar", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Comparar datas", "label.confirm": "Confirmar", "label.confirm-password": "Confirmar contrasinal", "label.contains": "Contén", - "label.content": "Content", + "label.content": "Contido", "label.continue": "Continuar", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Conversión", + "label.conversion-rate": "Taxa de conversión", + "label.conversion-step": "Paso de conversión", "label.count": "Reconto", "label.countries": "Países", "label.country": "País", "label.create": "Crear", - "label.create-report": "Crear report", - "label.create-team": "Crear team", - "label.create-user": "Crear user", + "label.create-report": "Crear informe", + "label.create-team": "Crear equipo", + "label.create-user": "Crear usuario", "label.created": "Creado", "label.created-by": "Creado por", - "label.currency": "Currency", + "label.currency": "Moeda", "label.current": "Actual", "label.current-password": "Contrasinal actual", "label.custom-range": "Rango personalizado", @@ -72,28 +72,28 @@ "label.details": "Detalles", "label.device": "Dispositivo", "label.devices": "Dispositivos", - "label.direct": "Direct", + "label.direct": "Directo", "label.dismiss": "Desbotar", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "ID distinto", "label.does-not-contain": "Non contén", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Non inclúe", + "label.doest-not-exist": "Non existe", "label.domain": "Dominio", "label.dropoff": "Disminución", "label.edit": "Editar", "label.edit-dashboard": "Editar taboleiro", "label.edit-member": "Editar membro", - "label.email": "Email", + "label.email": "Correo electrónico", "label.enable-share-url": "Activar URL de compartición", - "label.end-step": "End Step", - "label.entry": "Entry URL", + "label.end-step": "Paso final", + "label.entry": "URL de entrada", "label.event": "Evento", "label.event-data": "Datos do evento", - "label.event-name": "Event name", + "label.event-name": "Nome do evento", "label.events": "Eventos", - "label.exists": "Exists", + "label.exists": "Existe", "label.exit": "URL de saída", - "label.expand": "Expand", + "label.expand": "Expandir", "label.false": "Falso", "label.field": "Campo", "label.fields": "Campos", @@ -101,37 +101,37 @@ "label.filter-combined": "Combinado", "label.filter-raw": "Crú", "label.filters": "Filtros", - "label.first-click": "First click", + "label.first-click": "Primeiro clic", "label.first-seen": "Primeira visita", - "label.funnel": "Funnel", + "label.funnel": "Funil", "label.funnel-description": "Entende a taxa de conversión e de abandono dos usuarios.", - "label.funnels": "Funnels", + "label.funnels": "Funís", "label.goal": "Obxectivo", "label.goals": "Obxectivos", "label.goals-description": "Segue os teus obxectivos de visualizacións de páxinas e eventos.", "label.greater-than": "Maior que", "label.greater-than-equals": "Maior ou igual que", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", + "label.grouped": "Agrupado", + "label.hostname": "Nome do host", + "label.includes": "Inclúe", + "label.insight": "Información", + "label.insights": "Informacións", + "label.insights-description": "Afonda nos teus datos usando segmentos e filtros.", "label.is": "É", - "label.is-false": "Is false", + "label.is-false": "É falso", "label.is-not": "Non é", "label.is-not-set": "Non está establecido", "label.is-set": "Está establecido", - "label.is-true": "Is true", + "label.is-true": "É verdadeiro", "label.join": "Unirse", "label.join-team": "Unirse ao equipo", "label.journey": "Traxectoria", "label.journey-description": "Entende como os usuarios navegan polo teu sitio web.", - "label.journeys": "Journeys", + "label.journeys": "Traxectorias", "label.language": "Idioma", "label.languages": "Idiomas", "label.laptop": "Portátil", - "label.last-click": "Last click", + "label.last-click": "Último clic", "label.last-days": "Últimos {x} días", "label.last-hours": "Últimas {x} horas", "label.last-months": "Últimos {x} meses", @@ -140,48 +140,48 @@ "label.leave-team": "Deixar o equipo", "label.less-than": "Menor que", "label.less-than-equals": "Menor ou igual que", - "label.links": "Links", + "label.links": "Ligazóns", "label.login": "Acceder", "label.logout": "Pechar sesión", "label.manage": "Xestionar", "label.manager": "Xestor", "label.max": "Max", - "label.medium": "Medium", + "label.medium": "Medio", "label.member": "Membro", "label.members": "Membros", "label.min": "Min", "label.mobile": "Móbil", - "label.model": "Model", + "label.model": "Modelo", "label.more": "Máis", "label.my-account": "A miña conta", "label.my-websites": "Os meus sitios web", "label.name": "Nome", "label.new-password": "Novo contrasinal", - "label.none": "None", + "label.none": "Ningún", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Busca orgánica", + "label.organic-shopping": "Compra orgánica", + "label.organic-social": "Social orgánico", + "label.organic-video": "Vídeo orgánico", "label.os": "Sistema operativo", - "label.other": "Other", + "label.other": "Outro", "label.overview": "Resumo", "label.owner": "Propietario/a", - "label.page": "Page", + "label.page": "Páxina", "label.page-of": "Páxina {current} de {total}", "label.page-views": "Vistas de páxinas", "label.pageTitle": "Título da páxina", "label.pages": "Páxinas", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Anuncios de pago", + "label.paid-search": "Busca de pago", + "label.paid-shopping": "Compra de pago", + "label.paid-social": "Social de pago", + "label.paid-video": "Vídeo de pago", "label.password": "Contrasinal", "label.path": "Ruta", "label.paths": "Rutas", - "label.pixels": "Pixels", + "label.pixels": "Píxeles", "label.powered-by": "Funciona grazas a {name}", "label.previous": "Anterior", "label.previous-period": "Periodo anterior", @@ -193,14 +193,14 @@ "label.query": "Petición", "label.query-parameters": "Parámetros da petición", "label.realtime": "Agora mesmo", - "label.referral": "Referral", + "label.referral": "Referencia", "label.referrer": "Orixe", "label.referrers": "Orixes", "label.refresh": "Actualizar", "label.regenerate": "Rexenerar", "label.region": "Rexión", "label.regions": "Rexións", - "label.remaining": "Remaining", + "label.remaining": "Restante", "label.remove": "Eliminar", "label.remove-member": "Eliminar membro", "label.reports": "Reportes", @@ -218,35 +218,35 @@ "label.search": "Buscar", "label.select": "Seleccionar", "label.select-date": "Seleccionar data", - "label.select-filter": "Select filter", + "label.select-filter": "Seleccionar filtro", "label.select-role": "Seleccionar rol", "label.select-website": "Seleccionar sitio web", "label.session": "Sesión", - "label.session-data": "Session data", + "label.session-data": "Datos da sesión", "label.sessions": "Sesións", "label.settings": "Axustes", - "label.share": "Share", + "label.share": "Compartir", "label.share-url": "Compartir URL", "label.single-day": "Un só día", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Fontes", "label.start-step": "Start Step", "label.steps": "Pasos", "label.sum": "Suma", "label.tablet": "Tableta", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Etiqueta", + "label.tags": "Etiquetas", "label.team": "Equipo", "label.team-id": "ID do equipo", "label.team-manager": "Xestor do equipo", "label.team-member": "Membro do equipo", "label.team-name": "Nome do equipo", "label.team-owner": "Propietario do equipo", - "label.team-settings": "Team settings", + "label.team-settings": "Axustes do equipo", "label.team-view-only": "Equipo de só lectura", "label.team-websites": "Sitios web do equipo", "label.teams": "Equipos", - "label.terms": "Terms", + "label.terms": "Termos", "label.theme": "Decorado", "label.this-month": "Este mes", "label.this-week": "Esta semana", diff --git a/src/lang/he-IL.json b/src/lang/he-IL.json index 6296b9b5..9de3af45 100644 --- a/src/lang/he-IL.json +++ b/src/lang/he-IL.json @@ -1,206 +1,206 @@ { - "label.access-code": "Access code", + "label.access-code": "קוד גישה", "label.actions": "פעולות", - "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.activity": "יומן פעילות", + "label.add": "הוסף", + "label.add-board": "הוסף לוח", + "label.add-description": "הוסף תיאור", + "label.add-member": "הוסף חבר", + "label.add-step": "הוסף שלב", "label.add-website": "הוספת אתר", "label.admin": "מנהל", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "שותף", + "label.after": "אחרי", "label.all": "הכל", - "label.all-time": "All time", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.all-time": "כל הזמנים", + "label.analytics": "אנליטיקה", + "label.apply": "החל", + "label.attribution": "שיוך", + "label.attribution-description": "צפה כיצד משתמשים מתקשרים עם השיווק שלך ומה מניע המרות.", + "label.average": "ממוצע", "label.back": "חזרה", - "label.before": "Before", - "label.boards": "Boards", - "label.bounce-rate": "Bounce rate", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.before": "לפני", + "label.boards": "לוחות", + "label.bounce-rate": "שיעור נטישה", + "label.breakdown": "פירוט", + "label.browser": "דפדפן", "label.browsers": "דפדפנים", - "label.campaigns": "Campaigns", + "label.campaigns": "קמפיינים", "label.cancel": "ביטול", "label.change-password": "שינוי סיסמה", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "ערוצים", + "label.cities": "ערים", + "label.city": "עיר", + "label.clear-all": "נקה הכל", + "label.cohort": "קבוצה", + "label.compare": "השווה", + "label.compare-dates": "השווה תאריכים", + "label.confirm": "אשר", "label.confirm-password": "אישור סיסמה", "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.content": "תוכן", + "label.continue": "המשך", + "label.conversion": "המרה", + "label.conversion-rate": "שיעור המרה", + "label.conversion-step": "שלב המרה", + "label.count": "ספירה", "label.countries": "מדינות", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "מדינה", + "label.create": "צור", + "label.create-report": "צור דוח", + "label.create-team": "צור צוות", + "label.create-user": "צור משתמש", + "label.created": "נוצר", + "label.created-by": "נוצר על ידי", + "label.currency": "מטבע", + "label.current": "נוכחי", "label.current-password": "סיסמה נוכחית", "label.custom-range": "טווח מותאם", "label.dashboard": "דשבורד", - "label.data": "Data", - "label.date": "Date", + "label.data": "נתונים", + "label.date": "תאריך", "label.date-range": "טווח תאריכים", - "label.day": "Day", + "label.day": "יום", "label.default-date-range": "טווח תאריכים בברירת מחדל", "label.delete": "הסרה", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "מחק דוח", + "label.delete-team": "מחק צוות", + "label.delete-user": "מחק משתמש", "label.delete-website": "הסרת אתר", - "label.description": "Description", - "label.desktop": "דסקטופ", - "label.details": "Details", - "label.device": "Device", + "label.description": "תיאור", + "label.desktop": "מחשב שולחני", + "label.details": "פרטים", + "label.device": "מכשיר", "label.devices": "מכשירים", - "label.direct": "Direct", + "label.direct": "ישיר", "label.dismiss": "שיחרור", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "מזהה ייחודי", + "label.does-not-contain": "לא מכיל", + "label.does-not-include": "לא כולל", + "label.doest-not-exist": "לא קיים", "label.domain": "דומיין", - "label.dropoff": "Dropoff", + "label.dropoff": "עזיבה", "label.edit": "עריכה", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", - "label.email": "Email", + "label.edit-dashboard": "ערוך לוח מחוונים", + "label.edit-member": "ערוך חבר", + "label.email": "אימייל", "label.enable-share-url": "הפעלת URL שיתוף", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "שלב סיום", + "label.entry": "כתובת כניסה", + "label.event": "אירוע", + "label.event-data": "נתוני אירוע", + "label.event-name": "שם האירוע", "label.events": "אירועים", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", + "label.exists": "קיים", + "label.exit": "כתובת יציאה", + "label.expand": "הרחב", + "label.false": "שקר", + "label.field": "שדה", + "label.fields": "שדות", "label.filter": "Filter", "label.filter-combined": "משותף", "label.filter-raw": "גולמי", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.filters": "מסננים", + "label.first-click": "קליק ראשון", + "label.first-seen": "נראה לראשונה", + "label.funnel": "משפך", + "label.funnel-description": "הבן את שיעור ההמרה והעזיבה של המשתמשים.", + "label.funnels": "משפכים", + "label.goal": "מטרה", + "label.goals": "מטרות", + "label.goals-description": "עקוב אחרי המטרות שלך לצפיות בדף ואירועים.", + "label.greater-than": "גדול מ-", + "label.greater-than-equals": "גדול או שווה ל-", + "label.grouped": "מקובץ", + "label.hostname": "שם מארח", + "label.includes": "כולל", + "label.insight": "תובנה", + "label.insights": "תובנות", + "label.insights-description": "צלול עמוק יותר לנתונים שלך באמצעות פילוחים ומסננים.", + "label.is": "הוא", + "label.is-false": "הוא שקר", + "label.is-not": "אינו", + "label.is-not-set": "לא הוגדר", + "label.is-set": "הוגדר", + "label.is-true": "הוא אמת", + "label.join": "הצטרף", + "label.join-team": "הצטרף לצוות", + "label.journey": "מסע", + "label.journey-description": "הבן כיצד משתמשים מנווטים באתר שלך.", + "label.journeys": "מסעות", "label.language": "Language", "label.languages": "Languages", "label.laptop": "לפטופ", - "label.last-click": "Last click", + "label.last-click": "קליק אחרון", "label.last-days": "{x} ימים אחרונים", "label.last-hours": "{x} שעות אחרונות", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "{x} חודשים אחרונים", + "label.last-seen": "נראה לאחרונה", + "label.leave": "עזוב", + "label.leave-team": "עזוב צוות", + "label.less-than": "פחות מ-", + "label.less-than-equals": "פחות או שווה ל-", + "label.links": "קישורים", "label.login": "התחברות", "label.logout": "התנתקות", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.manage": "נהל", + "label.manager": "מנהל", + "label.max": "מקסימום", + "label.medium": "בינוני", + "label.member": "חבר", + "label.members": "חברים", + "label.min": "מינימום", "label.mobile": "מובייל", "label.model": "Model", "label.more": "עוד", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "החשבון שלי", + "label.my-websites": "האתרים שלי", "label.name": "שם", "label.new-password": "סיסמה חדשה", - "label.none": "None", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", + "label.none": "ללא", + "label.number-of-records": "{x} {x, plural, one {רשומה} other {רשומות}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "חיפוש אורגני", + "label.organic-shopping": "קניות אורגניות", + "label.organic-social": "רשת חברתית אורגנית", + "label.organic-video": "וידאו אורגני", "label.os": "OS", - "label.other": "Other", - "label.overview": "Overview", - "label.owner": "Owner", - "label.page": "Page", - "label.page-of": "Page {current} of {total}", + "label.other": "אחר", + "label.overview": "סקירה כללית", + "label.owner": "בעלים", + "label.page": "דף", + "label.page-of": "דף {current} מתוך {total}", "label.page-views": "צפיות בדפים", "label.pageTitle": "Page title", "label.pages": "דפים", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "מודעות בתשלום", + "label.paid-search": "חיפוש בתשלום", + "label.paid-shopping": "קניות בתשלום", + "label.paid-social": "רשת חברתית בתשלום", + "label.paid-video": "וידאו בתשלום", "label.password": "סיסמה", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "נתיב", + "label.paths": "נתיבים", + "label.pixels": "פיקסלים", "label.powered-by": "Powered by {name}", "label.previous": "Previous", "label.previous-period": "Previous period", "label.previous-year": "Previous year", "label.profile": "פרופיל", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.properties": "מאפיינים", + "label.property": "מאפיין", + "label.queries": "שאילתות", + "label.query": "שאילתה", + "label.query-parameters": "פרמטרי שאילתה", "label.realtime": "זמן אמת", - "label.referral": "Referral", + "label.referral": "הפניה", "label.referrer": "Referrer", "label.referrers": "מפנים", "label.refresh": "רענון", "label.regenerate": "Regenerate", "label.region": "Region", "label.regions": "Regions", - "label.remaining": "Remaining", + "label.remaining": "נותר", "label.remove": "Remove", "label.remove-member": "Remove member", "label.reports": "Reports", @@ -209,44 +209,44 @@ "label.reset-website": "Reset statistics", "label.retention": "Retention", "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "הכנסה", + "label.revenue-description": "בדוק את ההכנסות שלך לאורך זמן.", "label.role": "Role", "label.run-query": "Run query", "label.save": "שמירה", - "label.screens": "Screens", + "label.screens": "מסכים", "label.search": "Search", "label.select": "Select", "label.select-date": "Select date", - "label.select-filter": "Select filter", + "label.select-filter": "בחר מסנן", "label.select-role": "Select role", "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "סשן", + "label.session-data": "נתוני סשן", "label.sessions": "Sessions", "label.settings": "הגדרות", - "label.share": "Share", + "label.share": "שתף", "label.share-url": "שיתוף URL", "label.single-day": "יום בודד", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", + "label.sources": "מקורות", + "label.start-step": "שלב התחלה", + "label.steps": "שלבים", "label.sum": "Sum", "label.tablet": "טאבלט", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "תגית", + "label.tags": "תגיות", "label.team": "Team", "label.team-id": "Team ID", "label.team-manager": "Team manager", "label.team-member": "Team member", "label.team-name": "Team name", "label.team-owner": "Team owner", - "label.team-settings": "Team settings", + "label.team-settings": "הגדרות צוות", "label.team-view-only": "Team view only", "label.team-websites": "Team websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "תנאים", "label.theme": "Theme", "label.this-month": "החודש", "label.this-week": "השבוע", diff --git a/src/lang/hi-IN.json b/src/lang/hi-IN.json index 69b95aee..d15c16ad 100644 --- a/src/lang/hi-IN.json +++ b/src/lang/hi-IN.json @@ -3,251 +3,251 @@ "label.actions": "कार्य", "label.activity": "गतिविधि लॉग", "label.add": "जोडो", - "label.add-board": "Add board", + "label.add-board": "बोर्ड जोड़ें", "label.add-description": "विवरण लिखें", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.add-member": "सदस्य जोड़ें", + "label.add-step": "चरण जोड़ें", "label.add-website": "वेबसाइट", "label.admin": "प्रशासक", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "संबद्ध", + "label.after": "बाद में", "label.all": "सब", - "label.all-time": "All time", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.all-time": "सभी समय", + "label.analytics": "विश्लेषण", + "label.apply": "लागू करें", + "label.attribution": "अर्पण", + "label.attribution-description": "देखें कि उपयोगकर्ता आपके विपणन के साथ कैसे जुड़ते हैं और क्या रूपांतरण को प्रेरित करता है।", + "label.average": "औसत", "label.back": "पीछे", - "label.before": "Before", - "label.boards": "Boards", + "label.before": "पहले", + "label.boards": "बोर्ड्स", "label.bounce-rate": "उछाल दर", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.breakdown": "विभाजन", + "label.browser": "ब्राउज़र", "label.browsers": "वेब ब्राउज़र", - "label.campaigns": "Campaigns", + "label.campaigns": "अभियान", "label.cancel": "रद्द करें", "label.change-password": "पासवर्ड बदलें", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "चैनल", + "label.cities": "शहर", + "label.city": "शहर", + "label.clear-all": "सभी साफ करें", + "label.cohort": "समूह", + "label.compare": "तुलना करें", + "label.compare-dates": "तिथियों की तुलना करें", + "label.confirm": "पुष्टि करें", "label.confirm-password": "पासवर्ड की पुष्टि कीजिये", - "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.contains": "शामिल है", + "label.content": "सामग्री", + "label.continue": "जारी रखें", + "label.conversion": "रूपांतरण", + "label.conversion-rate": "रूपांतरण दर", + "label.conversion-step": "रूपांतरण चरण", + "label.count": "गिनती", "label.countries": "देश", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "देश", + "label.create": "बनाएँ", + "label.create-report": "रिपोर्ट बनाएं", + "label.create-team": "टीम बनाएं", + "label.create-user": "उपयोगकर्ता बनाएं", + "label.created": "बनाया गया", + "label.created-by": "द्वारा बनाया गया", + "label.currency": "मुद्रा", + "label.current": "वर्तमान", "label.current-password": "वर्तमान पासवर्ड", "label.custom-range": "कस्टम रेंज", "label.dashboard": "नियंत्रण-पट्ट", - "label.data": "Data", - "label.date": "Date", + "label.data": "डेटा", + "label.date": "तिथि", "label.date-range": "तिथि सीमा", - "label.day": "Day", + "label.day": "दिन", "label.default-date-range": "डिफ़ॉल्ट तिथि सीमा", "label.delete": "खाता हटाएं", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "रिपोर्ट हटाएं", + "label.delete-team": "टीम हटाएं", + "label.delete-user": "उपयोगकर्ता हटाएं", "label.delete-website": "वेबसाइट हटाएं", - "label.description": "Description", + "label.description": "विवरण", "label.desktop": "डेस्कटॉप", - "label.details": "Details", - "label.device": "Device", + "label.details": "विवरण", + "label.device": "डिवाइस", "label.devices": "उपकरण", - "label.direct": "Direct", + "label.direct": "प्रत्यक्ष", "label.dismiss": "खारिज कीजिये", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "अद्वितीय आईडी", + "label.does-not-contain": "शामिल नहीं है", + "label.does-not-include": "शामिल नहीं है", + "label.doest-not-exist": "मौजूद नहीं है", "label.domain": "डोमेन", "label.dropoff": "Dropoff", "label.edit": "संपादित करें", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", - "label.email": "Email", + "label.edit-dashboard": "डैशबोर्ड संपादित करें", + "label.edit-member": "सदस्य संपादित करें", + "label.email": "ईमेल", "label.enable-share-url": "शेयर URL सक्षम करें", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "अंतिम चरण", + "label.entry": "प्रवेश URL", + "label.event": "घटना", + "label.event-data": "घटना डेटा", + "label.event-name": "घटना नाम", "label.events": "स्पर्धाएँ", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", - "label.filter": "Filter", + "label.exists": "मौजूद है", + "label.exit": "निकास URL", + "label.expand": "विस्तार करें", + "label.false": "गलत", + "label.field": "फ़ील्ड", + "label.fields": "फ़ील्ड्स", + "label.filter": "फ़िल्टर", "label.filter-combined": "संयुक्त", "label.filter-raw": "रॉ", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", - "label.language": "Language", - "label.languages": "Languages", + "label.filters": "फ़िल्टर", + "label.first-click": "पहला क्लिक", + "label.first-seen": "पहली बार देखा गया", + "label.funnel": "फनल", + "label.funnel-description": "उपयोगकर्ताओं की रूपांतरण और ड्रॉप-ऑफ दर को समझें।", + "label.funnels": "फनल्स", + "label.goal": "लक्ष्य", + "label.goals": "लक्ष्य", + "label.goals-description": "पृष्ठदृश्यों और घटनाओं के लिए अपने लक्ष्यों को ट्रैक करें।", + "label.greater-than": "से अधिक", + "label.greater-than-equals": "से अधिक या बराबर", + "label.grouped": "समूहित", + "label.hostname": "होस्टनाम", + "label.includes": "शामिल है", + "label.insight": "अंतर्दृष्टि", + "label.insights": "अंतर्दृष्टियाँ", + "label.insights-description": "सेगमेंट और फ़िल्टर का उपयोग करके अपने डेटा में गहराई से जाएं।", + "label.is": "है", + "label.is-false": "गलत है", + "label.is-not": "नहीं है", + "label.is-not-set": "सेट नहीं है", + "label.is-set": "सेट है", + "label.is-true": "सही है", + "label.join": "शामिल हों", + "label.join-team": "टीम में शामिल हों", + "label.journey": "यात्रा", + "label.journey-description": "समझें कि उपयोगकर्ता आपकी वेबसाइट पर कैसे नेविगेट करते हैं।", + "label.journeys": "यात्राएँ", + "label.language": "भाषा", + "label.languages": "भाषाएँ", "label.laptop": "लैपटॉप", - "label.last-click": "Last click", + "label.last-click": "अंतिम क्लिक", "label.last-days": "पिछले {x} दिन", "label.last-hours": "पिछले {x} घंटे", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "पिछले {x} महीने", + "label.last-seen": "अंतिम बार देखा गया", + "label.leave": "छोड़ें", + "label.leave-team": "टीम छोड़ें", + "label.less-than": "से कम", + "label.less-than-equals": "से कम या बराबर", + "label.links": "लिंक", "label.login": "लॉग इन", "label.logout": "लॉग आउट", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.manage": "प्रबंधित करें", + "label.manager": "प्रबंधक", + "label.max": "अधिकतम", + "label.medium": "मध्यम", + "label.member": "सदस्य", + "label.members": "सदस्यगण", + "label.min": "न्यूनतम", "label.mobile": "मोबाइल फोन", - "label.model": "Model", + "label.model": "मॉडल", "label.more": "और", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "मेरा खाता", + "label.my-websites": "मेरी वेबसाइट्स", "label.name": "नाम", "label.new-password": "नया पासवर्ड", - "label.none": "None", + "label.none": "कोई नहीं", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "ऑर्गेनिक खोज", + "label.organic-shopping": "ऑर्गेनिक खरीदारी", + "label.organic-social": "ऑर्गेनिक सोशल", + "label.organic-video": "ऑर्गेनिक वीडियो", "label.os": "OS", - "label.other": "Other", - "label.overview": "Overview", - "label.owner": "Owner", - "label.page": "Page", - "label.page-of": "Page {current} of {total}", + "label.other": "अन्य", + "label.overview": "सारांश", + "label.owner": "मालिक", + "label.page": "पृष्ठ", + "label.page-of": "पृष्ठ {current} का {total}", "label.page-views": "पृष्ठ दृश्य", - "label.pageTitle": "Page title", + "label.pageTitle": "पृष्ठ शीर्षक", "label.pages": "पृष्ठों", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "पेड विज्ञापन", + "label.paid-search": "पेड खोज", + "label.paid-shopping": "पेड खरीदारी", + "label.paid-social": "पेड सोशल", + "label.paid-video": "पेड वीडियो", "label.password": "पासवर्ड", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "पथ", + "label.paths": "पथ", + "label.pixels": "पिक्सेल", "label.powered-by": "{name} द्वारा संचालित", "label.previous": "Previous", "label.previous-period": "Previous period", "label.previous-year": "Previous year", "label.profile": "प्रोफ़ाइल", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.properties": "गुण", + "label.property": "गुण", + "label.queries": "प्रश्न", + "label.query": "प्रश्न", + "label.query-parameters": "प्रश्न पैरामीटर", "label.realtime": "वास्तव काल", - "label.referral": "Referral", - "label.referrer": "Referrer", + "label.referral": "संदर्भ", + "label.referrer": "संदर्भकर्ता", "label.referrers": "सन्दर्भदाता", "label.refresh": "रिफ्रेश", - "label.regenerate": "Regenerate", - "label.region": "Region", - "label.regions": "Regions", - "label.remaining": "Remaining", - "label.remove": "Remove", - "label.remove-member": "Remove member", - "label.reports": "प्रतिवेदन", + "label.regenerate": "पुनः उत्पन्न करें", + "label.region": "क्षेत्र", + "label.regions": "क्षेत्र", + "label.remaining": "शेष", + "label.remove": "हटाएं", + "label.remove-member": "सदस्य हटाएं", + "label.reports": "रिपोर्ट्स", "label.required": "अपेक्षित", "label.reset": "रीसेट", - "label.reset-website": "Reset statistics", - "label.retention": "Retention", - "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", - "label.role": "Role", - "label.run-query": "Run query", + "label.reset-website": "आँकड़े रीसेट करें", + "label.retention": "पुनः आगमन", + "label.retention-description": "यह मापें कि उपयोगकर्ता कितनी बार आपकी वेबसाइट पर लौटते हैं।", + "label.revenue": "राजस्व", + "label.revenue-description": "समय के साथ अपने राजस्व को देखें।", + "label.role": "भूमिका", + "label.run-query": "प्रश्न चलाएँ", "label.save": "सहेजें", - "label.screens": "Screens", - "label.search": "Search", - "label.select": "Select", - "label.select-date": "Select date", - "label.select-filter": "Select filter", - "label.select-role": "Select role", - "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", - "label.sessions": "Sessions", + "label.screens": "स्क्रीन", + "label.search": "खोजें", + "label.select": "चुनें", + "label.select-date": "तिथि चुनें", + "label.select-filter": "फ़िल्टर चुनें", + "label.select-role": "भूमिका चुनें", + "label.select-website": "वेबसाइट चुनें", + "label.session": "सत्र", + "label.session-data": "सत्र डेटा", + "label.sessions": "सत्र", "label.settings": "समायोजन", - "label.share": "Share", + "label.share": "साझा करें", "label.share-url": "यूआरएल साझा करें", "label.single-day": "एक दिन", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", - "label.sum": "Sum", + "label.sources": "स्रोत", + "label.start-step": "प्रारंभिक चरण", + "label.steps": "चरण", + "label.sum": "योग", "label.tablet": "टैबलेट", - "label.tag": "Tag", - "label.tags": "Tags", - "label.team": "Team", - "label.team-id": "Team ID", - "label.team-manager": "Team manager", - "label.team-member": "Team member", - "label.team-name": "Team name", - "label.team-owner": "Team owner", - "label.team-settings": "Team settings", - "label.team-view-only": "Team view only", - "label.team-websites": "Team websites", - "label.teams": "Teams", - "label.terms": "Terms", - "label.theme": "Theme", + "label.tag": "टैग", + "label.tags": "टैग्स", + "label.team": "टीम", + "label.team-id": "टीम आईडी", + "label.team-manager": "टीम प्रबंधक", + "label.team-member": "टीम सदस्य", + "label.team-name": "टीम नाम", + "label.team-owner": "टीम मालिक", + "label.team-settings": "टीम सेटिंग्स", + "label.team-view-only": "केवल टीम देखें", + "label.team-websites": "टीम वेबसाइट्स", + "label.teams": "टीमें", + "label.terms": "शर्तें", + "label.theme": "थीम", "label.this-month": "इस महीने", "label.this-week": "इस सप्ताह", "label.this-year": "इस साल", diff --git a/src/lang/hr-HR.json b/src/lang/hr-HR.json index 0ac1ddf1..17b6bbf9 100644 --- a/src/lang/hr-HR.json +++ b/src/lang/hr-HR.json @@ -1,206 +1,206 @@ { - "label.access-code": "Access code", - "label.actions": "Actions", - "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.access-code": "Pristupni kod", + "label.actions": "Akcije", + "label.activity": "Dnevnik aktivnosti", + "label.add": "Dodaj", + "label.add-board": "Dodaj ploču", + "label.add-description": "Dodaj opis", + "label.add-member": "Dodaj člana", + "label.add-step": "Dodaj korak", "label.add-website": "Dodaj web stranicu", "label.admin": "Administrator", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "Partner", + "label.after": "Nakon", "label.all": "Sve", "label.all-time": "Svo vrijeme", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.analytics": "Analitika", + "label.apply": "Primijeni", + "label.attribution": "Atribucija", + "label.attribution-description": "Pogledajte kako korisnici komuniciraju s vašim marketingom i što dovodi do konverzija.", + "label.average": "Prosjek", "label.back": "Natrag ", - "label.before": "Before", - "label.boards": "Boards", - "label.bounce-rate": "Bounce rate", - "label.breakdown": "Breakdown", - "label.browser": "Browser", - "label.browsers": "Browsers", - "label.campaigns": "Campaigns", + "label.before": "Prije", + "label.boards": "Ploče", + "label.bounce-rate": "Stopa napuštanja", + "label.breakdown": "Raspad", + "label.browser": "Preglednik", + "label.browsers": "Preglednici", + "label.campaigns": "Kampanje", "label.cancel": "Odustani", "label.change-password": "Promijeni lozinku", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "Kanali", + "label.cities": "Gradovi", + "label.city": "Grad", + "label.clear-all": "Očisti sve", + "label.cohort": "Kohorta", + "label.compare": "Usporedi", + "label.compare-dates": "Usporedi datume", + "label.confirm": "Potvrdi", "label.confirm-password": "Potvrdi lozinku", "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.content": "Sadržaj", + "label.continue": "Nastavi", + "label.conversion": "Konverzija", + "label.conversion-rate": "Stopa konverzije", + "label.conversion-step": "Korak konverzije", + "label.count": "Broj", "label.countries": "Countries", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "Država", + "label.create": "Kreiraj", + "label.create-report": "Kreiraj izvještaj", + "label.create-team": "Kreiraj tim", + "label.create-user": "Kreiraj korisnika", + "label.created": "Kreirano", + "label.created-by": "Kreirao", + "label.currency": "Valuta", + "label.current": "Trenutno", "label.current-password": "Trenutna lozinka", "label.custom-range": "Prilagođeni raspon", "label.dashboard": "Nadzorna ploča", - "label.data": "Data", - "label.date": "Date", + "label.data": "Podaci", + "label.date": "Datum", "label.date-range": "Raspon datuma", - "label.day": "Day", + "label.day": "Dan", "label.default-date-range": "Zadani datumski raspon", "label.delete": "Obriši", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "Obriši izvještaj", + "label.delete-team": "Obriši tim", + "label.delete-user": "Obriši korisnika", "label.delete-website": "Obriši web stranicu", - "label.description": "Description", - "label.desktop": "Desktop", - "label.details": "Details", - "label.device": "Device", - "label.devices": "Devices", - "label.direct": "Direct", + "label.description": "Opis", + "label.desktop": "Stolno računalo", + "label.details": "Detalji", + "label.device": "Uređaj", + "label.devices": "Uređaji", + "label.direct": "Direktno", "label.dismiss": "Odbaci", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "Jedinstveni ID", + "label.does-not-contain": "Ne sadrži", + "label.does-not-include": "Ne uključuje", + "label.doest-not-exist": "Ne postoji", "label.domain": "Domena", - "label.dropoff": "Dropoff", + "label.dropoff": "Odlazak", "label.edit": "Uredi", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", - "label.email": "Email", + "label.edit-dashboard": "Uredi nadzornu ploču", + "label.edit-member": "Uredi člana", + "label.email": "E-mail", "label.enable-share-url": "Omogući dijeljenje poveznice", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", + "label.end-step": "Završni korak", + "label.entry": "Ulazni URL", + "label.event": "Događaj", "label.event-data": "Podaci događaja", - "label.event-name": "Event name", + "label.event-name": "Naziv događaja", "label.events": "Events", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", + "label.exists": "Postoji", + "label.exit": "Izlazni URL", + "label.expand": "Proširi", + "label.false": "Netočno", + "label.field": "Polje", + "label.fields": "Polja", "label.filter": "Filter", "label.filter-combined": "Combined", "label.filter-raw": "Raw", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.filters": "Filteri", + "label.first-click": "Prvi klik", + "label.first-seen": "Prvi put viđeno", + "label.funnel": "Lijevak", + "label.funnel-description": "Razumite stopu konverzije i odlaska korisnika.", + "label.funnels": "Ljevci", + "label.goal": "Cilj", + "label.goals": "Ciljevi", + "label.goals-description": "Pratite svoje ciljeve za prikaze stranica i događaje.", + "label.greater-than": "Veće od", + "label.greater-than-equals": "Veće ili jednako", + "label.grouped": "Grupirano", + "label.hostname": "Naziv hosta", + "label.includes": "Uključuje", + "label.insight": "Uvid", + "label.insights": "Uvidi", + "label.insights-description": "Dublje analizirajte svoje podatke pomoću segmenata i filtera.", + "label.is": "Je", + "label.is-false": "Je netočno", + "label.is-not": "Nije", + "label.is-not-set": "Nije postavljeno", + "label.is-set": "Postavljeno", + "label.is-true": "Je točno", + "label.join": "Pridruži se", + "label.join-team": "Pridruži se timu", + "label.journey": "Putovanje", + "label.journey-description": "Razumite kako korisnici navigiraju vašom web stranicom.", + "label.journeys": "Putovanja", "label.language": "Jezik", "label.languages": "Languages", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Zadnji klik", "label.last-days": "Zadnjih {x} dana", "label.last-hours": "Zadnjih {x} sati", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "Zadnjih {x} mjeseci", + "label.last-seen": "Zadnji put viđeno", + "label.leave": "Napusti", + "label.leave-team": "Napusti tim", + "label.less-than": "Manje od", + "label.less-than-equals": "Manje ili jednako", + "label.links": "Poveznice", "label.login": "Prijava", "label.logout": "Odjava", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.manage": "Upravljaj", + "label.manager": "Upravitelj", + "label.max": "Maksimum", + "label.medium": "Srednje", + "label.member": "Član", + "label.members": "Članovi", + "label.min": "Minimum", "label.mobile": "Mobile", "label.model": "Model", "label.more": "Više", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "Moj račun", + "label.my-websites": "Moje web stranice", "label.name": "Ime", "label.new-password": "Nova lozinka", - "label.none": "Ništa", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", + "label.none": "Nijedan", + "label.number-of-records": "{x} {x, plural, one {zapis} other {zapisa}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organsko pretraživanje", + "label.organic-shopping": "Organska kupovina", + "label.organic-social": "Organska društvena mreža", + "label.organic-video": "Organski videozapis", "label.os": "OS", - "label.other": "Other", - "label.overview": "Overview", + "label.other": "Ostalo", + "label.overview": "Pregled", "label.owner": "Vlasnik", - "label.page": "Page", - "label.page-of": "Page {current} of {total}", + "label.page": "Stranica", + "label.page-of": "Stranica {current} od {total}", "label.page-views": "Page views", "label.pageTitle": "Page title", "label.pages": "Pages", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Plaćeni oglasi", + "label.paid-search": "Plaćeno pretraživanje", + "label.paid-shopping": "Plaćena kupovina", + "label.paid-social": "Plaćena društvena mreža", + "label.paid-video": "Plaćeni videozapis", "label.password": "Lozinka", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Putanja", + "label.paths": "Putanje", + "label.pixels": "Pikseli", "label.powered-by": "Powered by {name}", "label.previous": "Previous", "label.previous-period": "Previous period", "label.previous-year": "Previous year", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.properties": "Svojstva", + "label.property": "Svojstvo", + "label.queries": "Upiti", + "label.query": "Upit", + "label.query-parameters": "Parametri upita", "label.realtime": "Stvarno vrijeme", - "label.referral": "Referral", + "label.referral": "Preporuka", "label.referrer": "Referrer", "label.referrers": "Referrers", "label.refresh": "Osvježi", "label.regenerate": "Regenerate", "label.region": "Region", "label.regions": "Regions", - "label.remaining": "Remaining", + "label.remaining": "Preostalo", "label.remove": "Remove", "label.remove-member": "Remove member", "label.reports": "Reports", @@ -209,44 +209,44 @@ "label.reset-website": "Resetirati web stranicu", "label.retention": "Retention", "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Prihod", + "label.revenue-description": "Pogledajte svoj prihod tijekom vremena.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Spremi", - "label.screens": "Screens", + "label.screens": "Ekrani", "label.search": "Search", "label.select": "Select", "label.select-date": "Select date", - "label.select-filter": "Select filter", + "label.select-filter": "Odaberi filter", "label.select-role": "Select role", "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Sesija", + "label.session-data": "Podaci sesije", "label.sessions": "Sessions", "label.settings": "Postavke", - "label.share": "Share", + "label.share": "Podijeli", "label.share-url": "Podijeli poveznicu", "label.single-day": "Jedan dan", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", + "label.sources": "Izvori", + "label.start-step": "Početni korak", + "label.steps": "Koraci", "label.sum": "Sum", "label.tablet": "Tablet", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Oznaka", + "label.tags": "Oznake", "label.team": "Team", "label.team-id": "Team ID", "label.team-manager": "Team manager", "label.team-member": "Team member", "label.team-name": "Team name", "label.team-owner": "Team owner", - "label.team-settings": "Team settings", + "label.team-settings": "Postavke tima", "label.team-view-only": "Team view only", "label.team-websites": "Team websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Pojmovi", "label.theme": "Tema", "label.this-month": "Ovaj mjesec", "label.this-week": "Ovaj tjedan", diff --git a/src/lang/hu-HU.json b/src/lang/hu-HU.json index f6039281..58715069 100644 --- a/src/lang/hu-HU.json +++ b/src/lang/hu-HU.json @@ -1,206 +1,206 @@ { - "label.access-code": "Access code", + "label.access-code": "Hozzáférési kód", "label.actions": "Műveletek", - "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.activity": "Tevékenységnapló", + "label.add": "Hozzáadás", + "label.add-board": "Tábla hozzáadása", + "label.add-description": "Leírás hozzáadása", + "label.add-member": "Tag hozzáadása", + "label.add-step": "Lépés hozzáadása", "label.add-website": "Weboldal hozzáadása", "label.admin": "Adminisztrátor", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "Partner", + "label.after": "Után", "label.all": "Összes", - "label.all-time": "All time", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.all-time": "Minden időszak", + "label.analytics": "Analitika", + "label.apply": "Alkalmaz", + "label.attribution": "Attribúció", + "label.attribution-description": "Nézze meg, hogyan lépnek kapcsolatba a felhasználók a marketingjével, és mi vezet konverzióhoz.", + "label.average": "Átlag", "label.back": "Vissza", - "label.before": "Before", - "label.boards": "Boards", + "label.before": "Előtt", + "label.boards": "Táblák", "label.bounce-rate": "Visszafordulási arány", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.breakdown": "Bontás", + "label.browser": "Böngésző", "label.browsers": "Böngészők", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampányok", "label.cancel": "Mégsem", "label.change-password": "Jelszó módosítása", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "Csatornák", + "label.cities": "Városok", + "label.city": "Város", + "label.clear-all": "Összes törlése", + "label.cohort": "Kohorsz", + "label.compare": "Összehasonlít", + "label.compare-dates": "Dátumok összehasonlítása", + "label.confirm": "Megerősít", "label.confirm-password": "Jelszó megerősítése", "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.content": "Tartalom", + "label.continue": "Folytatás", + "label.conversion": "Konverzió", + "label.conversion-rate": "Konverziós arány", + "label.conversion-step": "Konverziós lépés", + "label.count": "Darabszám", "label.countries": "Országok", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "Ország", + "label.create": "Létrehozás", + "label.create-report": "Jelentés létrehozása", + "label.create-team": "Csapat létrehozása", + "label.create-user": "Felhasználó létrehozása", + "label.created": "Létrehozva", + "label.created-by": "Létrehozta", + "label.currency": "Pénznem", + "label.current": "Jelenlegi", "label.current-password": "Jelenlegi jelszó", "label.custom-range": "Egyedi tartomány", "label.dashboard": "Áttekintés", - "label.data": "Data", - "label.date": "Date", + "label.data": "Adat", + "label.date": "Dátum", "label.date-range": "Időintervallum", - "label.day": "Day", + "label.day": "Nap", "label.default-date-range": "Alapértelmezett időintervallum", "label.delete": "Eltávolítás", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "Jelentés törlése", + "label.delete-team": "Csapat törlése", + "label.delete-user": "Felhasználó törlése", "label.delete-website": "Weboldal eltávolítása", - "label.description": "Description", + "label.description": "Leírás", "label.desktop": "Asztali számítógép", - "label.details": "Details", - "label.device": "Device", + "label.details": "Részletek", + "label.device": "Eszköz", "label.devices": "Eszközök", - "label.direct": "Direct", + "label.direct": "Közvetlen", "label.dismiss": "Mellőzés", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "Egyedi azonosító", + "label.does-not-contain": "Nem tartalmazza", + "label.does-not-include": "Nem tartalmazza", + "label.doest-not-exist": "Nem létezik", "label.domain": "Domain", - "label.dropoff": "Dropoff", + "label.dropoff": "Lemorzsolódás", "label.edit": "Módosítás", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", - "label.email": "Email", + "label.edit-dashboard": "Irányítópult szerkesztése", + "label.edit-member": "Tag szerkesztése", + "label.email": "E-mail", "label.enable-share-url": "URL-megosztás engedélyezése", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "Befejező lépés", + "label.entry": "Belépési URL", + "label.event": "Esemény", + "label.event-data": "Eseményadatok", + "label.event-name": "Esemény neve", "label.events": "Események", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", + "label.exists": "Létezik", + "label.exit": "Kilépési URL", + "label.expand": "Kibontás", + "label.false": "Hamis", + "label.field": "Mező", + "label.fields": "Mezők", "label.filter": "Filter", "label.filter-combined": "Összevont", "label.filter-raw": "Nyers", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.filters": "Szűrők", + "label.first-click": "Első kattintás", + "label.first-seen": "Első megtekintés", + "label.funnel": "Tölcsér", + "label.funnel-description": "Értse meg a felhasználók konverziós és lemorzsolódási arányát.", + "label.funnels": "Tölcsérek", + "label.goal": "Cél", + "label.goals": "Célok", + "label.goals-description": "Kövesse nyomon a céljait oldalmegtekintések és események alapján.", + "label.greater-than": "Nagyobb mint", + "label.greater-than-equals": "Nagyobb vagy egyenlő", + "label.grouped": "Csoportosítva", + "label.hostname": "Hosztnév", + "label.includes": "Tartalmazza", + "label.insight": "Betekintés", + "label.insights": "Betekintések", + "label.insights-description": "Merüljön el mélyebben az adataiban szegmensek és szűrők használatával.", + "label.is": "Az", + "label.is-false": "Hamis", + "label.is-not": "Nem az", + "label.is-not-set": "Nincs beállítva", + "label.is-set": "Beállítva", + "label.is-true": "Igaz", + "label.join": "Csatlakozás", + "label.join-team": "Csatlakozás a csapathoz", + "label.journey": "Út", + "label.journey-description": "Értse meg, hogyan navigálnak a felhasználók a weboldalán.", + "label.journeys": "Utak", "label.language": "Language", "label.languages": "Languages", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Utolsó kattintás", "label.last-days": "Legutóbbi {x} nap", "label.last-hours": "Legutóbbi {x} óra", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "Utolsó {x} hónap", + "label.last-seen": "Utoljára látva", + "label.leave": "Kilépés", + "label.leave-team": "Csapat elhagyása", + "label.less-than": "Kevesebb mint", + "label.less-than-equals": "Kevesebb vagy egyenlő", + "label.links": "Linkek", "label.login": "Bejelentkezés", "label.logout": "Kijelentkezés", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.manage": "Kezelés", + "label.manager": "Menedzser", + "label.max": "Maximum", + "label.medium": "Közepes", + "label.member": "Tag", + "label.members": "Tagok", + "label.min": "Minimum", "label.mobile": "Telefon", "label.model": "Model", "label.more": "Bővebben", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "Saját fiók", + "label.my-websites": "Saját weboldalak", "label.name": "Név", "label.new-password": "Új jelszó", - "label.none": "None", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", + "label.none": "Nincs", + "label.number-of-records": "{x} {x, plural, one {rekord} other {rekord}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organikus keresés", + "label.organic-shopping": "Organikus vásárlás", + "label.organic-social": "Organikus közösségi", + "label.organic-video": "Organikus videó", "label.os": "OS", - "label.other": "Other", - "label.overview": "Overview", - "label.owner": "Owner", - "label.page": "Page", - "label.page-of": "Page {current} of {total}", + "label.other": "Egyéb", + "label.overview": "Áttekintés", + "label.owner": "Tulajdonos", + "label.page": "Oldal", + "label.page-of": "Oldal {current} / {total}", "label.page-views": "Oldalmegtekintések", "label.pageTitle": "Page title", "label.pages": "Oldalak", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Fizetett hirdetések", + "label.paid-search": "Fizetett keresés", + "label.paid-shopping": "Fizetett vásárlás", + "label.paid-social": "Fizetett közösségi", + "label.paid-video": "Fizetett videó", "label.password": "Jelszó", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Útvonal", + "label.paths": "Útvonalak", + "label.pixels": "Pixelek", "label.powered-by": "Működteti az {name}", "label.previous": "Previous", "label.previous-period": "Previous period", "label.previous-year": "Previous year", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.properties": "Tulajdonságok", + "label.property": "Tulajdonság", + "label.queries": "Lekérdezések", + "label.query": "Lekérdezés", + "label.query-parameters": "Lekérdezési paraméterek", "label.realtime": "Valós idejű", - "label.referral": "Referral", + "label.referral": "Hivatkozás", "label.referrer": "Referrer", "label.referrers": "Hivatkozók", "label.refresh": "Frissítés", "label.regenerate": "Regenerate", "label.region": "Region", "label.regions": "Regions", - "label.remaining": "Remaining", + "label.remaining": "Hátralévő", "label.remove": "Remove", "label.remove-member": "Remove member", "label.reports": "Reports", @@ -209,44 +209,44 @@ "label.reset-website": "Reset statistics", "label.retention": "Retention", "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Bevétel", + "label.revenue-description": "Tekintse meg bevételeit az idő múlásával.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Mentés", - "label.screens": "Screens", + "label.screens": "Képernyők", "label.search": "Search", "label.select": "Select", "label.select-date": "Select date", - "label.select-filter": "Select filter", + "label.select-filter": "Szűrő kiválasztása", "label.select-role": "Select role", "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Munkamenet", + "label.session-data": "Munkamenet adatai", "label.sessions": "Sessions", "label.settings": "Beállítások", - "label.share": "Share", + "label.share": "Megosztás", "label.share-url": "URL megosztása", "label.single-day": "Egy nap", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", + "label.sources": "Források", + "label.start-step": "Kezdő lépés", + "label.steps": "Lépések", "label.sum": "Sum", "label.tablet": "Táblagép", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Címke", + "label.tags": "Címkék", "label.team": "Team", "label.team-id": "Team ID", "label.team-manager": "Team manager", "label.team-member": "Team member", "label.team-name": "Team name", "label.team-owner": "Team owner", - "label.team-settings": "Team settings", + "label.team-settings": "Csapat beállításai", "label.team-view-only": "Team view only", "label.team-websites": "Team websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Kifejezések", "label.theme": "Theme", "label.this-month": "Ezen hónap", "label.this-week": "Ezen hét", diff --git a/src/lang/id-ID.json b/src/lang/id-ID.json index 69490f5c..63114bb8 100644 --- a/src/lang/id-ID.json +++ b/src/lang/id-ID.json @@ -3,46 +3,46 @@ "label.actions": "Aksi", "label.activity": "Catatan aktivitas", "label.add": "Tambah", - "label.add-board": "Add board", + "label.add-board": "Tambah papan", "label.add-description": "Tambah deskripsi", "label.add-member": "Tambah anggota", "label.add-step": "Tambah langkah", "label.add-website": "Tambah situs web", "label.admin": "Pengelola", - "label.affiliate": "Affiliate", + "label.affiliate": "Afiliasi", "label.after": "Setelah", "label.all": "Semua", "label.all-time": "Semua waktu", "label.analytics": "Analitik", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Terapkan", + "label.attribution": "Atribusi", + "label.attribution-description": "Lihat bagaimana pengguna berinteraksi dengan pemasaran Anda dan apa yang mendorong konversi.", "label.average": "Rata-rata", "label.back": "Kembali", "label.before": "Sebelum", - "label.boards": "Boards", + "label.boards": "Papan", "label.bounce-rate": "Rasio pentalan", "label.breakdown": "Rincian", "label.browser": "Peramban", "label.browsers": "Peramban", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampanye", "label.cancel": "Batal", "label.change-password": "Ganti kata sandi", - "label.channels": "Channels", + "label.channels": "Saluran", "label.cities": "Kota", "label.city": "Kota", "label.clear-all": "Hapus semua", - "label.cohort": "Cohort", + "label.cohort": "Kelompok", "label.compare": "Bandingkan", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Bandingkan tanggal", "label.confirm": "Konfirmasi", "label.confirm-password": "Konfirmasi kata sandi", "label.contains": "Mengandung", - "label.content": "Content", + "label.content": "Konten", "label.continue": "Lanjutkan", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Konversi", + "label.conversion-rate": "Tingkat konversi", + "label.conversion-step": "Langkah konversi", "label.count": "Jumlah", "label.countries": "Negara", "label.country": "Negara", @@ -52,7 +52,7 @@ "label.create-user": "Buat pengguna", "label.created": "Dibuat", "label.created-by": "Dibuat oleh", - "label.currency": "Currency", + "label.currency": "Mata uang", "label.current": "Saat ini", "label.current-password": "Kata sandi sekarang", "label.custom-range": "Rentang khusus", @@ -72,12 +72,12 @@ "label.details": "Detail", "label.device": "Perangkat", "label.devices": "Perangkat", - "label.direct": "Direct", + "label.direct": "Langsung", "label.dismiss": "Tutup", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "ID unik", "label.does-not-contain": "Tidak mengandung", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Tidak termasuk", + "label.doest-not-exist": "Tidak ada", "label.domain": "Domain", "label.dropoff": "Penurunan", "label.edit": "Sunting", @@ -89,11 +89,11 @@ "label.entry": "URL masuk", "label.event": "Peristiwa", "label.event-data": "Data peristiwa", - "label.event-name": "Event name", + "label.event-name": "Nama peristiwa", "label.events": "Peristiwa", - "label.exists": "Exists", + "label.exists": "Ada", "label.exit": "Exit URL", - "label.expand": "Expand", + "label.expand": "Perluas", "label.false": "Salah", "label.field": "Kolom", "label.fields": "Kolom", @@ -101,37 +101,37 @@ "label.filter-combined": "Gabungan", "label.filter-raw": "Mentah", "label.filters": "Filters", - "label.first-click": "First click", + "label.first-click": "Klik pertama", "label.first-seen": "Pertama kali dilihat", "label.funnel": "Funnel", "label.funnel-description": "Pahami tingkat konversi dan penurunan pengguna.", - "label.funnels": "Funnels", + "label.funnels": "Corong", "label.goal": "Tujuan", "label.goals": "Tujuan", "label.goals-description": "Lacak tujuan Anda untuk tampilan halaman dan peristiwa.", "label.greater-than": "Lebih dari", "label.greater-than-equals": "Lebih dari atau sama dengan", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Dikelompokkan", + "label.hostname": "Nama host", + "label.includes": "Termasuk", + "label.insight": "Wawasan", "label.insights": "Wawasan", "label.insights-description": "Jelajahi data Anda lebih dalam dengan menggunakan segmen dan filter.", "label.is": "Adalah", - "label.is-false": "Is false", + "label.is-false": "Salah", "label.is-not": "Bukan", "label.is-not-set": "Tidak diatur", "label.is-set": "Diatur", - "label.is-true": "Is true", + "label.is-true": "Benar", "label.join": "Gabung", "label.join-team": "Gabung tim", "label.journey": "Perjalanan", "label.journey-description": "Pahami bagaimana pengguna menavigasi situs web Anda.", - "label.journeys": "Journeys", + "label.journeys": "Perjalanan", "label.language": "Bahasa", "label.languages": "Bahasa", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Klik terakhir", "label.last-days": "{x} hari terakhir", "label.last-hours": "{x} jam terakhir", "label.last-months": "{x} bulan terakhir", @@ -140,16 +140,16 @@ "label.leave-team": "Keluar dari tim", "label.less-than": "Kurang dari", "label.less-than-equals": "Kurang dari atau sama dengan", - "label.links": "Links", + "label.links": "Tautan", "label.login": "Masuk", "label.logout": "Keluar", "label.manage": "Kelola", - "label.manager": "Pengelola", - "label.max": "Maks", - "label.medium": "Medium", + "label.manager": "Manajer", + "label.max": "Maksimum", + "label.medium": "Sedang", "label.member": "Anggota", "label.members": "Anggota", - "label.min": "Min", + "label.min": "Minimum", "label.mobile": "Ponsel", "label.model": "Model", "label.more": "Lebih banyak", @@ -158,49 +158,49 @@ "label.name": "Nama", "label.new-password": "Kata sandi baru", "label.none": "Tidak ada", - "label.number-of-records": "{x} {x, plural, one {record} other {records}}", + "label.number-of-records": "{x} {x, plural, one {catatan} other {catatan}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Pencarian organik", + "label.organic-shopping": "Belanja organik", + "label.organic-social": "Sosial organik", + "label.organic-video": "Video organik", "label.os": "OS", - "label.other": "Other", + "label.other": "Lainnya", "label.overview": "Tinjauan umum", "label.owner": "Pemilik", - "label.page": "Page", + "label.page": "Halaman", "label.page-of": "Halaman {current} dari {total}", "label.page-views": "Tampilan halaman", "label.pageTitle": "Judul halaman", "label.pages": "Halaman", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Iklan berbayar", + "label.paid-search": "Pencarian berbayar", + "label.paid-shopping": "Belanja berbayar", + "label.paid-social": "Sosial berbayar", + "label.paid-video": "Video berbayar", "label.password": "Kata sandi", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Jalur", + "label.paths": "Jalur", + "label.pixels": "Piksel", "label.powered-by": "Didukung oleh {name}", "label.previous": "Sebelumnya", "label.previous-period": "Periode sebelumnya", "label.previous-year": "Tahun lalu", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.properties": "Properti", + "label.property": "Properti", + "label.queries": "Kueri", + "label.query": "Kueri", + "label.query-parameters": "Parameter kueri", "label.realtime": "Waktu nyata", - "label.referral": "Referral", + "label.referral": "Rujukan", "label.referrer": "Perujuk", "label.referrers": "Perujuk", "label.refresh": "Segarkan", "label.regenerate": "Buat ulang", "label.region": "Wilayah", "label.regions": "Wilayah", - "label.remaining": "Remaining", + "label.remaining": "Tersisa", "label.remove": "Hapus", "label.remove-member": "Hapus anggota", "label.reports": "Laporan", @@ -218,35 +218,35 @@ "label.search": "Cari", "label.select": "Pilih", "label.select-date": "Pilih tanggal", - "label.select-filter": "Select filter", + "label.select-filter": "Pilih filter", "label.select-role": "Pilih role", "label.select-website": "Pilih situs web", "label.session": "Sesi", - "label.session-data": "Session data", + "label.session-data": "Data sesi", "label.sessions": "Sesi", "label.settings": "Pengaturan", - "label.share": "Share", + "label.share": "Bagikan", "label.share-url": "Bagikan URL", "label.single-day": "Sehari", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Sumber", "label.start-step": "Langkah awal", "label.steps": "Langkah", "label.sum": "Sum", "label.tablet": "Tablet", "label.tag": "Tag", - "label.tags": "Tags", + "label.tags": "Tag", "label.team": "Tim", "label.team-id": "ID tim", "label.team-manager": "Pengelola tim", "label.team-member": "Anggota tim", "label.team-name": "Nama tim", "label.team-owner": "Pemilik tim", - "label.team-settings": "Team settings", + "label.team-settings": "Pengaturan tim", "label.team-view-only": "Team view only", "label.team-websites": "Situs web tim", "label.teams": "Tim", - "label.terms": "Terms", + "label.terms": "Ketentuan", "label.theme": "Tema", "label.this-month": "Bulan ini", "label.this-week": "Minggu ini", diff --git a/src/lang/it-IT.json b/src/lang/it-IT.json index 3c697131..fc16f2ea 100644 --- a/src/lang/it-IT.json +++ b/src/lang/it-IT.json @@ -1,206 +1,206 @@ { - "label.access-code": "Access code", + "label.access-code": "Codice di accesso", "label.actions": "Azioni", - "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.activity": "Registro attività", + "label.add": "Aggiungi", + "label.add-board": "Aggiungi bacheca", + "label.add-description": "Aggiungi descrizione", + "label.add-member": "Aggiungi membro", + "label.add-step": "Aggiungi passaggio", "label.add-website": "Aggiungi sito", "label.admin": "Amministratore", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "Affiliato", + "label.after": "Dopo", "label.all": "Tutto", "label.all-time": "Sempre", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.analytics": "Analitica", + "label.apply": "Applica", + "label.attribution": "Attribuzione", + "label.attribution-description": "Scopri come gli utenti interagiscono con il tuo marketing e cosa genera conversioni.", + "label.average": "Media", "label.back": "Indietro", - "label.before": "Before", - "label.boards": "Boards", + "label.before": "Prima", + "label.boards": "Bacheche", "label.bounce-rate": "Frequenza di rimbalzo", - "label.breakdown": "Breakdown", + "label.breakdown": "Dettaglio", "label.browser": "Browser", "label.browsers": "Browser", - "label.campaigns": "Campaigns", + "label.campaigns": "Campagne", "label.cancel": "Annulla", "label.change-password": "Modifica password", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "Canali", + "label.cities": "Città", + "label.city": "Città", + "label.clear-all": "Cancella tutto", + "label.cohort": "Coorte", + "label.compare": "Confronta", + "label.compare-dates": "Confronta date", + "label.confirm": "Conferma", "label.confirm-password": "Conferma password", "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.content": "Contenuto", + "label.continue": "Continua", + "label.conversion": "Conversione", + "label.conversion-rate": "Tasso di conversione", + "label.conversion-step": "Passaggio di conversione", + "label.count": "Conteggio", "label.countries": "Nazioni", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "Paese", + "label.create": "Crea", + "label.create-report": "Crea rapporto", + "label.create-team": "Crea team", + "label.create-user": "Crea utente", + "label.created": "Creato", + "label.created-by": "Creato da", + "label.currency": "Valuta", + "label.current": "Attuale", "label.current-password": "Password attuale", "label.custom-range": "Personalizzato", "label.dashboard": "Pannello di Controllo", - "label.data": "Data", - "label.date": "Date", + "label.data": "Dati", + "label.date": "Data", "label.date-range": "Periodo", - "label.day": "Day", + "label.day": "Giorno", "label.default-date-range": "Periodo standard", "label.delete": "Elimina", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "Elimina rapporto", + "label.delete-team": "Elimina team", + "label.delete-user": "Elimina utente", "label.delete-website": "Elimina sito", - "label.description": "Description", + "label.description": "Descrizione", "label.desktop": "Desktop", - "label.details": "Details", - "label.device": "Device", + "label.details": "Dettagli", + "label.device": "Dispositivo", "label.devices": "Dispositivi", - "label.direct": "Direct", + "label.direct": "Diretto", "label.dismiss": "Scarta", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "ID distinto", + "label.does-not-contain": "Non contiene", + "label.does-not-include": "Non include", + "label.doest-not-exist": "Non esiste", "label.domain": "Dominio", - "label.dropoff": "Dropoff", + "label.dropoff": "Abbandono", "label.edit": "Modifica", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", + "label.edit-dashboard": "Modifica pannello di controllo", + "label.edit-member": "Modifica membro", "label.email": "Email", "label.enable-share-url": "Abilita URL di condivisione", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "Passaggio finale", + "label.entry": "URL di ingresso", + "label.event": "Evento", + "label.event-data": "Dati evento", + "label.event-name": "Nome evento", "label.events": "Eventi", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", + "label.exists": "Esiste", + "label.exit": "URL di uscita", + "label.expand": "Espandi", + "label.false": "Falso", + "label.field": "Campo", + "label.fields": "Campi", "label.filter": "Filter", "label.filter-combined": "Aggregati", "label.filter-raw": "Raw", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", + "label.filters": "Filtri", + "label.first-click": "Primo clic", + "label.first-seen": "Prima visualizzazione", "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", - "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.funnel-description": "Comprendi il tasso di conversione e di abbandono degli utenti.", + "label.funnels": "Funnel", + "label.goal": "Obiettivo", + "label.goals": "Obiettivi", + "label.goals-description": "Tieni traccia dei tuoi obiettivi per visualizzazioni di pagina ed eventi.", + "label.greater-than": "Maggiore di", + "label.greater-than-equals": "Maggiore o uguale a", + "label.grouped": "Raggruppato", + "label.hostname": "Nome host", + "label.includes": "Include", + "label.insight": "Approfondimento", + "label.insights": "Approfondimenti", + "label.insights-description": "Analizza più a fondo i tuoi dati utilizzando segmenti e filtri.", + "label.is": "È", + "label.is-false": "È falso", + "label.is-not": "Non è", + "label.is-not-set": "Non impostato", + "label.is-set": "Impostato", + "label.is-true": "È vero", + "label.join": "Unisciti", + "label.join-team": "Unisciti al team", + "label.journey": "Percorso", + "label.journey-description": "Comprendi come gli utenti navigano nel tuo sito web.", + "label.journeys": "Percorsi", "label.language": "Lingua", "label.languages": "Lingue", "label.laptop": "Portatile", - "label.last-click": "Last click", + "label.last-click": "Ultimo clic", "label.last-days": "Ultimi {x} giorni", "label.last-hours": "Ultime {x} ore", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "Ultimi {x} mesi", + "label.last-seen": "Ultima visualizzazione", + "label.leave": "Lascia", + "label.leave-team": "Lascia il team", + "label.less-than": "Meno di", + "label.less-than-equals": "Meno o uguale a", + "label.links": "Link", "label.login": "Accedi", "label.logout": "Esci", - "label.manage": "Manage", + "label.manage": "Gestisci", "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.max": "Massimo", + "label.medium": "Medio", + "label.member": "Membro", + "label.members": "Membri", + "label.min": "Minimo", "label.mobile": "Cellulare", "label.model": "Model", "label.more": "Dettagli", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "Il mio account", + "label.my-websites": "I miei siti", "label.name": "Nome", "label.new-password": "Nuova password", - "label.none": "None", + "label.none": "Nessuno", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Ricerca organica", + "label.organic-shopping": "Acquisto organico", + "label.organic-social": "Social organico", + "label.organic-video": "Video organico", "label.os": "OS", - "label.other": "Other", + "label.other": "Altro", "label.overview": "Overview", "label.owner": "Proprietario", - "label.page": "Page", + "label.page": "Pagina", "label.page-of": "Page {current} of {total}", "label.page-views": "Visualizzazioni di pagina", "label.pageTitle": "Page title", "label.pages": "Pagine", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Annunci a pagamento", + "label.paid-search": "Ricerca a pagamento", + "label.paid-shopping": "Acquisto a pagamento", + "label.paid-social": "Social a pagamento", + "label.paid-video": "Video a pagamento", "label.password": "Password", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Percorso", + "label.paths": "Percorsi", + "label.pixels": "Pixel", "label.powered-by": "Powered by {name}", "label.previous": "Previous", "label.previous-period": "Previous period", "label.previous-year": "Previous year", "label.profile": "Profilo", - "label.properties": "Properties", - "label.property": "Property", - "label.queries": "Queries", + "label.properties": "Proprietà", + "label.property": "Proprietà", + "label.queries": "Query", "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.query-parameters": "Parametri query", "label.realtime": "Tempo reale", - "label.referral": "Referral", + "label.referral": "Referente", "label.referrer": "Referrer", "label.referrers": "Referrers", "label.refresh": "Ricarica", "label.regenerate": "Regenerate", "label.region": "Region", "label.regions": "Regions", - "label.remaining": "Remaining", + "label.remaining": "Rimanente", "label.remove": "Remove", "label.remove-member": "Remove member", "label.reports": "Reports", @@ -209,44 +209,44 @@ "label.reset-website": "Resetta le statistiche", "label.retention": "Retention", "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Ricavi", + "label.revenue-description": "Consulta i tuoi ricavi nel tempo.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Salva", - "label.screens": "Screens", + "label.screens": "Schermi", "label.search": "Search", "label.select": "Select", "label.select-date": "Select date", - "label.select-filter": "Select filter", + "label.select-filter": "Seleziona filtro", "label.select-role": "Select role", "label.select-website": "Select website", "label.session": "Session", - "label.session-data": "Session data", + "label.session-data": "Dati sessione", "label.sessions": "Sessions", "label.settings": "Impostazioni", - "label.share": "Share", + "label.share": "Condividi", "label.share-url": "Condividi link", "label.single-day": "Singolo giorno", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Fonti", "label.start-step": "Start Step", "label.steps": "Steps", "label.sum": "Sum", "label.tablet": "Tablet", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Etichetta", + "label.tags": "Etichette", "label.team": "Team", "label.team-id": "Team ID", "label.team-manager": "Team manager", "label.team-member": "Team member", "label.team-name": "Team name", "label.team-owner": "Team owner", - "label.team-settings": "Team settings", + "label.team-settings": "Impostazioni team", "label.team-view-only": "Team view only", "label.team-websites": "Team websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Termini", "label.theme": "Tema", "label.this-month": "Questo mese", "label.this-week": "Questa settimana", diff --git a/src/lang/ja-JP.json b/src/lang/ja-JP.json index f2f5fbee..5e51efc4 100644 --- a/src/lang/ja-JP.json +++ b/src/lang/ja-JP.json @@ -3,46 +3,46 @@ "label.actions": "アクション", "label.activity": "アクティビティログ", "label.add": "追加", - "label.add-board": "Add board", + "label.add-board": "ボードを追加", "label.add-description": "説明を追加", "label.add-member": "メンバーの追加", "label.add-step": "ステップを追加", "label.add-website": "Webサイトの追加", "label.admin": "管理者", - "label.affiliate": "Affiliate", + "label.affiliate": "アフィリエイト", "label.after": "直後", "label.all": "すべて", "label.all-time": "すべての時間帯", "label.analytics": "アナリティクス", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "適用", + "label.attribution": "アトリビューション", + "label.attribution-description": "ユーザーがあなたのマーケティングにどのように関与し、何がコンバージョンを促進するかを確認します。", "label.average": "平均", "label.back": "戻る", "label.before": "直前", - "label.boards": "Boards", + "label.boards": "ボード", "label.bounce-rate": "直帰率", "label.breakdown": "故障", "label.browser": "ブラウザ", "label.browsers": "ブラウザ", - "label.campaigns": "Campaigns", + "label.campaigns": "キャンペーン", "label.cancel": "キャンセル", "label.change-password": "パスワードの変更", - "label.channels": "Channels", + "label.channels": "チャンネル", "label.cities": "都市", "label.city": "都市", "label.clear-all": "すべてクリア", - "label.cohort": "Cohort", + "label.cohort": "コホート", "label.compare": "比較", - "label.compare-dates": "Compare dates", + "label.compare-dates": "日付を比較", "label.confirm": "確認", "label.confirm-password": "パスワード(確認)", "label.contains": "コンテンツ", - "label.content": "Content", + "label.content": "コンテンツ", "label.continue": "続ける", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "コンバージョン", + "label.conversion-rate": "コンバージョン率", + "label.conversion-step": "コンバージョンステップ", "label.count": "回数", "label.countries": "国名", "label.country": "国", @@ -52,7 +52,7 @@ "label.create-user": "ユーザーの作成", "label.created": "作成されました", "label.created-by": "作成者", - "label.currency": "Currency", + "label.currency": "通貨", "label.current": "現在", "label.current-password": "現在のパスワード", "label.custom-range": "範囲指定", @@ -72,28 +72,28 @@ "label.details": "詳細情報", "label.device": "デバイス", "label.devices": "デバイス", - "label.direct": "Direct", + "label.direct": "ダイレクト", "label.dismiss": "却下", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "識別ID", "label.does-not-contain": "を含まない", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "含まない", + "label.doest-not-exist": "存在しない", "label.domain": "ドメイン", "label.dropoff": "切り捨て", "label.edit": "編集", "label.edit-dashboard": "ダッシュボードの編集", "label.edit-member": "メンバーの編集", - "label.email": "Email", + "label.email": "メール", "label.enable-share-url": "共有URLを有効にする", "label.end-step": "最終ステップ", "label.entry": "訪問時のURL", "label.event": "イベント", "label.event-data": "イベントデータ", - "label.event-name": "Event name", + "label.event-name": "イベント名", "label.events": "イベント", - "label.exists": "Exists", + "label.exists": "存在する", "label.exit": "退出時のURL", - "label.expand": "Expand", + "label.expand": "展開", "label.false": "偽", "label.field": "フィールド", "label.fields": "フィールド", @@ -101,37 +101,37 @@ "label.filter-combined": "結合", "label.filter-raw": "RAW", "label.filters": "フィルター", - "label.first-click": "First click", + "label.first-click": "最初のクリック", "label.first-seen": "初回ログイン", "label.funnel": "ファネル", "label.funnel-description": "ユーザーのコンバージョン率と離脱率を分析します。", - "label.funnels": "Funnels", + "label.funnels": "ファネル", "label.goal": "目標", "label.goals": "目標", "label.goals-description": "ページビューとイベントの目標を追跡します。", "label.greater-than": "超過", "label.greater-than-equals": "以上", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "グループ化", + "label.hostname": "ホスト名", + "label.includes": "含む", + "label.insight": "インサイト", "label.insights": "インサイト", "label.insights-description": "セグメントとフィルタを使用して、データをさらに詳しく分析します。", "label.is": "に等しい", - "label.is-false": "Is false", + "label.is-false": "偽である", "label.is-not": "に等しくない", "label.is-not-set": "未設定", "label.is-set": "設定済み", - "label.is-true": "Is true", + "label.is-true": "真である", "label.join": "参加", "label.join-team": "チームに参加", "label.journey": "ジャーニー", "label.journey-description": "ユーザーがWebサイト内をどのように移動するかを把握します。", - "label.journeys": "Journeys", + "label.journeys": "ジャーニー", "label.language": "言語", "label.languages": "言語", "label.laptop": "ノートPC", - "label.last-click": "Last click", + "label.last-click": "最後のクリック", "label.last-days": "過去{x}日間", "label.last-hours": "過去{x}時間", "label.last-months": "過去{x}月間", @@ -140,18 +140,18 @@ "label.leave-team": "チームを離脱", "label.less-than": "未満", "label.less-than-equals": "以下", - "label.links": "Links", + "label.links": "リンク", "label.login": "ログイン", "label.logout": "ログアウト", "label.manage": "管理", "label.manager": "管理者", "label.max": "最大", - "label.medium": "Medium", + "label.medium": "メディア", "label.member": "メンバー", "label.members": "メンバー", "label.min": "最小", "label.mobile": "携帯電話", - "label.model": "Model", + "label.model": "モデル", "label.more": "もっと見る", "label.my-account": "マイアカウント", "label.my-websites": "マイWebサイト", @@ -160,28 +160,28 @@ "label.none": "なし", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "オーガニック検索", + "label.organic-shopping": "オーガニックショッピング", + "label.organic-social": "オーガニックソーシャル", + "label.organic-video": "オーガニックビデオ", "label.os": "OS", - "label.other": "Other", + "label.other": "その他", "label.overview": "概要", "label.owner": "所有者", - "label.page": "Page", + "label.page": "ページ", "label.page-of": "ページ {current}/{total}", "label.page-views": "閲覧数", "label.pageTitle": "ページタイトル", "label.pages": "ページ", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "有料広告", + "label.paid-search": "有料検索", + "label.paid-shopping": "有料ショッピング", + "label.paid-social": "有料ソーシャル", + "label.paid-video": "有料ビデオ", "label.password": "パスワード", "label.path": "パス", "label.paths": "パス", - "label.pixels": "Pixels", + "label.pixels": "ピクセル", "label.powered-by": "Powered by {name}", "label.previous": "以前", "label.previous-period": "前期", @@ -200,7 +200,7 @@ "label.regenerate": "再生成", "label.region": "地域", "label.regions": "地域", - "label.remaining": "Remaining", + "label.remaining": "残り", "label.remove": "削除", "label.remove-member": "メンバーの削除", "label.reports": "レポート", @@ -218,35 +218,35 @@ "label.search": "検索", "label.select": "選択", "label.select-date": "日付を選択", - "label.select-filter": "Select filter", + "label.select-filter": "フィルターを選択", "label.select-role": "ロールを選択", "label.select-website": "Webサイトを選択", "label.session": "セッション", - "label.session-data": "Session data", + "label.session-data": "セッションデータ", "label.sessions": "セッション", "label.settings": "設定", - "label.share": "Share", + "label.share": "共有", "label.share-url": "共有URL", "label.single-day": "一日", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "ソース", "label.start-step": "最初のステップ", "label.steps": "ステップ", "label.sum": "合計", "label.tablet": "タブレット", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "タグ", + "label.tags": "タグ", "label.team": "チーム", "label.team-id": "チームID", "label.team-manager": "チーム管理者", "label.team-member": "チームメンバー", "label.team-name": "チーム名", "label.team-owner": "チームオーナー", - "label.team-settings": "Team settings", + "label.team-settings": "チーム設定", "label.team-view-only": "チーム表示のみ", "label.team-websites": "チームのWebサイト", "label.teams": "チーム", - "label.terms": "Terms", + "label.terms": "利用規約", "label.theme": "テーマ", "label.this-month": "今月", "label.this-week": "今週", diff --git a/src/lang/km-KH.json b/src/lang/km-KH.json index b12b60f1..79f3d14b 100644 --- a/src/lang/km-KH.json +++ b/src/lang/km-KH.json @@ -1,48 +1,48 @@ { - "label.access-code": "Access code", + "label.access-code": "កូដចូលប្រើ", "label.actions": "សកម្មភាព", "label.activity": "កំណត់ហេតុ​សកម្មភាព", "label.add": "បង្កើតបន្ថែម", - "label.add-board": "Add board", + "label.add-board": "បន្ថែមក្តារ", "label.add-description": "បន្ថែមពិពណ៌នា", "label.add-member": "បន្ថែមសមាជិក", "label.add-step": "បន្ថែមជំហាន", "label.add-website": "បន្ថែមគេហទំព័រ", "label.admin": "អ្នកគ្រប់គ្រង", - "label.affiliate": "Affiliate", + "label.affiliate": "ដៃគូ", "label.after": "បន្ទាប់", "label.all": "ទាំងអស់", "label.all-time": "គ្រប់ពេល", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.analytics": "វិភាគ", + "label.apply": "អនុវត្ត", + "label.attribution": "ការបញ្ជាក់", + "label.attribution-description": "មើលថាប្រើប្រាស់របស់អ្នកធ្វើអ្វីជាមួយទីផ្សាររបស់អ្នក និងអ្វីជាហេតុបណ្តាលឲ្យមានការបម្លែង។", "label.average": "ជាមធ្យម", "label.back": "ថយក្រោយ", "label.before": "មុន", - "label.boards": "Boards", + "label.boards": "ក្តារ", "label.bounce-rate": "ចំនួនវិលត្រឡប់", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.breakdown": "បំបែកលម្អិត", + "label.browser": "កម្មវិធីរុករក", "label.browsers": "កម្មវិធី", - "label.campaigns": "Campaigns", + "label.campaigns": "យុទ្ធនាការ", "label.cancel": "បោះបង់", "label.change-password": "ផ្លាស់ប្តូរពាក្យសម្ងាត់", - "label.channels": "Channels", + "label.channels": "ឆានែល", "label.cities": "ទីក្រុង", "label.city": "ទីក្រុង", - "label.clear-all": "លុបទាំងអស់", - "label.cohort": "Cohort", + "label.clear-all": "លុបចេញទាំងអស់", + "label.cohort": "ក្រុម", "label.compare": "ប្រៀបធៀប", - "label.compare-dates": "Compare dates", + "label.compare-dates": "ប្រៀបធៀបទិន្នន័យថ្ងៃខែ", "label.confirm": "បញ្ជាក់", "label.confirm-password": "បញ្ជាក់ពាក្យសម្ងាត់", "label.contains": "មាន", - "label.content": "Content", + "label.content": "មាតិកា", "label.continue": "បន្ត", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "ការបម្លែង", + "label.conversion-rate": "អត្រាបម្លែង", + "label.conversion-step": "ជំហានបម្លែង", "label.count": "ចំនួន", "label.countries": "ប្រទេស", "label.country": "ប្រទេស", @@ -52,7 +52,7 @@ "label.create-user": "បង្កើតអ្នកប្រើប្រាស់", "label.created": "បង្កើតនៅ", "label.created-by": "បង្កើតដោយ", - "label.currency": "Currency", + "label.currency": "រូបិយប័ណ្ណ", "label.current": "បច្ចុប្បន្ន", "label.current-password": "ពាក្យសម្ងាត់បច្ចុប្បន្ន", "label.custom-range": "កំណត់ដោយខ្លួនឯង", @@ -72,12 +72,12 @@ "label.details": "ព័ត៌មានលម្អិត", "label.device": "ឧបករណ៍", "label.devices": "ឧបករណ៍", - "label.direct": "Direct", + "label.direct": "ផ្ទាល់", "label.dismiss": "រំសាយ", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "លេខសម្គាល់ពិសេស", "label.does-not-contain": "មិនមាន", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "មិនរួមបញ្ចូល", + "label.doest-not-exist": "មិនមានទេ", "label.domain": "Domain", "label.dropoff": "Dropoff", "label.edit": "កែប្រែ", @@ -89,11 +89,11 @@ "label.entry": "URL ចូល", "label.event": "ព្រឹត្តិការណ៍", "label.event-data": "ទិន្នន័យព្រឹត្តិការណ៍", - "label.event-name": "Event name", + "label.event-name": "ឈ្មោះព្រឹត្តិការណ៍", "label.events": "ព្រឹត្តិការណ៍", - "label.exists": "Exists", + "label.exists": "មាន", "label.exit": "URL ចេញ", - "label.expand": "Expand", + "label.expand": "ពង្រីក", "label.false": "មិនពិត", "label.field": "Field", "label.fields": "Fields", @@ -101,37 +101,37 @@ "label.filter-combined": "រួមបញ្ចូលគ្នា", "label.filter-raw": "ដើម", "label.filters": "ចម្រោះ", - "label.first-click": "First click", + "label.first-click": "ចុចដំបូង", "label.first-seen": "First seen", - "label.funnel": "Funnel", + "label.funnel": "ផ្លូវបង្ហាញ", "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", + "label.funnels": "ផ្លូវបង្ហាញ", "label.goal": "គោលដៅ", "label.goals": "គោលដៅ", "label.goals-description": "តាមដានគោលដៅរបស់អ្នកសម្រាប់ pageviews និង events។", "label.greater-than": "ធំជាង", "label.greater-than-equals": "ធំជាងឬស្មើ", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "បានដាក់ជាក្រុម", + "label.hostname": "ឈ្មោះម៉ាស៊ីន", + "label.includes": "រួមបញ្ចូល", + "label.insight": "ការយល់ដឹង", "label.insights": "Insights", "label.insights-description": "Dive deeper into your data by using segments and filters.", "label.is": "គឺ", - "label.is-false": "Is false", + "label.is-false": "មិនពិត", "label.is-not": "មិនមែន", "label.is-not-set": "មិនបានកំណត់", "label.is-set": "បានកំណត់", - "label.is-true": "Is true", + "label.is-true": "ពិត", "label.join": "ចូលរួម", "label.join-team": "ចូលក្រុម", "label.journey": "​ដំណើរ", "label.journey-description": "ស្វែងយល់ពីការប្រើប្រាស់គេហទំព័ររបស់អតិថិជនអ្នក។", - "label.journeys": "Journeys", + "label.journeys": "ដំណើរ", "label.language": "ភាសា", "label.languages": "ភាសា", "label.laptop": "កុំព្យូទ័រយួរដៃ", - "label.last-click": "Last click", + "label.last-click": "ចុចចុងក្រោយ", "label.last-days": "{x} ថ្ងៃចុងក្រោយ", "label.last-hours": "{x} ម៉ោងចុងក្រោយ", "label.last-months": "{x} ខែចុងក្រោយ", @@ -140,73 +140,74 @@ "label.leave-team": "ចេញពីក្រុម", "label.less-than": "តិច​ជាង", "label.less-than-equals": "តិចជាង ឬស្មើ", - "label.links": "Links", + "label.links": "តំណភ្ជាប់", "label.login": "Login", "label.logout": "Logout", "label.manage": "គ្រប់គ្រង", "label.manager": "អ្នកគ្រប់គ្រង", "label.max": "Max", - "label.medium": "Medium", + "label.medium": "មធ្យម", "label.member": "សមាជិក", "label.members": "សមាជិក", "label.min": "Min", "label.mobile": "ទូរស័ព្ទចល័ត", - "label.model": "Model", + "label.model": "ម៉ូដែល", "label.more": "បន្ថែម", "label.my-account": "គណនី​របស់ខ្ញុំ", "label.my-websites": "គេហទំព័ររបស់ខ្ញុំ", "label.name": "ឈ្មោះ", "label.new-password": "ពាក្យសម្ងាត់​ថ្មី", - "label.none": "មិនមាន", + "label.none": "គ្មាន", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "ស្វែងរកធម្មជាតិ", + "label.organic-shopping": "ការទិញធម្មជាតិ", + "label.organic-social": "សង្គមធម្មជាតិ", + "label.organic-video": "វីដេអូធម្មជាតិ", "label.os": "OS", - "label.other": "Other", + "label.other": "ផ្សេងទៀត", "label.overview": "ទិដ្ឋភាពរួម", "label.owner": "ម្ចាស់", - "label.page": "Page", + "label.page": "ទំព័រ", "label.page-of": "ទំព័រទី {current} នៃ {total}", "label.page-views": "អ្នកមើលទំព័រ", "label.pageTitle": "ចំណងជើងទំព័រ", "label.pages": "ទំព័រ", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "ផ្សាយពាណិជ្ជកម្មបង់ប្រាក់", + "label.paid-search": "ស្វែងរកបង់ប្រាក់", + "label.paid-shopping": "ទិញបង់ប្រាក់", + "label.paid-social": "សង្គមបង់ប្រាក់", + "label.paid-video": "វីដេអូបង់ប្រាក់", "label.password": "ពាក្យសម្ងាត់​", "label.path": "Path", "label.paths": "Paths", - "label.pixels": "Pixels", + "label.pixels": "ភីកសែល", "label.powered-by": "ដំណើរការដោយ {name}", "label.previous": "មុន", "label.previous-period": "មួយរយៈពេលមុន", "label.previous-year": "ឆ្នាំ​មុន", "label.profile": "គណនី", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "លក្ខណៈពិសេស", + "label.property": "លក្ខណៈពិសេស", "label.queries": "Queries", "label.query": "Query", "label.query-parameters": "ប៉ារ៉ាម៉ែត្រ Query", "label.realtime": "ឥលូវនេះ", - "label.referral": "Referral", + "label.referral": "ការបញ្ជូន", "label.referrer": "អ្នកណែនាំ", "label.referrers": "អ្នកណែនាំ", "label.refresh": "ផ្ទុកឡើងវិញ", "label.regenerate": "Regenerate", "label.region": "តំបន់", "label.regions": "តំបន់", - "label.remaining": "Remaining", + "label.remaining": "នៅសល់", "label.remove": "លុប", "label.remove-member": "លុបសមាជិកក្រុម", "label.reports": "របាយការណ៍", "label.required": "ទាមទារ", "label.reset": "កែសម្រួល", - "label.reset-website": "កំណត់ស្ថិតិឡើងវិញ", + "label.reset-website": "ដើម្បីកែគេហទំព័រនេះឡើងវិញ សូមសរសេរ {confirmation} នៅក្នុងប្រអប់ខាងក្រោមដើម្បីបញ្ជាក់។", + "label.reset-website-warning": "ស្ថិតិទាំងអស់សម្រាប់គេហទំព័រនេះនឹងត្រូវបានលុប ប៉ុន្តែកូដតាមដានរបស់អ្នកនឹងនៅដដែល។", "label.retention": "ការរក្សាទុក", "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.revenue": "Revenue", @@ -218,35 +219,35 @@ "label.search": "ស្វែងរក", "label.select": "ជ្រើសរើស", "label.select-date": "ជ្រើសរើសកាលបរិច្ឆេទ", - "label.select-filter": "Select filter", + "label.select-filter": "ជ្រើសរើសតម្រង", "label.select-role": "ជ្រើសរើសមុខងារ", "label.select-website": "ជ្រើសរើសគេហទំព័រ", "label.session": "Session", - "label.session-data": "Session data", + "label.session-data": "ទិន្នន័យសម័យ", "label.sessions": "Sessions", "label.settings": "ការកំណត់", - "label.share": "Share", + "label.share": "ចែករំលែក", "label.share-url": "ចែករំលែក URL", "label.single-day": "ថ្ងៃតែមួយ", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "ប្រភព", "label.start-step": "ជំហានចាប់ផ្តើម", "label.steps": "ជំហាន", "label.sum": "Sum", "label.tablet": "ថេប្លេត", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "ស្លាក", + "label.tags": "ស្លាក", "label.team": "ក្រុម", "label.team-id": "ID ក្រុម", "label.team-manager": "អ្នកគ្រប់គ្រងក្រុម", "label.team-member": "សមាជិកក្រុម", "label.team-name": "ឈ្មោះក្រុម", "label.team-owner": "ម្ចាស់ក្រុម", - "label.team-settings": "Team settings", + "label.team-settings": "ការកំណត់ក្រុម", "label.team-view-only": "Team view only", "label.team-websites": "គេហទំព័ររបស់ក្រុម", "label.teams": "ក្រុម", - "label.terms": "Terms", + "label.terms": "លក្ខខណ្ឌ", "label.theme": "រូបរាង", "label.this-month": "ខែនេះ", "label.this-week": "ស​ប្តា​ហ៍​នេះ", diff --git a/src/lang/ko-KR.json b/src/lang/ko-KR.json index 2a33266d..4962ebf4 100644 --- a/src/lang/ko-KR.json +++ b/src/lang/ko-KR.json @@ -3,46 +3,46 @@ "label.actions": "동작", "label.activity": "활동", "label.add": "추가", - "label.add-board": "Add board", + "label.add-board": "보드 추가", "label.add-description": "설명 추가", "label.add-member": "멤버 추가", "label.add-step": "단계 추가", "label.add-website": "웹사이트 추가", "label.admin": "관리자", - "label.affiliate": "Affiliate", + "label.affiliate": "제휴사", "label.after": "이후", "label.all": "전체", "label.all-time": "전체 시간", "label.analytics": "분석", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "적용", + "label.attribution": "기여도", + "label.attribution-description": "사용자가 마케팅에 어떻게 반응하고 전환을 유도하는지 확인하세요.", "label.average": "평균", "label.back": "뒤로", "label.before": "이전", - "label.boards": "Boards", + "label.boards": "보드", "label.bounce-rate": "이탈률", "label.breakdown": "세부 사항", "label.browser": "브라우저", "label.browsers": "브라우저", - "label.campaigns": "Campaigns", + "label.campaigns": "캠페인", "label.cancel": "취소", "label.change-password": "비밀번호 변경", - "label.channels": "Channels", + "label.channels": "채널", "label.cities": "도시", "label.city": "도시", "label.clear-all": "모두 지우기", - "label.cohort": "Cohort", + "label.cohort": "코호트", "label.compare": "비교", - "label.compare-dates": "Compare dates", + "label.compare-dates": "날짜 비교", "label.confirm": "확인", "label.confirm-password": "비밀번호 확인", "label.contains": "포함", - "label.content": "Content", + "label.content": "콘텐츠", "label.continue": "계속", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "전환", + "label.conversion-rate": "전환율", + "label.conversion-step": "전환 단계", "label.count": "수", "label.countries": "국가", "label.country": "국가", @@ -52,7 +52,7 @@ "label.create-user": "사용자 만들기", "label.created": "생성됨", "label.created-by": "작성자", - "label.currency": "Currency", + "label.currency": "통화", "label.current": "현재", "label.current-password": "현재 비밀번호", "label.custom-range": "범위 지정", @@ -72,28 +72,28 @@ "label.details": "세부 정보", "label.device": "기기", "label.devices": "기기", - "label.direct": "Direct", + "label.direct": "직접", "label.dismiss": "무시하기", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "고유 ID", "label.does-not-contain": "포함하지 않음", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "포함하지 않음", + "label.doest-not-exist": "존재하지 않음", "label.domain": "도메인", "label.dropoff": "이탈", "label.edit": "편집", "label.edit-dashboard": "대시보드 편집", "label.edit-member": "멤버 편집", - "label.email": "Email", + "label.email": "이메일", "label.enable-share-url": "URL 공유 활성화", "label.end-step": "마지막 단계", "label.entry": "입장 URL", "label.event": "이벤트", "label.event-data": "이벤트 데이터", - "label.event-name": "Event name", + "label.event-name": "이벤트 이름", "label.events": "이벤트", - "label.exists": "Exists", + "label.exists": "존재함", "label.exit": "퇴장 URL", - "label.expand": "Expand", + "label.expand": "확장", "label.false": "거짓", "label.field": "필드", "label.fields": "필드", @@ -101,37 +101,37 @@ "label.filter-combined": "합쳐 보기", "label.filter-raw": "전체 보기", "label.filters": "필터", - "label.first-click": "First click", + "label.first-click": "첫 클릭", "label.first-seen": "첫 접속", "label.funnel": "퍼널", "label.funnel-description": "사용자 전환율 및 이탈률을 살펴보세요.", - "label.funnels": "Funnels", + "label.funnels": "퍼널", "label.goal": "목표", "label.goals": "목표", "label.goals-description": "페이지 조회 및 이벤트 목표를 추적합니다.", "label.greater-than": "이상", "label.greater-than-equals": "이상", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "그룹화됨", + "label.hostname": "호스트명", + "label.includes": "포함", + "label.insight": "인사이트", "label.insights": "인사이트", "label.insights-description": "세그먼트 및 필터를 사용하여 데이터를 더 자세히 살펴보세요.", "label.is": "해당", - "label.is-false": "Is false", + "label.is-false": "거짓임", "label.is-not": "해당하지 않음", "label.is-not-set": "설정되지 않음", "label.is-set": "설정됨", - "label.is-true": "Is true", + "label.is-true": "참임", "label.join": "가입하기", "label.join-team": "팀 가입하기", "label.journey": "여정", "label.journey-description": "사용자가 웹사이트를 탐색하는 경로를 살펴보세요.", - "label.journeys": "Journeys", + "label.journeys": "여정", "label.language": "언어", "label.languages": "언어", "label.laptop": "노트북", - "label.last-click": "Last click", + "label.last-click": "마지막 클릭", "label.last-days": "지난 {x}일", "label.last-hours": "지난 {x}시간", "label.last-months": "지난 {x}개월", @@ -140,18 +140,18 @@ "label.leave-team": "팀 떠나기", "label.less-than": "미만", "label.less-than-equals": "이하", - "label.links": "Links", + "label.links": "링크", "label.login": "로그인", "label.logout": "로그아웃", "label.manage": "관리", "label.manager": "관리자", "label.max": "최대", - "label.medium": "Medium", + "label.medium": "미디엄", "label.member": "멤버", "label.members": "멤버", "label.min": "최소", "label.mobile": "모바일", - "label.model": "Model", + "label.model": "모델", "label.more": "더 보기", "label.my-account": "내 계정", "label.my-websites": "내 웹사이트", @@ -160,28 +160,28 @@ "label.none": "없음", "label.number-of-records": "{x}개 레코드", "label.ok": "확인", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "자연 검색", + "label.organic-shopping": "자연 쇼핑", + "label.organic-social": "자연 소셜", + "label.organic-video": "자연 비디오", "label.os": "운영 체제", - "label.other": "Other", + "label.other": "기타", "label.overview": "개요", "label.owner": "소유자", - "label.page": "Page", + "label.page": "페이지", "label.page-of": "페이지 {current}/{total}", "label.page-views": "페이지 조회", "label.pageTitle": "페이지 제목", "label.pages": "페이지", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "유료 광고", + "label.paid-search": "유료 검색", + "label.paid-shopping": "유료 쇼핑", + "label.paid-social": "유료 소셜", + "label.paid-video": "유료 비디오", "label.password": "비밀번호", "label.path": "패스", "label.paths": "패스", - "label.pixels": "Pixels", + "label.pixels": "픽셀", "label.powered-by": "Powered by {name}", "label.previous": "이전", "label.previous-period": "이전 기간", @@ -200,7 +200,7 @@ "label.regenerate": "다시 생성", "label.region": "지역", "label.regions": "지역", - "label.remaining": "Remaining", + "label.remaining": "남음", "label.remove": "제거", "label.remove-member": "멤버 제거", "label.reports": "보고서", @@ -218,35 +218,35 @@ "label.search": "검색", "label.select": "선택", "label.select-date": "날짜 선택", - "label.select-filter": "Select filter", + "label.select-filter": "필터 선택", "label.select-role": "역할 선택", "label.select-website": "웹사이트 선택", "label.session": "세션", - "label.session-data": "Session data", + "label.session-data": "세션 데이터", "label.sessions": "세션", "label.settings": "설정", - "label.share": "Share", + "label.share": "공유", "label.share-url": "공유 URL", "label.single-day": "하루", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "소스", "label.start-step": "시작 단계", "label.steps": "단계", "label.sum": "합계", "label.tablet": "태블릿", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "태그", + "label.tags": "태그", "label.team": "팀", "label.team-id": "팀 ID", "label.team-manager": "팀 관리자", "label.team-member": "팀 멤버", "label.team-name": "팀 이름", "label.team-owner": "팀 소유자", - "label.team-settings": "Team settings", + "label.team-settings": "팀 설정", "label.team-view-only": "팀 보기 전용", "label.team-websites": "팀 웹사이트", "label.teams": "팀", - "label.terms": "Terms", + "label.terms": "약관", "label.theme": "테마", "label.this-month": "이번 달", "label.this-week": "이번 주", diff --git a/src/lang/lt-LT.json b/src/lang/lt-LT.json index b0969b8f..8dc4f2f7 100644 --- a/src/lang/lt-LT.json +++ b/src/lang/lt-LT.json @@ -3,57 +3,57 @@ "label.actions": "Veiksmai", "label.activity": "Veiklos žurnalas", "label.add": "Pridėti", - "label.add-board": "Add board", + "label.add-board": "Pridėti lentą", "label.add-description": "Pridėti aprašymą", "label.add-member": "Pridėti narį", - "label.add-step": "Add step", + "label.add-step": "Pridėti žingsnį", "label.add-website": "Pridėti svetainę", "label.admin": "Administrator", - "label.affiliate": "Affiliate", + "label.affiliate": "Partneris", "label.after": "Po", "label.all": "Visi", "label.all-time": "Visas laikotarpis", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.analytics": "Analitika", + "label.apply": "Taikyti", + "label.attribution": "Priskyrimas", + "label.attribution-description": "Žiūrėkite, kaip naudotojai įsitraukia į jūsų rinkodarą ir kas lemia konversijas.", "label.average": "Vidurkis", "label.back": "Atgal", "label.before": "Prieš", - "label.boards": "Boards", + "label.boards": "Lentos", "label.bounce-rate": "Atmetimo rodiklis", - "label.breakdown": "Breakdown", + "label.breakdown": "Išskaidymas", "label.browser": "Naršyklė", "label.browsers": "Naršyklės", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampanijos", "label.cancel": "Atšaukti", "label.change-password": "Pakeisti slaptažodį", - "label.channels": "Channels", + "label.channels": "Kanalai", "label.cities": "Miestai", "label.city": "Miestas", "label.clear-all": "Išvalyti visus", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", + "label.cohort": "Kohorta", + "label.compare": "Palyginti", + "label.compare-dates": "Palyginti datas", "label.confirm": "Patvirtinti", "label.confirm-password": "Patvirtinti slaptažodį", - "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.contains": "Turi", + "label.content": "Turinys", + "label.continue": "Tęsti", + "label.conversion": "Konversija", + "label.conversion-rate": "Konversijos rodiklis", + "label.conversion-step": "Konversijos žingsnis", + "label.count": "Skaičius", "label.countries": "Šalys", "label.country": "Šalis", "label.create": "Sukurti", "label.create-report": "Kurti ataskaitą", "label.create-team": "Sukurti komandą", "label.create-user": "Sukurti vartotoją", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.created": "Sukurta", + "label.created-by": "Sukūrė", + "label.currency": "Valiuta", + "label.current": "Dabartinis", "label.current-password": "Dabartinis slaptažodis", "label.custom-range": "Pasirinktinis intervalas", "label.dashboard": "Švieslentė", @@ -68,185 +68,185 @@ "label.delete-user": "Ištrinti vartotoją", "label.delete-website": "Ištrinti svetainę", "label.description": "Aprašymas", - "label.desktop": "Desktop", + "label.desktop": "Stalinis kompiuteris", "label.details": "Detalės", "label.device": "Įrenginys", "label.devices": "Įrenginiai", - "label.direct": "Direct", + "label.direct": "Tiesioginis", "label.dismiss": "Gerai", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "Unikalus ID", + "label.does-not-contain": "Neturi", + "label.does-not-include": "Neįtraukia", + "label.doest-not-exist": "Neegzistuoja", "label.domain": "Domenas", - "label.dropoff": "Dropoff", + "label.dropoff": "Atsitraukimas", "label.edit": "Redaguoti", "label.edit-dashboard": "Redaguoti švieslentę", "label.edit-member": "Redaguoti narį", - "label.email": "Email", + "label.email": "El. paštas", "label.enable-share-url": "Įjungti bendrinimą su nuoroda", - "label.end-step": "End Step", - "label.entry": "Entry URL", + "label.end-step": "Paskutinis žingsnis", + "label.entry": "Įėjimo URL", "label.event": "Įvykis", "label.event-data": "Įvykių duomenys", - "label.event-name": "Event name", + "label.event-name": "Įvykio pavadinimas", "label.events": "Įvykiai", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", + "label.exists": "Egzistuoja", + "label.exit": "Išėjimo URL", + "label.expand": "Išplėsti", + "label.false": "Netiesa", "label.field": "Laukelis", "label.fields": "Laukeliai", "label.filter": "Filtruoti", "label.filter-combined": "Kombinuoti", "label.filter-raw": "Neapdoroti", "label.filters": "Filtrai", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.first-click": "Pirmas paspaudimas", + "label.first-seen": "Pirmą kartą matyta", + "label.funnel": "Piltuvas", + "label.funnel-description": "Supraskite naudotojų konversijos ir atsitraukimo rodiklius.", + "label.funnels": "Piltuvai", + "label.goal": "Tikslas", + "label.goals": "Tikslai", + "label.goals-description": "Sekite savo tikslus puslapių peržiūroms ir įvykiams.", + "label.greater-than": "Daugiau nei", + "label.greater-than-equals": "Daugiau arba lygu", + "label.grouped": "Grupuota", + "label.hostname": "Pagrindinis kompiuteris", + "label.includes": "Įtraukia", + "label.insight": "Įžvalga", "label.insights": "Įžvalgos", "label.insights-description": "Pasinerkite giliau į savo duomenis naudodami segmentus ir filtrus.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", + "label.is": "Yra", + "label.is-false": "Yra netiesa", + "label.is-not": "Nėra", + "label.is-not-set": "Nenurodyta", + "label.is-set": "Nustatyta", + "label.is-true": "Yra tiesa", "label.join": "Prisijungti", "label.join-team": "Prisijungti į komandą", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.journey": "Kelionė", + "label.journey-description": "Sužinokite, kaip naudotojai naršo jūsų svetainėje.", + "label.journeys": "Kelionės", "label.language": "Kalba", "label.languages": "Kalbos", - "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.laptop": "Nešiojamas kompiuteris", + "label.last-click": "Paskutinis paspaudimas", "label.last-days": "{x, plural, =0 {Paskutinės # dienų} zero {Paskutinės # dienų} one {Paskutinė diena} other {Paskutinės # dienos}}", "label.last-hours": "{x, plural, =0 {Paskutinės # valandų} zero {Paskutinės # valandų} one {Paskutinė # valanda} other {Paskutinės # valandos}}", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", + "label.last-months": "Paskutiniai {x} mėnesiai", + "label.last-seen": "Paskutinį kartą matyta", "label.leave": "Išeiti", "label.leave-team": "Išeiti iš komandos", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.less-than": "Mažiau nei", + "label.less-than-equals": "Mažiau arba lygu", + "label.links": "Nuorodos", "label.login": "Prisijungti", "label.logout": "Atsijungti", "label.manage": "Tvarkyti", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", + "label.manager": "Vadovas", + "label.max": "Maksimumas", + "label.medium": "Vidutinis", "label.member": "Narys", "label.members": "Nariai", - "label.min": "Min", + "label.min": "Minimumas", "label.mobile": "Mobilusis", - "label.model": "Model", + "label.model": "Modelis", "label.more": "Daugiau", "label.my-account": "Mano paskyra", "label.my-websites": "Mano svetainės", "label.name": "Pavadinimas", "label.new-password": "Naujas slaptažodis", - "label.none": "None", + "label.none": "Nėra", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organinė paieška", + "label.organic-shopping": "Organinis apsipirkimas", + "label.organic-social": "Organinis socialinis", + "label.organic-video": "Organinis vaizdo įrašas", "label.os": "Operacinės sistemos", - "label.other": "Other", + "label.other": "Kita", "label.overview": "Apžvalga", "label.owner": "Savininkas", - "label.page": "Page", + "label.page": "Puslapis", "label.page-of": "Puslapis {current} iš {total}", "label.page-views": "Puslapių peržiūros", "label.pageTitle": "Puslapio pavadinimas", "label.pages": "Puslapiai", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Mokama reklama", + "label.paid-search": "Mokama paieška", + "label.paid-shopping": "Mokamas apsipirkimas", + "label.paid-social": "Mokamas socialinis", + "label.paid-video": "Mokamas vaizdo įrašas", "label.password": "Slaptažodis", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Kelias", + "label.paths": "Keliai", + "label.pixels": "Pikseliai", "label.powered-by": "Powered by {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "Ankstesnis", + "label.previous-period": "Ankstesnis laikotarpis", + "label.previous-year": "Ankstesni metai", "label.profile": "Profilis", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Savybės", + "label.property": "Savybė", "label.queries": "Užklausos", "label.query": "Užklausa", "label.query-parameters": "Užklausų parametrai", "label.realtime": "Realiuoju laiku", - "label.referral": "Referral", + "label.referral": "Persiuntimas", "label.referrer": "Persiuntėjas", "label.referrers": "Persiuntėjai", "label.refresh": "Atnaujinti", - "label.regenerate": "Regenerate", + "label.regenerate": "Sugeneruoti iš naujo", "label.region": "Regionas", "label.regions": "Regionai", - "label.remaining": "Remaining", + "label.remaining": "Likę", "label.remove": "Pašalinti", "label.remove-member": "Pašalinti narį", "label.reports": "Ataskaitos", "label.required": "Reikalinga", "label.reset": "Atstatyti", "label.reset-website": "Atstatyti statistikos duomenis", - "label.retention": "Retention", - "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", - "label.role": "Rolė", - "label.run-query": "Run query", + "label.retention": "Išlaikymas", + "label.retention-description": "Išmatuokite, kaip dažnai naudotojai grįžta į jūsų svetainę.", + "label.revenue": "Pajamos", + "label.revenue-description": "Peržiūrėkite savo pajamas laikui bėgant.", + "label.role": "Vaidmuo", + "label.run-query": "Vykdyti užklausą", "label.save": "Išsaugoti", "label.screens": "Ekranai", "label.search": "Ieškoti", - "label.select": "Select", + "label.select": "Pasirinkti", "label.select-date": "Pasirinkti laikotarpį", - "label.select-filter": "Select filter", + "label.select-filter": "Pasirinkti filtrą", "label.select-role": "Pasirinkti rolę", "label.select-website": "Pasirinkti svetainę", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Sesija", + "label.session-data": "Sesijos duomenys", "label.sessions": "Sesijos", "label.settings": "Nustatymai", - "label.share": "Share", + "label.share": "Dalintis", "label.share-url": "Pasidalinti nuoroda", "label.single-day": "Viena diena", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", + "label.sources": "Šaltiniai", + "label.start-step": "Pradžios žingsnis", + "label.steps": "Žingsniai", "label.sum": "Suma", "label.tablet": "Planšetė", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Žyma", + "label.tags": "Žymos", "label.team": "Komanda", "label.team-id": "Komandos ID", - "label.team-manager": "Team manager", + "label.team-manager": "Komandos vadovas", "label.team-member": "Komandos narys", "label.team-name": "Komandos pavadinimas", "label.team-owner": "Komandos savininkas", - "label.team-settings": "Team settings", - "label.team-view-only": "Team view only", - "label.team-websites": "Team websites", + "label.team-settings": "Komandos nustatymai", + "label.team-view-only": "Tik peržiūra", + "label.team-websites": "Komandos svetainės", "label.teams": "Komandos", - "label.terms": "Terms", + "label.terms": "Sąlygos", "label.theme": "Spalvų tema", "label.this-month": "Šis mėnuo", "label.this-week": "Ši savaitė", diff --git a/src/lang/mn-MN.json b/src/lang/mn-MN.json index ecdf5fd0..03ad8a98 100644 --- a/src/lang/mn-MN.json +++ b/src/lang/mn-MN.json @@ -3,46 +3,46 @@ "label.actions": "Үйлдлүүд", "label.activity": "Үйл ажиллагааны бүртгэл", "label.add": "Нэмэх", - "label.add-board": "Add board", + "label.add-board": "Самбар нэмэх", "label.add-description": "Тайлбар нэмэх", "label.add-member": "Гишүүн нэмэх", "label.add-step": "Алхам нэмэх", "label.add-website": "Веб нэмэх", "label.admin": "Админ", - "label.affiliate": "Affiliate", + "label.affiliate": "Харьяа", "label.after": "Хойно", "label.all": "Бүх", "label.all-time": "Бүх цаг үеийн", "label.analytics": "Аналитик", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Хэрэглэх", + "label.attribution": "Холбогдол", + "label.attribution-description": "Хэрэглэгчид таны маркетингт хэрхэн оролцож, ямар зүйлс хөрвүүлэлтэд нөлөөлж байгааг хараарай.", "label.average": "Дундаж", "label.back": "Буцах", "label.before": "Өмнө", - "label.boards": "Boards", + "label.boards": "Самбарууд", "label.bounce-rate": "Нэг хуудас үзээд гарсан", "label.breakdown": "Задаргаа", "label.browser": "Хөтөч", "label.browsers": "Хөтөч", - "label.campaigns": "Campaigns", + "label.campaigns": "Аянууд", "label.cancel": "Цуцлах", "label.change-password": "Нууц үг солих", - "label.channels": "Channels", + "label.channels": "Суваг", "label.cities": "Хотууд", "label.city": "Хот", "label.clear-all": "Бүгдийг арилгах", - "label.cohort": "Cohort", + "label.cohort": "Бүлэг", "label.compare": "Харьцуулах", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Огноо харьцуулах", "label.confirm": "Батлах", "label.confirm-password": "Шинэ нууц үгээ давтах", "label.contains": "Агуулах", - "label.content": "Content", + "label.content": "Агуулга", "label.continue": "Үргэлжлүүлэх", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Хөрвүүлэлт", + "label.conversion-rate": "Хөрвүүлэлтийн хувь", + "label.conversion-step": "Хөрвүүлэлтийн алхам", "label.count": "Тоо", "label.countries": "Улс", "label.country": "Улс", @@ -52,7 +52,7 @@ "label.create-user": "Хэрэглэгч үүсгэх", "label.created": "Үүсгэсэн", "label.created-by": "Үүсгэсэн", - "label.currency": "Currency", + "label.currency": "Валют", "label.current": "Одоогийн", "label.current-password": "Ашиглаж буй нууц үг", "label.custom-range": "Дурын хугацаа", @@ -72,28 +72,28 @@ "label.details": "Мэдээлэл", "label.device": "Төхөөрөмж", "label.devices": "Төхөөрөмж", - "label.direct": "Direct", + "label.direct": "Шууд", "label.dismiss": "Үл хэрэгсэх", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Ялгаатай ID", "label.does-not-contain": "Агуулахгүй", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Агуулаагүй", + "label.doest-not-exist": "Байхгүй", "label.domain": "Домэйн", "label.dropoff": "Уналт", "label.edit": "Засах", "label.edit-dashboard": "Хянах самбар засах", "label.edit-member": "Гишүүн засах", - "label.email": "Email", + "label.email": "Имэйл", "label.enable-share-url": "Хуваалцах холбоос идэвхжүүлэх", "label.end-step": "Төгсгөлийн алхам", "label.entry": "Орох зам", "label.event": "Үйлдэл", "label.event-data": "Үйлдлийн өгөгдөл", - "label.event-name": "Event name", + "label.event-name": "Үйлдлийн нэр", "label.events": "Үйлдэл", - "label.exists": "Exists", + "label.exists": "Байгаа", "label.exit": "Гарах зам", - "label.expand": "Expand", + "label.expand": "Өргөтгөх", "label.false": "Худал", "label.field": "Талбар", "label.fields": "Талбар", @@ -101,37 +101,37 @@ "label.filter-combined": "Нэгтгэсэн", "label.filter-raw": "Түүхий", "label.filters": "Шүүлтүүр", - "label.first-click": "First click", + "label.first-click": "Эхний даралт", "label.first-seen": "Анх харсан", "label.funnel": "Цутгал", "label.funnel-description": "Хэрэглэгчдийн шилжилт, уналтын хэмжээг шинжлэх.", - "label.funnels": "Funnels", + "label.funnels": "Цутгалууд", "label.goal": "Зорилго", "label.goals": "Зорилго", "label.goals-description": "Хуудас үзсэн болон үйлдлийн зорилгыг мөрдөх.", "label.greater-than": "Их", "label.greater-than-equals": "Их буюу тэнцүү", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Бүлэглэсэн", + "label.hostname": "Хост нэр", + "label.includes": "Агуулсан", + "label.insight": "Ойлголт", "label.insights": "Шинжлэх", "label.insights-description": "Өгөгдлөө хэсэгчлэн хуваах, шүүх байдлаар задлан шинжлэх.", "label.is": "Бол", - "label.is-false": "Is false", + "label.is-false": "Худал байна", "label.is-not": "Биш", "label.is-not-set": "Утга оноогоогүй", "label.is-set": "Утга оноосон", - "label.is-true": "Is true", + "label.is-true": "Үнэн байна", "label.join": "Нэгдэх", "label.join-team": "Багт нэгдэх", "label.journey": "Аялал", "label.journey-description": "Хэрэглэгчид таны цахим хуудсаар хэрхэн шилжиж явсныг шинжлэх.", - "label.journeys": "Journeys", + "label.journeys": "Аялалууд", "label.language": "Хэл", "label.languages": "Хэл", "label.laptop": "Зөөврийн компьютер", - "label.last-click": "Last click", + "label.last-click": "Сүүлийн даралт", "label.last-days": "Сүүлийн {x} хоног", "label.last-hours": "Сүүлийн {x} цаг", "label.last-months": "Сүүлийн {x} сар", @@ -140,18 +140,18 @@ "label.leave-team": "Багаас гарах", "label.less-than": "Бага", "label.less-than-equals": "Бага буюу тэнцүү", - "label.links": "Links", + "label.links": "Холбоосууд", "label.login": "Нэвтрэх", "label.logout": "Гарах", "label.manage": "Удирдах", "label.manager": "Удирдагч", "label.max": "Max", - "label.medium": "Medium", + "label.medium": "Дунд", "label.member": "Гишүүн", "label.members": "Гишүүд", "label.min": "Min", "label.mobile": "Утас", - "label.model": "Model", + "label.model": "Загвар", "label.more": "Цааш", "label.my-account": "Миний бүртгэл", "label.my-websites": "Миний вебүүд", @@ -160,28 +160,28 @@ "label.none": "Байхгүй", "label.number-of-records": "{x} {x, plural, one {бичлэг} other {бичлэг}}", "label.ok": "ЗА", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Байгалийн хайлт", + "label.organic-shopping": "Байгалийн дэлгүүр", + "label.organic-social": "Байгалийн сошиал", + "label.organic-video": "Байгалийн видео", "label.os": "OS", - "label.other": "Other", + "label.other": "Бусад", "label.overview": "Тойм", "label.owner": "Эзэмшигч", - "label.page": "Page", + "label.page": "Хуудас", "label.page-of": "Хуудас {total}-с {current}", "label.page-views": "Хуудас үзсэн", "label.pageTitle": "Хуудасны гарчиг", "label.pages": "Хуудас", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Төлбөртэй зар", + "label.paid-search": "Төлбөртэй хайлт", + "label.paid-shopping": "Төлбөртэй дэлгүүр", + "label.paid-social": "Төлбөртэй сошиал", + "label.paid-video": "Төлбөртэй видео", "label.password": "Нууц үг", "label.path": "Зам", "label.paths": "Зам", - "label.pixels": "Pixels", + "label.pixels": "Пиксел", "label.powered-by": "{name} дээр суурилсан", "label.previous": "Өмнөх", "label.previous-period": "Өмнөх үе", @@ -200,7 +200,7 @@ "label.regenerate": "Дахин үүсгэх", "label.region": "Бүс", "label.regions": "Бүсүүд", - "label.remaining": "Remaining", + "label.remaining": "Үлдсэн", "label.remove": "Устгах", "label.remove-member": "Гишүүн хасах", "label.reports": "Тайлан", @@ -218,35 +218,35 @@ "label.search": "Хайх", "label.select": "Сонгох", "label.select-date": "Огноо сонгох", - "label.select-filter": "Select filter", + "label.select-filter": "Шүүлтүүр сонгох", "label.select-role": "Select role", "label.select-website": "Веб сонгох", "label.session": "Session", - "label.session-data": "Session data", + "label.session-data": "Сессийн өгөгдөл", "label.sessions": "Sessions", "label.settings": "Тохиргоо", - "label.share": "Share", + "label.share": "Хуваалцах", "label.share-url": "Хуваалцах холбоос", "label.single-day": "Нэг өдөр", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Эх сурвалжууд", "label.start-step": "Эхлэх алхам", "label.steps": "Алхам", "label.sum": "Нийлбэр", "label.tablet": "Таблет", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Таг", + "label.tags": "Тагууд", "label.team": "Баг", "label.team-id": "Багийн ID", "label.team-manager": "Багийн удирдагч", "label.team-member": "Багийн гишүүн", "label.team-name": "Багийн нэр", "label.team-owner": "Багийн эзэмшигч", - "label.team-settings": "Team settings", + "label.team-settings": "Багийн тохиргоо", "label.team-view-only": "Team view only", "label.team-websites": "Багийн вебүүд", "label.teams": "Багууд", - "label.terms": "Terms", + "label.terms": "Нөхцөл", "label.theme": "Загвар", "label.this-month": "Энэ сар", "label.this-week": "Энэ долоо хоног", diff --git a/src/lang/ms-MY.json b/src/lang/ms-MY.json index 708bf66e..aef880b3 100644 --- a/src/lang/ms-MY.json +++ b/src/lang/ms-MY.json @@ -41,7 +41,7 @@ "label.content": "Content", "label.continue": "Continue", "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", + "label.conversion-rate": "Conversion rate", "label.conversion-step": "Conversion step", "label.count": "Count", "label.countries": "Negara", diff --git a/src/lang/my-MM.json b/src/lang/my-MM.json index 52190830..3f1c6e5a 100644 --- a/src/lang/my-MM.json +++ b/src/lang/my-MM.json @@ -41,7 +41,7 @@ "label.content": "Content", "label.continue": "ဆက်သွားမည်", "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", + "label.conversion-rate": "Conversion rate", "label.conversion-step": "Conversion step", "label.count": "Count", "label.countries": "နိုင်ငံများ", diff --git a/src/lang/nb-NO.json b/src/lang/nb-NO.json index 10cb8736..51c88032 100644 --- a/src/lang/nb-NO.json +++ b/src/lang/nb-NO.json @@ -3,46 +3,46 @@ "label.actions": "Handlinger", "label.activity": "Aktivitetslogg", "label.add": "Legg til", - "label.add-board": "Add board", + "label.add-board": "Legg til tavle", "label.add-description": "Legg til beskrivelse", "label.add-member": "Legg til bruker", "label.add-step": "Legg til steg", "label.add-website": "Legg til nettsted", "label.admin": "Administrator", - "label.affiliate": "Affiliate", + "label.affiliate": "Tilknyttet", "label.after": "Etter", "label.all": "Alle", "label.all-time": "Noensinne", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.analytics": "Analyse", + "label.apply": "Bruk", + "label.attribution": "Attribusjon", + "label.attribution-description": "Se hvordan brukere engasjerer seg i markedsføringen din og hva som driver konverteringer.", "label.average": "Gjennomsnnitt", "label.back": "Tilbake", "label.before": "Før", - "label.boards": "Boards", + "label.boards": "Tavler", "label.bounce-rate": "Avvisningsfrekvens", "label.breakdown": "Nedbrytning", "label.browser": "Nettleser", "label.browsers": "Nettlesere", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampanjer", "label.cancel": "Avvis", "label.change-password": "Bytt passord", - "label.channels": "Channels", + "label.channels": "Kanaler", "label.cities": "Byer", "label.city": "By", "label.clear-all": "Tøm alle", - "label.cohort": "Cohort", + "label.cohort": "Kohort", "label.compare": "Sammenlign", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Sammenlign datoer", "label.confirm": "Bekreft", "label.confirm-password": "Godkjenn passord", "label.contains": "Inneholder", - "label.content": "Content", + "label.content": "Innhold", "label.continue": "Fortsett", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Konvertering", + "label.conversion-rate": "Konverteringsrate", + "label.conversion-step": "Konverteringssteg", "label.count": "Antall", "label.countries": "Land", "label.country": "Land", @@ -52,7 +52,7 @@ "label.create-user": "Opprett bruker", "label.created": "Opprettet", "label.created-by": "Opprettet av", - "label.currency": "Currency", + "label.currency": "Valuta", "label.current": "Nåværende", "label.current-password": "Nåværende passord", "label.custom-range": "Egendefinert utvalg", @@ -63,21 +63,21 @@ "label.day": "Dag", "label.default-date-range": "Standard datoperiode", "label.delete": "Slett", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "Slett rapport", + "label.delete-team": "Slett team", + "label.delete-user": "Slett bruker", "label.delete-website": "Slett nettstedet", - "label.description": "Description", + "label.description": "Beskrivelse", "label.desktop": "Stasjonær", "label.details": "Detaljer", "label.device": "Enhet", "label.devices": "Enheter", - "label.direct": "Direct", + "label.direct": "Direkte", "label.dismiss": "Avbryt", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Unik ID", "label.does-not-contain": "Innholder ikke", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Inkluderer ikke", + "label.doest-not-exist": "Eksisterer ikke", "label.domain": "Domene", "label.dropoff": "Dropoff", "label.edit": "Rediger", @@ -89,11 +89,11 @@ "label.entry": "Inngangs-URL", "label.event": "Hendelse", "label.event-data": "Hendelsesdata", - "label.event-name": "Event name", + "label.event-name": "Hendelsesnavn", "label.events": "Hendelser", - "label.exists": "Exists", + "label.exists": "Eksisterer", "label.exit": "Utgangs-URL", - "label.expand": "Expand", + "label.expand": "Utvid", "label.false": "Usant", "label.field": "Felt", "label.fields": "Felt", @@ -101,37 +101,37 @@ "label.filter-combined": "Kombinert", "label.filter-raw": "Rå", "label.filters": "Filter", - "label.first-click": "First click", + "label.first-click": "Første klikk", "label.first-seen": "Først sett", "label.funnel": "Trakt", "label.funnel-description": "Forstå konverteringen og drop-off frafallsfrekvens av brukere.", - "label.funnels": "Funnels", + "label.funnels": "Trakter", "label.goal": "Mål", "label.goals": "Mål", "label.goals-description": "Spor dine mål for sidevisninger og hendelser.", "label.greater-than": "Mer enn", "label.greater-than-equals": "Mer enn eller lik", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Gruppert", + "label.hostname": "Vertsnavn", + "label.includes": "Inkluderer", + "label.insight": "Innsikt", "label.insights": "Innsikt", "label.insights-description": "Dykk dypere i din data ved bruk av segmentering og filtre.", "label.is": "Er", - "label.is-false": "Is false", + "label.is-false": "Er usant", "label.is-not": "Er ikke", "label.is-not-set": "Er ikke satt", "label.is-set": "Er satt", - "label.is-true": "Is true", + "label.is-true": "Er sant", "label.join": "Bli med", "label.join-team": "Bli med i teamet", "label.journey": "Reise", "label.journey-description": "Forstå hvordan brukerene navigerer gjennom din side.", - "label.journeys": "Journeys", + "label.journeys": "Reiser", "label.language": "Språk", "label.languages": "Språk", "label.laptop": "Bærbar", - "label.last-click": "Last click", + "label.last-click": "Siste klikk", "label.last-days": "Siste {x} dager", "label.last-hours": "Siste {x} timer", "label.last-months": "Last {x} months", @@ -140,7 +140,7 @@ "label.leave-team": "Forlat team", "label.less-than": "Mindre enn", "label.less-than-equals": "Mindre enn eller lik", - "label.links": "Links", + "label.links": "Lenker", "label.login": "Logg inn", "label.logout": "Logg ut", "label.manage": "Administrer", @@ -151,7 +151,7 @@ "label.members": "Brukere", "label.min": "Min", "label.mobile": "Mobiltelefon", - "label.model": "Model", + "label.model": "Modell", "label.more": "Mer", "label.my-account": "Min konto", "label.my-websites": "Mine nettsider", @@ -160,28 +160,28 @@ "label.none": "Ingen", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organisk søk", + "label.organic-shopping": "Organisk handel", + "label.organic-social": "Organisk sosial", + "label.organic-video": "Organisk video", "label.os": "OS", - "label.other": "Other", + "label.other": "Annet", "label.overview": "Oversikt", "label.owner": "Eier", - "label.page": "Page", + "label.page": "Side", "label.page-of": "Side {current} av {total}", "label.page-views": "Sidevisninger", "label.pageTitle": "Sidetittel", "label.pages": "Sider", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Betalte annonser", + "label.paid-search": "Betalt søk", + "label.paid-shopping": "Betalt handel", + "label.paid-social": "Betalt sosial", + "label.paid-video": "Betalt video", "label.password": "Passord", "label.path": "Sti", "label.paths": "Stier", - "label.pixels": "Pixels", + "label.pixels": "Piksler", "label.powered-by": "Drevet av {name}", "label.previous": "Forrige", "label.previous-period": "Forrige periode", @@ -200,7 +200,7 @@ "label.regenerate": "Regenerer", "label.region": "Region", "label.regions": "Regioner", - "label.remaining": "Remaining", + "label.remaining": "Gjenstår", "label.remove": "Fjern", "label.remove-member": "Fjern bruker", "label.reports": "Rapporter", @@ -218,35 +218,35 @@ "label.search": "Søk", "label.select": "Velg", "label.select-date": "Velg dato", - "label.select-filter": "Select filter", + "label.select-filter": "Velg filter", "label.select-role": "Velg rolle", "label.select-website": "Velg nettsted", "label.session": "Økt", - "label.session-data": "Session data", + "label.session-data": "Øktdata", "label.sessions": "Økter", "label.settings": "Innstillinger", - "label.share": "Share", + "label.share": "Del", "label.share-url": "Del URL", "label.single-day": "Enkeltdag", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Kilder", "label.start-step": "Starttrinn", "label.steps": "Trinn", "label.sum": "Sum", "label.tablet": "Nettbrett", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Tagg", + "label.tags": "Tagger", "label.team": "Team", "label.team-id": "Team-ID", "label.team-manager": "Teamadministrator", "label.team-member": "Teammedlem", "label.team-name": "Teamnavn", "label.team-owner": "Teameier", - "label.team-settings": "Team settings", + "label.team-settings": "Teaminnstillinger", "label.team-view-only": "Team (kun visning)", "label.team-websites": "Team-nettsteder", "label.teams": "Team", - "label.terms": "Terms", + "label.terms": "Vilkår", "label.theme": "Tema", "label.this-month": "Denne måneden", "label.this-week": "Denne uka", diff --git a/src/lang/nl-NL.json b/src/lang/nl-NL.json index e4a3d32e..e199d7db 100644 --- a/src/lang/nl-NL.json +++ b/src/lang/nl-NL.json @@ -3,47 +3,47 @@ "label.actions": "Acties", "label.activity": "Activiteiten logboek", "label.add": "Toevoegen", - "label.add-board": "Add board", + "label.add-board": "Bord toevoegen", "label.add-description": "Omschrijving toevoegen", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.add-member": "Lid toevoegen", + "label.add-step": "Stap toevoegen", "label.add-website": "Website koppelen", "label.admin": "Administrator", - "label.affiliate": "Affiliate", + "label.affiliate": "Partner", "label.after": "Na", "label.all": "Alles", "label.all-time": "Onbeperkt", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.analytics": "Analyse", + "label.apply": "Toepassen", + "label.attribution": "Toewijzing", + "label.attribution-description": "Bekijk hoe gebruikers omgaan met je marketing en wat conversies stimuleert.", "label.average": "Gemiddelde", "label.back": "Terug", "label.before": "Voor", - "label.boards": "Boards", + "label.boards": "Borden", "label.bounce-rate": "Bouncepercentage", "label.breakdown": "Opsplitsen", "label.browser": "Browser", "label.browsers": "Browsers", - "label.campaigns": "Campaigns", + "label.campaigns": "Campagnes", "label.cancel": "Annuleren", "label.change-password": "Wachtwoord wijzigen", - "label.channels": "Channels", + "label.channels": "Kanalen", "label.cities": "Steden", "label.city": "Stad", "label.clear-all": "Filters wissen", "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", + "label.compare": "Vergelijken", + "label.compare-dates": "Datums vergelijken", "label.confirm": "Bevestigen", "label.confirm-password": "Wachtwoord bevestigen", "label.contains": "Bevat", - "label.content": "Content", + "label.content": "Inhoud", "label.continue": "Doorgaan", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "Conversie", + "label.conversion-rate": "Conversieratio", + "label.conversion-step": "Conversiestap", + "label.count": "Aantal", "label.countries": "Landen", "label.country": "Land", "label.create": "Aanmaken", @@ -52,8 +52,8 @@ "label.create-user": "Gebruiker maken", "label.created": "Gemaakt", "label.created-by": "Gemaakt Door", - "label.currency": "Currency", - "label.current": "Current", + "label.currency": "Valuta", + "label.current": "Huidig", "label.current-password": "Huidig wachtwoord", "label.custom-range": "Aangepast bereik", "label.dashboard": "Overzicht", @@ -65,19 +65,19 @@ "label.delete": "Verwijderen", "label.delete-report": "Rapport verwijderen", "label.delete-team": "Team verwijderen", - "label.delete-user": "Verwijder gebruiker", + "label.delete-user": "Gebruiker verwijderen", "label.delete-website": "Website verwijderen", - "label.description": "Omschrijving", + "label.description": "Beschrijving", "label.desktop": "Computer", "label.details": "Informatie", "label.device": "Apparaat", "label.devices": "Apparaten", "label.direct": "Direct", "label.dismiss": "Negeren", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Uniek ID", "label.does-not-contain": "Bevat geen", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Bevat niet", + "label.doest-not-exist": "Bestaat niet", "label.domain": "Domein", "label.dropoff": "Uitval", "label.edit": "Bewerken", @@ -89,11 +89,11 @@ "label.entry": "Entry URL", "label.event": "Gebeurtenis", "label.event-data": "Datum gebeurtenis", - "label.event-name": "Event name", + "label.event-name": "Gebeurtenisnaam", "label.events": "Gebeurtenissen", - "label.exists": "Exists", + "label.exists": "Bestaat", "label.exit": "Exit URL", - "label.expand": "Expand", + "label.expand": "Uitvouwen", "label.false": "Onwaar", "label.field": "Veld", "label.fields": "Velden", @@ -101,46 +101,46 @@ "label.filter-combined": "Gecombineerd", "label.filter-raw": "Ruw", "label.filters": "Filters", - "label.first-click": "First click", + "label.first-click": "Eerste klik", "label.first-seen": "First seen", "label.funnel": "Funnel", "label.funnel-description": "Ontdek de conversie- en uitvalpercentages van gebruikers.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", + "label.funnels": "Trechters", + "label.goal": "Doel", + "label.goals": "Doelen", + "label.goals-description": "Volg je doelen voor paginaweergaven en gebeurtenissen.", "label.greater-than": "Groter dan", "label.greater-than-equals": "Groter of gelijk aan", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Gegroepeerd", + "label.hostname": "Hostnaam", + "label.includes": "Bevat", + "label.insight": "Inzicht", "label.insights": "Inzichten", "label.insights-description": "Verken je gegevens verder door segmenten en filters te gebruiken.", "label.is": "Is", - "label.is-false": "Is false", + "label.is-false": "Is onwaar", "label.is-not": "Is niet", "label.is-not-set": "Is niet ingesteld", "label.is-set": "Is ingesteld", - "label.is-true": "Is true", + "label.is-true": "Is waar", "label.join": "Lid worden", "label.join-team": "Word lid van een team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.journey": "Reis", + "label.journey-description": "Begrijp hoe gebruikers door je website navigeren.", + "label.journeys": "Reizen", "label.language": "Taal", "label.languages": "Talen", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Laatste klik", "label.last-days": "Laatste {x} dagen", "label.last-hours": "Laatste {x} uur", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", + "label.last-months": "Laatste {x} maanden", + "label.last-seen": "Laatst gezien", "label.leave": "Verlaten", "label.leave-team": "Verlaat team", "label.less-than": "Minder dan", "label.less-than-equals": "Minder of gelijk aan", - "label.links": "Links", + "label.links": "Koppelingen", "label.login": "Inloggen", "label.logout": "Uitloggen", "label.manage": "Beheren", @@ -160,47 +160,47 @@ "label.none": "Geen", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organisch zoeken", + "label.organic-shopping": "Organisch winkelen", + "label.organic-social": "Organisch sociaal", + "label.organic-video": "Organische video", "label.os": "OS", - "label.other": "Other", + "label.other": "Overig", "label.overview": "Overzicht", "label.owner": "Eigenaar", - "label.page": "Page", + "label.page": "Pagina", "label.page-of": "Pagina {current} van {total}", "label.page-views": "Paginaweergaven", "label.pageTitle": "Pagina titel", "label.pages": "Pagina's", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Betaalde advertenties", + "label.paid-search": "Betaald zoeken", + "label.paid-shopping": "Betaald winkelen", + "label.paid-social": "Betaald sociaal", + "label.paid-video": "Betaalde video", "label.password": "Wachtwoord", - "label.path": "Path", - "label.paths": "Paths", + "label.path": "Pad", + "label.paths": "Paden", "label.pixels": "Pixels", "label.powered-by": "mogelijk gemaakt door {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "Vorige", + "label.previous-period": "Vorige periode", + "label.previous-year": "Vorig jaar", "label.profile": "Profiel", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Eigenschappen", + "label.property": "Eigenschap", "label.queries": "Parameters", "label.query": "Query", "label.query-parameters": "URL-parameters", "label.realtime": "Actueel", - "label.referral": "Referral", + "label.referral": "Verwijzing", "label.referrer": "Referrer", "label.referrers": "Verwijzers", "label.refresh": "Vernieuwen", "label.regenerate": "Opnieuw genereren", "label.region": "Regio", "label.regions": "Regio's", - "label.remaining": "Remaining", + "label.remaining": "Resterend", "label.remove": "Verwijderen", "label.remove-member": "Gebruiker verwijderen", "label.reports": "Rapporten", @@ -209,8 +209,8 @@ "label.reset-website": "Statistieken opnieuw instellen", "label.retention": "Retentie", "label.retention-description": "Meet de retentie van je website door door bij te houden hoe vaak gebruikers terugkeren.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Omzet", + "label.revenue-description": "Bekijk je omzet in de loop van de tijd.", "label.role": "Gebruikersrol", "label.run-query": "Query uitvoeren", "label.save": "Opslaan", @@ -218,35 +218,35 @@ "label.search": "Zoeken", "label.select": "Selecteer", "label.select-date": "Datum selecteren", - "label.select-filter": "Select filter", + "label.select-filter": "Filter selecteren", "label.select-role": "Rol selecteren", "label.select-website": "Website selecteren", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Sessie", + "label.session-data": "Sessiegegevens", "label.sessions": "Sessies", "label.settings": "Instellingen", - "label.share": "Share", + "label.share": "Delen", "label.share-url": "URL delen", "label.single-day": "Enkele dag", "label.sms": "SMS", - "label.sources": "Sources", - "label.start-step": "Start Step", - "label.steps": "Steps", + "label.sources": "Bronnen", + "label.start-step": "Startstap", + "label.steps": "Stappen", "label.sum": "Som", "label.tablet": "Tablet", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Label", + "label.tags": "Labels", "label.team": "Team", "label.team-id": "Team ID", - "label.team-manager": "Team manager", + "label.team-manager": "Teamleider", "label.team-member": "Teamlid", "label.team-name": "Teamnaam", "label.team-owner": "Teameigenaar", - "label.team-settings": "Team settings", + "label.team-settings": "Teaminstellingen", "label.team-view-only": "Team alleen lezen", "label.team-websites": "Team websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Voorwaarden", "label.theme": "Thema", "label.this-month": "Deze maand", "label.this-week": "Deze week", diff --git a/src/lang/pl-PL.json b/src/lang/pl-PL.json index 6e5e0c2f..5685b1e7 100644 --- a/src/lang/pl-PL.json +++ b/src/lang/pl-PL.json @@ -3,46 +3,46 @@ "label.actions": "Działania", "label.activity": "Dziennik aktywności", "label.add": "Dodaj", - "label.add-board": "Add board", + "label.add-board": "Dodaj tablicę", "label.add-description": "Dodaj opis", "label.add-member": "Dodaj członka", "label.add-step": "Dodaj krok", "label.add-website": "Dodaj witrynę", "label.admin": "Administrator", - "label.affiliate": "Affiliate", + "label.affiliate": "Partner", "label.after": "Po", "label.all": "Wszystkie", "label.all-time": "Cały czas", "label.analytics": "Analityka", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Zastosuj", + "label.attribution": "Atrybucja", + "label.attribution-description": "Zobacz, jak użytkownicy angażują się w Twoją reklamę i co napędza konwersje.", "label.average": "Średnia", "label.back": "Powrót", "label.before": "Przed", - "label.boards": "Boards", + "label.boards": "Tablice", "label.bounce-rate": "Współczynnik odrzuceń", "label.breakdown": "Rozbicie", "label.browser": "Przeglądarka", "label.browsers": "Przeglądarki", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampanie", "label.cancel": "Anuluj", "label.change-password": "Zmień hasło", - "label.channels": "Channels", + "label.channels": "Kanały", "label.cities": "Miasta", "label.city": "Miasto", "label.clear-all": "Wyczyść wszystko", - "label.cohort": "Cohort", + "label.cohort": "Kohorta", "label.compare": "Porównaj", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Porównaj daty", "label.confirm": "Potwierdź", "label.confirm-password": "Potwierdź hasło", "label.contains": "Zawiera", - "label.content": "Content", + "label.content": "Treść", "label.continue": "Kontynuuj", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Konwersja", + "label.conversion-rate": "Wskaźnik konwersji", + "label.conversion-step": "Etap konwersji", "label.count": "Liczba", "label.countries": "Kraje", "label.country": "Państwo", @@ -52,7 +52,7 @@ "label.create-user": "Utwórz użytkownika", "label.created": "Utworzony", "label.created-by": "Utworzony przez", - "label.currency": "Currency", + "label.currency": "Waluta", "label.current": "Aktualny", "label.current-password": "Aktualne hasło", "label.custom-range": "Zakres niestandardowy", @@ -72,12 +72,12 @@ "label.details": "Szczegóły", "label.device": "Urządzenie", "label.devices": "Urządzenia", - "label.direct": "Direct", + "label.direct": "Bezpośredni", "label.dismiss": "Odrzuć", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Unikalny ID", "label.does-not-contain": "Nie zawiera", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Nie zawiera", + "label.doest-not-exist": "Nie istnieje", "label.domain": "Domena", "label.dropoff": "Odpływ", "label.edit": "Edytuj", @@ -89,11 +89,11 @@ "label.entry": "Entry URL", "label.event": "Zdarzenie", "label.event-data": "Dane zdarzenia", - "label.event-name": "Event name", + "label.event-name": "Nazwa zdarzenia", "label.events": "Zdarzenia", - "label.exists": "Exists", + "label.exists": "Istnieje", "label.exit": "URL wyjściowy", - "label.expand": "Expand", + "label.expand": "Rozwiń", "label.false": "Fałsz", "label.field": "Pole", "label.fields": "Pola", @@ -101,46 +101,46 @@ "label.filter-combined": "Połączone", "label.filter-raw": "Surowe dane", "label.filters": "Filtry", - "label.first-click": "First click", + "label.first-click": "Pierwsze kliknięcie", "label.first-seen": "First seen", "label.funnel": "Lejek", "label.funnel-description": "Zrozum wskaźniki konwersji i odpływu użytkowników.", - "label.funnels": "Funnels", + "label.funnels": "Lejki", "label.goal": "Cel", "label.goals": "Cele", "label.goals-description": "Track your goals for pageviews and events.", "label.greater-than": "Większe niż", "label.greater-than-equals": "Większe niż lub równe", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Grupowane", + "label.hostname": "Nazwa hosta", + "label.includes": "Zawiera", + "label.insight": "Wgląd", "label.insights": "Analiza", "label.insights-description": "Poznaj lepiej swoje dane, korzystając z segmentów i filtrów.", "label.is": "Równe", - "label.is-false": "Is false", + "label.is-false": "Jest fałszem", "label.is-not": "Nie jest równe", "label.is-not-set": "Nieustawione", "label.is-set": "Ustawione", - "label.is-true": "Is true", + "label.is-true": "Jest prawdą", "label.join": "Dołącz", "label.join-team": "Dołącz do zespołu", "label.journey": "Droga", "label.journey-description": "Zrozum, w jaki sposób użytkownicy poruszają się po Twojej witrynie.", - "label.journeys": "Journeys", + "label.journeys": "Drogi", "label.language": "Język", "label.languages": "Języki", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Ostatnie kliknięcie", "label.last-days": "Ostatnie {x} dni", "label.last-hours": "Ostatnie {x} godzin", - "label.last-months": "Osatnie {x} miesięcy", - "label.last-seen": "Last seen", + "label.last-months": "Ostatnie {x} miesięcy", + "label.last-seen": "Ostatnio widziany", "label.leave": "Opuść", "label.leave-team": "Opuść zespół", "label.less-than": "Mniejsze niż", "label.less-than-equals": "Mniejsze niż lub równe", - "label.links": "Links", + "label.links": "Linki", "label.login": "Zaloguj się", "label.logout": "Wyloguj", "label.manage": "Manage", @@ -160,47 +160,47 @@ "label.none": "Brak", "label.number-of-records": "{x} {x, plural, one {rekord} other {rekordy}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Wyszukiwanie organiczne", + "label.organic-shopping": "Zakupy organiczne", + "label.organic-social": "Organiczne social media", + "label.organic-video": "Organiczne wideo", "label.os": "OS", - "label.other": "Other", + "label.other": "Inne", "label.overview": "Przegląd", "label.owner": "Właściciel", - "label.page": "Page", + "label.page": "Strona", "label.page-of": "Strona {current} z {total}", "label.page-views": "Wyświetlenia strony", "label.pageTitle": "Tytuł strony", "label.pages": "Strony", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Reklamy płatne", + "label.paid-search": "Płatne wyszukiwanie", + "label.paid-shopping": "Płatne zakupy", + "label.paid-social": "Płatne social media", + "label.paid-video": "Płatne wideo", "label.password": "Hasło", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Ścieżka", + "label.paths": "Ścieżki", + "label.pixels": "Piksele", "label.powered-by": "Obsługiwane przez {name}", "label.previous": "Poprzedni", "label.previous-period": "Poprzedni okres", "label.previous-year": "Poprzedni rok", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Właściwości", + "label.property": "Właściwość", "label.queries": "Zapytania", "label.query": "Zapytanie", "label.query-parameters": "Parametry zapytania", "label.realtime": "Czas rzeczywisty", - "label.referral": "Referral", + "label.referral": "Polecenie", "label.referrer": "Źródło odsyłające", "label.referrers": "Źródła odsyłające", "label.refresh": "Odśwież", "label.regenerate": "Wygeneruj ponownie", "label.region": "Region", "label.regions": "Regiony", - "label.remaining": "Remaining", + "label.remaining": "Pozostało", "label.remove": "Usuń", "label.remove-member": "Usuń członka", "label.reports": "Raporty", @@ -209,8 +209,8 @@ "label.reset-website": "Zresetuj statystyki", "label.retention": "Retencja", "label.retention-description": "Mierz przyciągającą siłę swojej strony internetowej, śledząc, jak często użytkownicy powracają.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Przychód", + "label.revenue-description": "Sprawdź swoje przychody w czasie.", "label.role": "Rola", "label.run-query": "Uruchom zapytanie", "label.save": "Zapisz", @@ -218,35 +218,35 @@ "label.search": "Szukaj", "label.select": "Wybierz", "label.select-date": "Wybierz datę", - "label.select-filter": "Select filter", + "label.select-filter": "Wybierz filtr", "label.select-role": "Wybierz rolę", "label.select-website": "Wybierz witrynę", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Sesja", + "label.session-data": "Dane sesji", "label.sessions": "Sesje", "label.settings": "Ustawienia", - "label.share": "Share", + "label.share": "Udostępnij", "label.share-url": "Udostępnij adres URL", "label.single-day": "W tym dniu", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Źródła", "label.start-step": "Krok startowy", "label.steps": "Kroki", "label.sum": "Suma", "label.tablet": "Tablet", "label.tag": "Tag", - "label.tags": "Tags", + "label.tags": "Tagi", "label.team": "Zespół", "label.team-id": "ID zespołu", - "label.team-manager": "Team manager", + "label.team-manager": "Menedżer zespołu", "label.team-member": "Członek zespołu", "label.team-name": "Nazwa zespołu", "label.team-owner": "Właściciel zespołu", - "label.team-settings": "Team settings", + "label.team-settings": "Ustawienia zespołu", "label.team-view-only": "Tylko do odczytu dla zespołu", "label.team-websites": "Witryny zespołu", "label.teams": "Zespoły", - "label.terms": "Terms", + "label.terms": "Warunki", "label.theme": "Motyw", "label.this-month": "W tym miesiącu", "label.this-week": "W tym tygodniu", diff --git a/src/lang/pt-BR.json b/src/lang/pt-BR.json index 6b1e272e..263f8340 100644 --- a/src/lang/pt-BR.json +++ b/src/lang/pt-BR.json @@ -3,47 +3,47 @@ "label.actions": "Ações do usuário", "label.activity": "Registro de atividades", "label.add": "Adicionar", - "label.add-board": "Add board", + "label.add-board": "Adicionar quadro", "label.add-description": "Adicionar descrição", "label.add-member": "Adicionar membro", "label.add-step": "Adicionar etapa", "label.add-website": "Adicionar site", "label.admin": "Administrador", - "label.affiliate": "Affiliate", + "label.affiliate": "Afiliado", "label.after": "Depois", "label.all": "Todos", "label.all-time": "Todos os períodos", "label.analytics": "Análise", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Aplicar", + "label.attribution": "Atribuição", + "label.attribution-description": "Veja como os usuários interagem com seu marketing e o que impulsiona conversões.", "label.average": "Média", "label.back": "Voltar", "label.before": "Antes", - "label.boards": "Boards", + "label.boards": "Quadros", "label.bounce-rate": "Taxa de rejeição", "label.breakdown": "Detalhamento", "label.browser": "Navegador", "label.browsers": "Navegadores", - "label.campaigns": "Campaigns", + "label.campaigns": "Campanhas", "label.cancel": "Cancelar", "label.change-password": "Alterar senha", - "label.channels": "Channels", + "label.channels": "Canais", "label.cities": "Cidades", "label.city": "Cidade", "label.clear-all": "Limpar tudo", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", + "label.cohort": "Cohorte", + "label.compare": "Comparar", + "label.compare-dates": "Comparar datas", "label.confirm": "Confirmar", "label.confirm-password": "Confirmar senha", "label.contains": "Contém", - "label.content": "Content", + "label.content": "Conteúdo", "label.continue": "Continuar", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "Conversão", + "label.conversion-rate": "Taxa de conversão", + "label.conversion-step": "Etapa de conversão", + "label.count": "Contagem", "label.countries": "Países", "label.country": "País", "label.create": "Criar", @@ -52,8 +52,8 @@ "label.create-user": "Criar usuário", "label.created": "Criado", "label.created-by": "Criado por", - "label.currency": "Currency", - "label.current": "Current", + "label.currency": "Moeda", + "label.current": "Atual", "label.current-password": "Senha atual", "label.custom-range": "Período personalizado", "label.dashboard": "Painel", @@ -68,16 +68,16 @@ "label.delete-user": "Excluir usuário", "label.delete-website": "Excluir site", "label.description": "Descrição", - "label.desktop": "Desktop", + "label.desktop": "Computador", "label.details": "Detalhes", "label.device": "Dispositivo", "label.devices": "Dispositivos", - "label.direct": "Direct", + "label.direct": "Direto", "label.dismiss": "Fechar", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "ID distinto", "label.does-not-contain": "Não contém", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Não inclui", + "label.doest-not-exist": "Não existe", "label.domain": "Domínio", "label.dropoff": "Abandono", "label.edit": "Editar", @@ -89,11 +89,11 @@ "label.entry": "Entry URL", "label.event": "Evento", "label.event-data": "Dados do evento", - "label.event-name": "Event name", + "label.event-name": "Nome do evento", "label.events": "Tipos de eventos", - "label.exists": "Exists", + "label.exists": "Existe", "label.exit": "Exit URL", - "label.expand": "Expand", + "label.expand": "Expandir", "label.false": "Não", "label.field": "Campo", "label.fields": "Campos", @@ -101,41 +101,41 @@ "label.filter-combined": "Combinado", "label.filter-raw": "Bruto", "label.filters": "Filtros", - "label.first-click": "First click", + "label.first-click": "Primeiro clique", "label.first-seen": "First seen", "label.funnel": "Funil", "label.funnel-description": "Entenda a taxa de conversão e abandono dos seus usuários.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", + "label.funnels": "Funis", + "label.goal": "Meta", + "label.goals": "Metas", + "label.goals-description": "Acompanhe suas metas para visualizações de página e eventos.", "label.greater-than": "Maior que", "label.greater-than-equals": "Maior ou igual a", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", + "label.grouped": "Agrupado", + "label.hostname": "Nome do host", + "label.includes": "Inclui", "label.insight": "Insight", "label.insights": "Insights", "label.insights-description": "Explore seus dados em mais detalhes usando filtros", "label.is": "É igual a", - "label.is-false": "Is false", + "label.is-false": "É falso", "label.is-not": "Não é igual a", "label.is-not-set": "Não definido", "label.is-set": "Definido", - "label.is-true": "Is true", + "label.is-true": "É verdadeiro", "label.join": "Participar", "label.join-team": "Participar da equipe", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.journey": "Jornada", + "label.journey-description": "Entenda como os usuários navegam pelo seu site.", + "label.journeys": "Jornadas", "label.language": "Idioma", "label.languages": "Idiomas", "label.laptop": "Notebook", - "label.last-click": "Last click", + "label.last-click": "Último clique", "label.last-days": "Últimos {x} dias", "label.last-hours": "Últimas {x} horas", "label.last-months": "Últimos {x} meses", - "label.last-seen": "Last seen", + "label.last-seen": "Última visualização", "label.leave": "Sair", "label.leave-team": "Sair da equipe", "label.less-than": "Menor que", @@ -146,12 +146,12 @@ "label.manage": "Gerenciar", "label.manager": "Manager", "label.max": "Máximo", - "label.medium": "Medium", + "label.medium": "Médio", "label.member": "Membro", "label.members": "Membros", "label.min": "Mínimo", "label.mobile": "Celular", - "label.model": "Model", + "label.model": "Modelo", "label.more": "Mais", "label.my-account": "Minha conta", "label.my-websites": "Meus sites", @@ -160,47 +160,47 @@ "label.none": "Nenhum", "label.number-of-records": "{x} {x, plural, one {registro} other {registros}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Busca orgânica", + "label.organic-shopping": "Compras orgânicas", + "label.organic-social": "Social orgânico", + "label.organic-video": "Vídeo orgânico", "label.os": "Sistema operacional", - "label.other": "Other", + "label.other": "Outro", "label.overview": "Visão geral", "label.owner": "Proprietário", - "label.page": "Page", + "label.page": "Página", "label.page-of": "Página {current} de {total}", "label.page-views": "Visualizações de página", "label.pageTitle": "Título", "label.pages": "Páginas", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Anúncios pagos", + "label.paid-search": "Busca paga", + "label.paid-shopping": "Compras pagas", + "label.paid-social": "Social pago", + "label.paid-video": "Vídeo pago", "label.password": "Senha", - "label.path": "Path", - "label.paths": "Paths", + "label.path": "Caminho", + "label.paths": "Caminhos", "label.pixels": "Pixels", "label.powered-by": "Desenvolvido por {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "Anterior", + "label.previous-period": "Período anterior", + "label.previous-year": "Ano anterior", "label.profile": "Perfil", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Propriedades", + "label.property": "Propriedade", "label.queries": "Consultas", "label.query": "Consulta", "label.query-parameters": "Parâmetros da consulta", "label.realtime": "Tempo real", - "label.referral": "Referral", + "label.referral": "Referência", "label.referrer": "Referência", "label.referrers": "Referências", "label.refresh": "Atualizar", "label.regenerate": "Gerar novamente", "label.region": "Estado", "label.regions": "Estados", - "label.remaining": "Remaining", + "label.remaining": "Restante", "label.remove": "Remover", "label.remove-member": "Remover membro", "label.reports": "Relatórios", @@ -209,8 +209,8 @@ "label.reset-website": "Redefinir dados", "label.retention": "Retenção", "label.retention-description": "Avalie a fidelidade dos seus usuários medindo a frequência com que eles retornam.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Receita", + "label.revenue-description": "Veja sua receita ao longo do tempo.", "label.role": "Função", "label.run-query": "Executar consulta", "label.save": "Salvar", @@ -218,18 +218,18 @@ "label.search": "Pesquisar", "label.select": "Selecionar", "label.select-date": "Selecionar data", - "label.select-filter": "Select filter", + "label.select-filter": "Selecionar filtro", "label.select-role": "Selecionar função", "label.select-website": "Selecionar site", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Sessão", + "label.session-data": "Dados da sessão", "label.sessions": "Sessões", "label.settings": "Configurações", - "label.share": "Share", + "label.share": "Compartilhar", "label.share-url": "Link para compartilhar", "label.single-day": "Apenas um dia", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Fontes", "label.start-step": "Start Step", "label.steps": "Etapas", "label.sum": "Soma", @@ -238,15 +238,15 @@ "label.tags": "Tags", "label.team": "Equipe", "label.team-id": "ID da equipe", - "label.team-manager": "Team manager", + "label.team-manager": "Gerente da equipe", "label.team-member": "Membro da equipe", "label.team-name": "Nome da equipe", "label.team-owner": "Proprietário da equipe", - "label.team-settings": "Team settings", + "label.team-settings": "Configurações da equipe", "label.team-view-only": "Apenas visualização da equipe", "label.team-websites": "Sites da equipe", "label.teams": "Equipes", - "label.terms": "Terms", + "label.terms": "Termos", "label.theme": "Tema", "label.this-month": "Este mês", "label.this-week": "Esta semana", diff --git a/src/lang/pt-PT.json b/src/lang/pt-PT.json index aa9a64bf..54569525 100644 --- a/src/lang/pt-PT.json +++ b/src/lang/pt-PT.json @@ -1,206 +1,206 @@ { - "label.access-code": "Access code", + "label.access-code": "Código de acesso", "label.actions": "Ações", - "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.activity": "Registo de atividade", + "label.add": "Adicionar", + "label.add-board": "Adicionar quadro", + "label.add-description": "Adicionar descrição", + "label.add-member": "Adicionar membro", + "label.add-step": "Adicionar passo", "label.add-website": "Adicionar website", "label.admin": "Administrador", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "Afiliado", + "label.after": "Depois", "label.all": "Todos", "label.all-time": "Todo o tempo", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.analytics": "Análise", + "label.apply": "Aplicar", + "label.attribution": "Atribuição", + "label.attribution-description": "Veja como os utilizadores interagem com o seu marketing e o que impulsiona conversões.", + "label.average": "Média", "label.back": "Voltar", - "label.before": "Before", - "label.boards": "Boards", + "label.before": "Antes", + "label.boards": "Quadros", "label.bounce-rate": "Taxa de rejeição", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.breakdown": "Detalhamento", + "label.browser": "Navegador", "label.browsers": "Navegadores", - "label.campaigns": "Campaigns", + "label.campaigns": "Campanhas", "label.cancel": "Cancelar", "label.change-password": "Alterar senha", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "Canais", + "label.cities": "Cidades", + "label.city": "Cidade", + "label.clear-all": "Limpar tudo", + "label.cohort": "Cohorte", + "label.compare": "Comparar", + "label.compare-dates": "Comparar datas", + "label.confirm": "Confirmar", "label.confirm-password": "Confirmar senha", "label.contains": "Contains", - "label.content": "Content", + "label.content": "Conteúdo", "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "Conversão", + "label.conversion-rate": "Taxa de conversão", + "label.conversion-step": "Passo de conversão", + "label.count": "Contagem", "label.countries": "Países", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "País", + "label.create": "Criar", + "label.create-report": "Criar relatório", + "label.create-team": "Criar equipa", + "label.create-user": "Criar utilizador", + "label.created": "Criado", + "label.created-by": "Criado por", + "label.currency": "Moeda", + "label.current": "Atual", "label.current-password": "Senha atual", "label.custom-range": "Intervalo personalizado", "label.dashboard": "Painel", "label.data": "Data", "label.date": "Date", "label.date-range": "Intervalo de datas", - "label.day": "Day", + "label.day": "Dia", "label.default-date-range": "Intervalo de datas predefinido", "label.delete": "Eliminar", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "Eliminar relatório", + "label.delete-team": "Eliminar equipa", + "label.delete-user": "Eliminar utilizador", "label.delete-website": "Eliminar website", - "label.description": "Description", - "label.desktop": "Desktop", - "label.details": "Details", - "label.device": "Device", + "label.description": "Descrição", + "label.desktop": "Computador", + "label.details": "Detalhes", + "label.device": "Dispositivo", "label.devices": "Dispositivos", - "label.direct": "Direct", + "label.direct": "Direto", "label.dismiss": "Ignorar", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "ID distinto", + "label.does-not-contain": "Não contém", + "label.does-not-include": "Não inclui", + "label.doest-not-exist": "Não existe", "label.domain": "Domínio", "label.dropoff": "Dropoff", "label.edit": "Editar", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", + "label.edit-dashboard": "Editar painel", + "label.edit-member": "Editar membro", "label.email": "Email", "label.enable-share-url": "Ativar link de partilha", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "Passo final", + "label.entry": "URL de entrada", + "label.event": "Evento", + "label.event-data": "Dados do evento", + "label.event-name": "Nome do evento", "label.events": "Eventos", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", - "label.filter": "Filter", + "label.exists": "Existe", + "label.exit": "URL de saída", + "label.expand": "Expandir", + "label.false": "Falso", + "label.field": "Campo", + "label.fields": "Campos", + "label.filter": "Filtro", "label.filter-combined": "Combinado", "label.filter-raw": "Dados brutos", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", + "label.filters": "Filtros", + "label.first-click": "Primeiro clique", + "label.first-seen": "Primeira visualização", + "label.funnel": "Funil", + "label.funnel-description": "Compreenda a taxa de conversão e abandono dos utilizadores.", + "label.funnels": "Funis", + "label.goal": "Objetivo", + "label.goals": "Objetivos", + "label.goals-description": "Acompanhe os seus objetivos para visualizações de página e eventos.", + "label.greater-than": "Maior que", + "label.greater-than-equals": "Maior ou igual a", + "label.grouped": "Agrupado", + "label.hostname": "Nome do host", + "label.includes": "Inclui", "label.insight": "Insight", "label.insights": "Insights", "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.is": "É", + "label.is-false": "É falso", + "label.is-not": "Não é", + "label.is-not-set": "Não definido", + "label.is-set": "Definido", + "label.is-true": "É verdadeiro", + "label.join": "Juntar-se", + "label.join-team": "Juntar-se à equipa", + "label.journey": "Jornada", + "label.journey-description": "Compreenda como os utilizadores navegam no seu website.", + "label.journeys": "Jornadas", "label.language": "Língua", "label.languages": "Línguas", "label.laptop": "Portátil", - "label.last-click": "Last click", + "label.last-click": "Último clique", "label.last-days": "Últimos {x} dias", "label.last-hours": "Últimas {x} horas", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "Últimos {x} meses", + "label.last-seen": "Última visualização", + "label.leave": "Sair", + "label.leave-team": "Sair da equipa", + "label.less-than": "Menor que", + "label.less-than-equals": "Menor ou igual a", + "label.links": "Ligações", "label.login": "Iniciar sessão", "label.logout": "Sair", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.manage": "Gerir", + "label.manager": "Gestor", + "label.max": "Máximo", + "label.medium": "Médio", + "label.member": "Membro", + "label.members": "Membros", + "label.min": "Mínimo", "label.mobile": "Telemóvel", - "label.model": "Model", + "label.model": "Modelo", "label.more": "Mais", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "A minha conta", + "label.my-websites": "Os meus websites", "label.name": "Nome", "label.new-password": "Nova senha", - "label.none": "None", + "label.none": "Nenhum", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Pesquisa orgânica", + "label.organic-shopping": "Compras orgânicas", + "label.organic-social": "Social orgânico", + "label.organic-video": "Vídeo orgânico", "label.os": "OS", - "label.other": "Other", + "label.other": "Outro", "label.overview": "Overview", "label.owner": "Proprietário", - "label.page": "Page", + "label.page": "Página", "label.page-of": "Page {current} of {total}", "label.page-views": "Visualizações da página", "label.pageTitle": "Page title", "label.pages": "Páginas", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Anúncios pagos", + "label.paid-search": "Pesquisa paga", + "label.paid-shopping": "Compras pagas", + "label.paid-social": "Social pago", + "label.paid-video": "Vídeo pago", "label.password": "Senha", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Caminho", + "label.paths": "Caminhos", + "label.pixels": "Píxeis", "label.powered-by": "Distribuído por {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "Anterior", + "label.previous-period": "Período anterior", + "label.previous-year": "Ano anterior", "label.profile": "Perfil", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Propriedades", + "label.property": "Propriedade", "label.queries": "Queries", "label.query": "Query", "label.query-parameters": "Query parameters", "label.realtime": "Tempo real", - "label.referral": "Referral", + "label.referral": "Referência", "label.referrer": "Referrer", "label.referrers": "Referenciadores", "label.refresh": "Atualizar", "label.regenerate": "Regenerate", "label.region": "Region", "label.regions": "Regions", - "label.remaining": "Remaining", + "label.remaining": "Restante", "label.remove": "Remove", "label.remove-member": "Remove member", "label.reports": "Reports", @@ -209,8 +209,8 @@ "label.reset-website": "Repor estatísticas", "label.retention": "Retention", "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Receita", + "label.revenue-description": "Veja a sua receita ao longo do tempo.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Guardar", @@ -218,35 +218,35 @@ "label.search": "Search", "label.select": "Select", "label.select-date": "Select date", - "label.select-filter": "Select filter", + "label.select-filter": "Selecionar filtro", "label.select-role": "Select role", "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Sessão", + "label.session-data": "Dados da sessão", "label.sessions": "Sessions", "label.settings": "Definições", - "label.share": "Share", + "label.share": "Partilhar", "label.share-url": "Partilhar link", "label.single-day": "Dia único", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Fontes", "label.start-step": "Start Step", "label.steps": "Steps", "label.sum": "Sum", "label.tablet": "Tablet", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Etiqueta", + "label.tags": "Etiquetas", "label.team": "Team", "label.team-id": "Team ID", - "label.team-manager": "Team manager", + "label.team-manager": "Gestor de equipa", "label.team-member": "Team member", "label.team-name": "Team name", "label.team-owner": "Team owner", - "label.team-settings": "Team settings", + "label.team-settings": "Definições da equipa", "label.team-view-only": "Team view only", "label.team-websites": "Team websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Termos", "label.theme": "Tema", "label.this-month": "Este mês", "label.this-week": "Esta semana", diff --git a/src/lang/ro-RO.json b/src/lang/ro-RO.json index fda14b4e..eaeecca3 100644 --- a/src/lang/ro-RO.json +++ b/src/lang/ro-RO.json @@ -3,46 +3,46 @@ "label.actions": "Acțiuni", "label.activity": "Jurnal de activități", "label.add": "Adaugă", - "label.add-board": "Add board", + "label.add-board": "Adaugă panou", "label.add-description": "Adaugă descriere", "label.add-member": "Adaugă membru", "label.add-step": "Adaugă pas", "label.add-website": "Adaugă site web", "label.admin": "Administrator", - "label.affiliate": "Affiliate", + "label.affiliate": "Afiliat", "label.after": "După", "label.all": "Toate", "label.all-time": "Pentru tot timpul", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.analytics": "Analiză", + "label.apply": "Aplică", + "label.attribution": "Atribuire", + "label.attribution-description": "Vezi cum utilizatorii interacționează cu marketingul tău și ce determină conversiile.", "label.average": "Mediu", "label.back": "Înapoi", "label.before": "Înainte", - "label.boards": "Boards", + "label.boards": "Panouri", "label.bounce-rate": "Rata de respingere", "label.breakdown": "Detaliat", "label.browser": "Browser", "label.browsers": "Browsere", - "label.campaigns": "Campaigns", + "label.campaigns": "Campanii", "label.cancel": "Anulează", "label.change-password": "Schimbare parolă", - "label.channels": "Channels", + "label.channels": "Canale", "label.cities": "Orașe", "label.city": "Oraș", "label.clear-all": "Șterge tot", - "label.cohort": "Cohort", + "label.cohort": "Cohortă", "label.compare": "Compară", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Compară datele", "label.confirm": "Confirm", "label.confirm-password": "Confirmare parolă", "label.contains": "Conține", - "label.content": "Content", + "label.content": "Conținut", "label.continue": "Continuă", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Conversie", + "label.conversion-rate": "Rată de conversie", + "label.conversion-step": "Pas de conversie", "label.count": "Număr", "label.countries": "Țări", "label.country": "Țară", @@ -52,7 +52,7 @@ "label.create-user": "Crează utilizator", "label.created": "Creat", "label.created-by": "Creat de", - "label.currency": "Currency", + "label.currency": "Monedă", "label.current": "Curent", "label.current-password": "Parola curentă", "label.custom-range": "Interval personalizat", @@ -76,8 +76,8 @@ "label.dismiss": "Renunță", "label.distinct-id": "Distinct ID", "label.does-not-contain": "Nu conține", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Nu include", + "label.doest-not-exist": "Nu există", "label.domain": "Domeniu", "label.dropoff": "Rată de abandon", "label.edit": "Editare", @@ -89,11 +89,11 @@ "label.entry": "URL de intrare", "label.event": "Eveniment", "label.event-data": "Date despre eveniment", - "label.event-name": "Event name", + "label.event-name": "Nume eveniment", "label.events": "Evenimente", - "label.exists": "Exists", + "label.exists": "Există", "label.exit": "URL de ieșire", - "label.expand": "Expand", + "label.expand": "Extinde", "label.false": "Fals", "label.field": "Câmp", "label.fields": "Câmpuri", @@ -101,37 +101,37 @@ "label.filter-combined": "Combinat", "label.filter-raw": "Brut", "label.filters": "Filtre", - "label.first-click": "First click", + "label.first-click": "Primul click", "label.first-seen": "Văzut pentru prima dată", "label.funnel": "Parcursul utilizatorului", "label.funnel-description": "Înțelege rata de conversie și rata de abandon a utilizatorilor.", - "label.funnels": "Funnels", + "label.funnels": "Parcursuri", "label.goal": "Obiectiv", "label.goals": "Obiective", "label.goals-description": "Urmărește obiectivele de vizualizări și evenimente.", "label.greater-than": "Mai mare decât", "label.greater-than-equals": "Mai mare sau egal cu", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Grupat", + "label.hostname": "Nume gazdă", + "label.includes": "Include", + "label.insight": "Perspectivă", "label.insights": "Perspective", "label.insights-description": "Aprofundează datele utilizând segmente și filtre.", "label.is": "Este", - "label.is-false": "Is false", + "label.is-false": "Este fals", "label.is-not": "Nu este", "label.is-not-set": "Nu este setat", "label.is-set": "Este setat", - "label.is-true": "Is true", + "label.is-true": "Este adevărat", "label.join": "Alătură-te", "label.join-team": "Alătură-te echipei", "label.journey": "Traseu", "label.journey-description": "Înțelege cum navighează vizitatorii prin website.", - "label.journeys": "Journeys", + "label.journeys": "Trasee", "label.language": "Limbă", "label.languages": "Limbi", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Ultimul click", "label.last-days": "Ultimele {x} zile", "label.last-hours": "Ultimele {x} ore", "label.last-months": "Ultimele {x} luni", @@ -140,13 +140,13 @@ "label.leave-team": "Părăsește echipa", "label.less-than": "Mai puțin decât", "label.less-than-equals": "Mai puțin sau egal cu", - "label.links": "Links", + "label.links": "Linkuri", "label.login": "Autentificare", "label.logout": "Ieșire din cont", "label.manage": "Administrează", "label.manager": "Manager", "label.max": "Max", - "label.medium": "Medium", + "label.medium": "Mediu", "label.member": "Membru", "label.members": "Membri", "label.min": "Min", @@ -160,28 +160,28 @@ "label.none": "Niciunul", "label.number-of-records": "{x} {x, plural, one {înregistrare} other {înregistrări}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Căutare organică", + "label.organic-shopping": "Cumpărături organice", + "label.organic-social": "Social organic", + "label.organic-video": "Video organic", "label.os": "OS", - "label.other": "Other", + "label.other": "Altul", "label.overview": "Vedere de ansamblu", "label.owner": "Titular", - "label.page": "Page", + "label.page": "Pagină", "label.page-of": "Pagina {current} din {total}", "label.page-views": "Vizualizări de pagină", "label.pageTitle": "Titlul paginii", "label.pages": "Pagini", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Reclame plătite", + "label.paid-search": "Căutare plătită", + "label.paid-shopping": "Cumpărături plătite", + "label.paid-social": "Social plătit", + "label.paid-video": "Video plătit", "label.password": "Parolă", "label.path": "Rută", "label.paths": "Rute", - "label.pixels": "Pixels", + "label.pixels": "Pixeli", "label.powered-by": "Cu sprijinul {name}", "label.previous": "Anterior", "label.previous-period": "Perioda anterioară", @@ -200,7 +200,7 @@ "label.regenerate": "Regenerează", "label.region": "Regiune", "label.regions": "Regiuni", - "label.remaining": "Remaining", + "label.remaining": "Rămas", "label.remove": "Îndepărtează", "label.remove-member": "Îndepărtează membru", "label.reports": "Rapoarte", @@ -218,35 +218,35 @@ "label.search": "Căutare", "label.select": "Selectează", "label.select-date": "Selectează data", - "label.select-filter": "Select filter", + "label.select-filter": "Selectează filtru", "label.select-role": "Selectează rolul", "label.select-website": "Selectează website", "label.session": "Sesiune", - "label.session-data": "Session data", + "label.session-data": "Date sesiune", "label.sessions": "Sesiuni", "label.settings": "Setări", - "label.share": "Share", + "label.share": "Partajează", "label.share-url": "Partajare URL", "label.single-day": "O singură zi", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Surse", "label.start-step": "Pas de început", "label.steps": "Pași", "label.sum": "Sumă", "label.tablet": "Tabletă", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Etichetă", + "label.tags": "Etichete", "label.team": "Echipă", "label.team-id": "ID Echipă", "label.team-manager": "Manager echipă", "label.team-member": "Membru echipă", "label.team-name": "Nume echipă", "label.team-owner": "Titular echipă", - "label.team-settings": "Team settings", + "label.team-settings": "Setări echipă", "label.team-view-only": "Doar vizualizare echipă", "label.team-websites": "Website-uri echipă", "label.teams": "Echipă", - "label.terms": "Terms", + "label.terms": "Termeni", "label.theme": "Temă", "label.this-month": "Această lună", "label.this-week": "Această săptămână", diff --git a/src/lang/ru-RU.json b/src/lang/ru-RU.json index d014c234..3dce74e5 100644 --- a/src/lang/ru-RU.json +++ b/src/lang/ru-RU.json @@ -3,46 +3,46 @@ "label.actions": "Действия", "label.activity": "Журнал активности", "label.add": "Добавить", - "label.add-board": "Add board", + "label.add-board": "Добавить доску", "label.add-description": "Добавить описание", "label.add-member": "Добавить участника", "label.add-step": "Добавить шаг", "label.add-website": "Добавить сайт", "label.admin": "Администратор", - "label.affiliate": "Affiliate", + "label.affiliate": "Партнер", "label.after": "После", "label.all": "Все", "label.all-time": "Все время", "label.analytics": "Аналитика", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Применить", + "label.attribution": "Атрибуция", + "label.attribution-description": "Посмотрите, как пользователи взаимодействуют с вашим маркетингом и что приводит к конверсиям.", "label.average": "Средний", "label.back": "Назад", "label.before": "До", - "label.boards": "Boards", + "label.boards": "Доски", "label.bounce-rate": "Отказы", "label.breakdown": "Авария", "label.browser": "Браузер", "label.browsers": "Браузеры", - "label.campaigns": "Campaigns", + "label.campaigns": "Кампании", "label.cancel": "Отменить", "label.change-password": "Изменить пароль", - "label.channels": "Channels", + "label.channels": "Каналы", "label.cities": "Города", "label.city": "Город", "label.clear-all": "Очистить все", - "label.cohort": "Cohort", + "label.cohort": "Когорта", "label.compare": "Сравнить", - "label.compare-dates": "Compare dates", + "label.compare-dates": "Сравнить даты", "label.confirm": "Подтвердить", "label.confirm-password": "Подтвердить пароль", "label.contains": "Содержит", - "label.content": "Content", + "label.content": "Контент", "label.continue": "Продолжить", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "Конверсия", + "label.conversion-rate": "Коэффициент конверсии", + "label.conversion-step": "Шаг конверсии", "label.count": "Считать", "label.countries": "Страны", "label.country": "Страна", @@ -52,7 +52,7 @@ "label.create-user": "Создать пользователя", "label.created": "Создано", "label.created-by": "Создано", - "label.currency": "Currency", + "label.currency": "Валюта", "label.current": "Текущий", "label.current-password": "Текущий пароль", "label.custom-range": "Другой период", @@ -76,8 +76,8 @@ "label.dismiss": "Отклонить", "label.distinct-id": "Distinct ID", "label.does-not-contain": "Не содержит", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Не включает", + "label.doest-not-exist": "Не существует", "label.domain": "Домен", "label.dropoff": "Высадка", "label.edit": "Изменить", @@ -89,11 +89,11 @@ "label.entry": "URL-адрес входа", "label.event": "Событие", "label.event-data": "Данные о событии", - "label.event-name": "Event name", + "label.event-name": "Название события", "label.events": "События", - "label.exists": "Exists", + "label.exists": "Существует", "label.exit": "URL-адрес выхода", - "label.expand": "Expand", + "label.expand": "Развернуть", "label.false": "Ложь", "label.field": "Поле", "label.fields": "Поля", @@ -101,37 +101,37 @@ "label.filter-combined": "Объединенные", "label.filter-raw": "Сырые данные", "label.filters": "Фильтры", - "label.first-click": "First click", + "label.first-click": "Первый клик", "label.first-seen": "Первый вход", "label.funnel": "Воронка", "label.funnel-description": "Изучите коэффициент конверсии и ухода пользователей.", - "label.funnels": "Funnels", + "label.funnels": "Воронки", "label.goal": "Цель", "label.goals": "Цели", "label.goals-description": "Отслеживайте свои цели по просмотрам страниц и событиям.", "label.greater-than": "Больше, чем", "label.greater-than-equals": "Больше или равно", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Группировано", + "label.hostname": "Имя хоста", + "label.includes": "Включает", + "label.insight": "Инсайт", "label.insights": "Информация", "label.insights-description": "Погрузитесь глубже в свои данные с помощью сегментов и фильтров.", "label.is": "Является", - "label.is-false": "Is false", + "label.is-false": "Ложно", "label.is-not": "Не установлен", "label.is-not-set": "Не установлено", "label.is-set": "Установлен", - "label.is-true": "Is true", + "label.is-true": "Истинно", "label.join": "Присоединиться", "label.join-team": "Присоединиться к команде", "label.journey": "Journey", "label.journey-description": "Поймите, как пользователи перемещаются по вашему сайту.", - "label.journeys": "Journeys", + "label.journeys": "Пути", "label.language": "Язык", "label.languages": "Языки", "label.laptop": "Ноутбук", - "label.last-click": "Last click", + "label.last-click": "Последний клик", "label.last-days": "Последние {x} дней", "label.last-hours": "Последние {x} часа", "label.last-months": "Последние {x} месяцев", @@ -140,18 +140,18 @@ "label.leave-team": "Покинуть команду", "label.less-than": "Меньше, чем", "label.less-than-equals": "Меньше или равно", - "label.links": "Links", + "label.links": "Ссылки", "label.login": "Войти", "label.logout": "Выйти", "label.manage": "Управление", "label.manager": "Менеджер", "label.max": "Максимум", - "label.medium": "Medium", + "label.medium": "Средний", "label.member": "Участник", "label.members": "Участники", "label.min": "Минимум", "label.mobile": "Смартфон", - "label.model": "Model", + "label.model": "Модель", "label.more": "Больше", "label.my-account": "Мой профиль", "label.my-websites": "Мои сайты", @@ -160,28 +160,28 @@ "label.none": "Не указано", "label.number-of-records": "{x} {x, plural, one {запись} other {записи}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Органический поиск", + "label.organic-shopping": "Органические покупки", + "label.organic-social": "Органические соцсети", + "label.organic-video": "Органическое видео", "label.os": "OS", - "label.other": "Other", + "label.other": "Другое", "label.overview": "Обзор", "label.owner": "Владелец", - "label.page": "Page", + "label.page": "Страница", "label.page-of": "Страница {current} из {total}", "label.page-views": "Просмотры страниц", "label.pageTitle": "Название страницы", "label.pages": "Страницы", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Платная реклама", + "label.paid-search": "Платный поиск", + "label.paid-shopping": "Платные покупки", + "label.paid-social": "Платные соцсети", + "label.paid-video": "Платное видео", "label.password": "Пароль", "label.path": "Путь", "label.paths": "Пути", - "label.pixels": "Pixels", + "label.pixels": "Пиксели", "label.powered-by": "На движке {name}", "label.previous": "Предыдущий", "label.previous-period": "Предыдущий период", @@ -200,7 +200,7 @@ "label.regenerate": "Обновить", "label.region": "Регион", "label.regions": "Регионы", - "label.remaining": "Remaining", + "label.remaining": "Осталось", "label.remove": "Удалить", "label.remove-member": "Удалить участника", "label.reports": "Отчеты", @@ -218,35 +218,35 @@ "label.search": "Поиск", "label.select": "Выберите", "label.select-date": "Выберите дату", - "label.select-filter": "Select filter", + "label.select-filter": "Выберите фильтр", "label.select-role": "Выберите роль", "label.select-website": "Выбрать сайт", "label.session": "Сессия", - "label.session-data": "Session data", + "label.session-data": "Данные сессии", "label.sessions": "Сессии", "label.settings": "Настройки", - "label.share": "Share", + "label.share": "Поделиться", "label.share-url": "Поделиться ссылкой", "label.single-day": "Один день", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Источники", "label.start-step": "Начальный этап", "label.steps": "Шаги", "label.sum": "Сумма", "label.tablet": "Планшет", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Тег", + "label.tags": "Теги", "label.team": "Команда", "label.team-id": "ID команды", "label.team-manager": "Менеджер команды", "label.team-member": "Член команды", "label.team-name": "Название команды", "label.team-owner": "Владелец команды", - "label.team-settings": "Team settings", + "label.team-settings": "Настройки команды", "label.team-view-only": "Только командный просмотр", "label.team-websites": "Веб-сайты команды", "label.teams": "Команды", - "label.terms": "Terms", + "label.terms": "Условия", "label.theme": "Тема", "label.this-month": "Этот месяц", "label.this-week": "Эта неделя", diff --git a/src/lang/si-LK.json b/src/lang/si-LK.json index e4ec7ea9..7de3ec70 100644 --- a/src/lang/si-LK.json +++ b/src/lang/si-LK.json @@ -41,7 +41,7 @@ "label.content": "Content", "label.continue": "Continue", "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", + "label.conversion-rate": "Conversion rate", "label.conversion-step": "Conversion step", "label.count": "Count", "label.countries": "Countries", diff --git a/src/lang/sk-SK.json b/src/lang/sk-SK.json index 5fd574e1..1b9e6033 100644 --- a/src/lang/sk-SK.json +++ b/src/lang/sk-SK.json @@ -1,206 +1,206 @@ { - "label.access-code": "Access code", + "label.access-code": "Prístupový kód", "label.actions": "Akcie", - "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.activity": "Denník aktivít", + "label.add": "Pridať", + "label.add-board": "Pridať tabuľu", + "label.add-description": "Pridať popis", + "label.add-member": "Pridať člena", + "label.add-step": "Pridať krok", "label.add-website": "Pridať web", "label.admin": "Administrátor", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "Partner", + "label.after": "Po", "label.all": "Všetko", - "label.all-time": "All time", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.all-time": "Celý čas", + "label.analytics": "Analytika", + "label.apply": "Použiť", + "label.attribution": "Priradenie", + "label.attribution-description": "Pozrite sa, ako používatelia interagujú s vaším marketingom a čo vedie ku konverziám.", + "label.average": "Priemer", "label.back": "Späť", - "label.before": "Before", - "label.boards": "Boards", + "label.before": "Pred", + "label.boards": "Tabule", "label.bounce-rate": "Okamžité opustenie", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.breakdown": "Rozpis", + "label.browser": "Prehliadač", "label.browsers": "Prehliadač", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampane", "label.cancel": "Zrušiť", "label.change-password": "Zmeniť heslo", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "Kanály", + "label.cities": "Mestá", + "label.city": "Mesto", + "label.clear-all": "Vymazať všetko", + "label.cohort": "Kohorta", + "label.compare": "Porovnať", + "label.compare-dates": "Porovnať dátumy", + "label.confirm": "Potvrdiť", "label.confirm-password": "Potvrdiť heslo", "label.contains": "Contains", - "label.content": "Content", + "label.content": "Obsah", "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "Konverzia", + "label.conversion-rate": "Miera konverzie", + "label.conversion-step": "Krok konverzie", + "label.count": "Počet", "label.countries": "Zem", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "Krajina", + "label.create": "Vytvoriť", + "label.create-report": "Vytvoriť správu", + "label.create-team": "Vytvoriť tím", + "label.create-user": "Vytvoriť používateľa", + "label.created": "Vytvorené", + "label.created-by": "Vytvoril", + "label.currency": "Mena", + "label.current": "Aktuálny", "label.current-password": "Aktuálne heslo", "label.custom-range": "Vlastný rozsah", "label.dashboard": "Prehlad", "label.data": "Data", "label.date": "Date", "label.date-range": "Obdobie", - "label.day": "Day", + "label.day": "Deň", "label.default-date-range": "Predvolené obdobie", "label.delete": "Zmazať", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "Zmazať správu", + "label.delete-team": "Zmazať tím", + "label.delete-user": "Zmazať používateľa", "label.delete-website": "Zmazať web", - "label.description": "Description", + "label.description": "Popis", "label.desktop": "Stolný počítač", "label.details": "Details", - "label.device": "Device", + "label.device": "Zariadenie", "label.devices": "Zariadenie", - "label.direct": "Direct", + "label.direct": "Priamy", "label.dismiss": "Odísť", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "Jedinečné ID", + "label.does-not-contain": "Neobsahuje", + "label.does-not-include": "Nezahŕňa", + "label.doest-not-exist": "Neexistuje", "label.domain": "Doména", "label.dropoff": "Dropoff", "label.edit": "Upraviť", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", + "label.edit-dashboard": "Upraviť prehľad", + "label.edit-member": "Upraviť člena", "label.email": "Email", "label.enable-share-url": "Povoliť zdielanie URL", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "Konečný krok", + "label.entry": "Vstupná URL", + "label.event": "Udalosť", + "label.event-data": "Dáta udalosti", + "label.event-name": "Názov udalosti", "label.events": "Udalosti", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", + "label.exists": "Existuje", + "label.exit": "Výstupná URL", + "label.expand": "Rozbaliť", + "label.false": "Nepravda", + "label.field": "Pole", + "label.fields": "Polia", "label.filter": "Filter", "label.filter-combined": "Kombinácie", "label.filter-raw": "Nezpracované", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.filters": "Filtre", + "label.first-click": "Prvé kliknutie", + "label.first-seen": "Prvýkrát videné", + "label.funnel": "Lievik", + "label.funnel-description": "Pochopte mieru konverzie a odchodu používateľov.", + "label.funnels": "Lieviky", + "label.goal": "Cieľ", + "label.goals": "Ciele", + "label.goals-description": "Sledujte svoje ciele pre zobrazenia stránok a udalosti.", + "label.greater-than": "Väčšie ako", + "label.greater-than-equals": "Väčšie alebo rovné", + "label.grouped": "Zoskupené", + "label.hostname": "Názov hostiteľa", + "label.includes": "Zahŕňa", + "label.insight": "Prehľad", "label.insights": "Insights", "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", - "label.language": "Language", - "label.languages": "Languages", + "label.is": "Je", + "label.is-false": "Je nepravda", + "label.is-not": "Nie je", + "label.is-not-set": "Nie je nastavené", + "label.is-set": "Nastavené", + "label.is-true": "Je pravda", + "label.join": "Pripojiť sa", + "label.join-team": "Pripojiť sa k tímu", + "label.journey": "Cesta", + "label.journey-description": "Pochopte, ako používatelia prechádzajú vaším webom.", + "label.journeys": "Cesty", + "label.language": "Jazyk", + "label.languages": "Jazyky", "label.laptop": "Prenosný počítač", - "label.last-click": "Last click", + "label.last-click": "Posledné kliknutie", "label.last-days": "Posledných {x} dní", "label.last-hours": "Posledných {x} hodín", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "Posledných {x} mesiacov", + "label.last-seen": "Naposledy videné", + "label.leave": "Odísť", + "label.leave-team": "Opustiť tím", + "label.less-than": "Menej ako", + "label.less-than-equals": "Menej alebo rovné", + "label.links": "Odkazy", "label.login": "Prihlásiť", "label.logout": "Odhlásiť", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.manage": "Spravovať", + "label.manager": "Manažér", + "label.max": "Maximum", + "label.medium": "Stredný", + "label.member": "Člen", + "label.members": "Členovia", + "label.min": "Minimum", "label.mobile": "Mobilný telefon", "label.model": "Model", "label.more": "Viac", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "Môj účet", + "label.my-websites": "Moje weby", "label.name": "Meno", "label.new-password": "Nové heslo", - "label.none": "None", + "label.none": "Žiadny", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organické vyhľadávanie", + "label.organic-shopping": "Organické nakupovanie", + "label.organic-social": "Organické sociálne siete", + "label.organic-video": "Organické video", "label.os": "OS", - "label.other": "Other", + "label.other": "Iné", "label.overview": "Overview", "label.owner": "Owner", - "label.page": "Page", + "label.page": "Stránka", "label.page-of": "Page {current} of {total}", "label.page-views": "Zobrazenie stánok", "label.pageTitle": "Page title", "label.pages": "Stránky", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Platené reklamy", + "label.paid-search": "Platené vyhľadávanie", + "label.paid-shopping": "Platené nakupovanie", + "label.paid-social": "Platené sociálne siete", + "label.paid-video": "Platené video", "label.password": "Heslo", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Cesta", + "label.paths": "Cesty", + "label.pixels": "Pixely", "label.powered-by": "Powered by {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "Predchádzajúci", + "label.previous-period": "Predchádzajúce obdobie", + "label.previous-year": "Predchádzajúci rok", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Vlastnosti", + "label.property": "Vlastnosť", "label.queries": "Queries", "label.query": "Query", "label.query-parameters": "Query parameters", "label.realtime": "Aktuálne", - "label.referral": "Referral", + "label.referral": "Odporúčanie", "label.referrer": "Referrer", "label.referrers": "Odkazy", "label.refresh": "Obnoviť", "label.regenerate": "Regenerate", "label.region": "Region", "label.regions": "Regions", - "label.remaining": "Remaining", + "label.remaining": "Zostáva", "label.remove": "Remove", "label.remove-member": "Remove member", "label.reports": "Reports", @@ -209,8 +209,8 @@ "label.reset-website": "Reset statistics", "label.retention": "Retention", "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Príjem", + "label.revenue-description": "Pozrite si svoj príjem v priebehu času.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Uložiť", @@ -218,35 +218,35 @@ "label.search": "Search", "label.select": "Select", "label.select-date": "Select date", - "label.select-filter": "Select filter", + "label.select-filter": "Vybrať filter", "label.select-role": "Select role", "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Sedenie", + "label.session-data": "Dáta sedenia", "label.sessions": "Sessions", "label.settings": "Nastavenia", - "label.share": "Share", + "label.share": "Zdieľať", "label.share-url": "Zdielanie URL", "label.single-day": "Jeden deň", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Zdroje", "label.start-step": "Start Step", "label.steps": "Steps", "label.sum": "Sum", "label.tablet": "Tablet", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Značka", + "label.tags": "Značky", "label.team": "Team", "label.team-id": "Team ID", - "label.team-manager": "Team manager", + "label.team-manager": "Manažér tímu", "label.team-member": "Team member", "label.team-name": "Team name", "label.team-owner": "Team owner", - "label.team-settings": "Team settings", + "label.team-settings": "Nastavenia tímu", "label.team-view-only": "Team view only", "label.team-websites": "Team websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Podmienky", "label.theme": "Theme", "label.this-month": "Tento mesiac", "label.this-week": "Tento týždeň", diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index 6f5b5f51..48599bf4 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -3,47 +3,47 @@ "label.actions": "Dejanja", "label.activity": "Dnevnik dejavnosti", "label.add": "Dodaj", - "label.add-board": "Add board", + "label.add-board": "Dodaj tablo", "label.add-description": "Dodaj opis", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.add-member": "Dodaj člana", + "label.add-step": "Dodaj korak", "label.add-website": "Dodaj spletno mesto", "label.admin": "Administrator", - "label.affiliate": "Affiliate", + "label.affiliate": "Partner", "label.after": "Po", "label.all": "Vsi", "label.all-time": "Ves čas", "label.analytics": "Analitika", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Uporabi", + "label.attribution": "Pripis", + "label.attribution-description": "Oglejte si, kako uporabniki sodelujejo z vašim marketingom in kaj spodbuja konverzije.", "label.average": "Povprečno", "label.back": "Nazaj", "label.before": "Pred", - "label.boards": "Boards", + "label.boards": "Table", "label.bounce-rate": "Odbojna stopnja", "label.breakdown": "Razčlenitev", "label.browser": "Brskalnik", "label.browsers": "Brskalniki", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampanje", "label.cancel": "Prekliči", "label.change-password": "Zamenjaj geslo", - "label.channels": "Channels", + "label.channels": "Kanali", "label.cities": "Mesta", "label.city": "Mesto", "label.clear-all": "Počisti vse", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", + "label.cohort": "Kohorta", + "label.compare": "Primerjaj", + "label.compare-dates": "Primerjaj datume", "label.confirm": "Potrdi", "label.confirm-password": "Potrdi geslo", "label.contains": "Vsebuje", - "label.content": "Content", + "label.content": "Vsebina", "label.continue": "Nadaljuj", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "Konverzija", + "label.conversion-rate": "Stopnja konverzije", + "label.conversion-step": "Korak konverzije", + "label.count": "Števec", "label.countries": "Države", "label.country": "Država", "label.create": "Create", @@ -51,9 +51,9 @@ "label.create-team": "Ustvari ekipo", "label.create-user": "Ustvari uporabnika", "label.created": "Ustvarjeno", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.created-by": "Ustvaril", + "label.currency": "Valuta", + "label.current": "Trenutno", "label.current-password": "Trenutno geslo", "label.custom-range": "Obdobje po meri", "label.dashboard": "Nadzorna plošča", @@ -63,7 +63,7 @@ "label.day": "Dan", "label.default-date-range": "Privzeto časovno obdobje", "label.delete": "Izbriši", - "label.delete-report": "Delete report", + "label.delete-report": "Izbriši poročilo", "label.delete-team": "Izbriši ekipo", "label.delete-user": "Izbriši uporabnika", "label.delete-website": "Izbriši spletno mesto", @@ -72,28 +72,28 @@ "label.details": "Podrobnosti", "label.device": "Naprava", "label.devices": "Naprave", - "label.direct": "Direct", + "label.direct": "Neposredno", "label.dismiss": "Prezri", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Unikatni ID", "label.does-not-contain": "Ne vsebuje", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Ne vključuje", + "label.doest-not-exist": "Ne obstaja", "label.domain": "Domena", "label.dropoff": "Zapustitev", "label.edit": "Uredi", "label.edit-dashboard": "Uredi nadzorno ploščo", - "label.edit-member": "Edit member", + "label.edit-member": "Uredi člana", "label.email": "Email", "label.enable-share-url": "Uredi povezavo za deljenje", - "label.end-step": "End Step", - "label.entry": "Entry URL", + "label.end-step": "Končni korak", + "label.entry": "Vhodni URL", "label.event": "Dogodek", "label.event-data": "Podatki dogodka", - "label.event-name": "Event name", + "label.event-name": "Ime dogodka", "label.events": "Dogodki", - "label.exists": "Exists", + "label.exists": "Obstaja", "label.exit": "Exit URL", - "label.expand": "Expand", + "label.expand": "Razširi", "label.false": "Napačno", "label.field": "Polje", "label.fields": "Polja", @@ -101,106 +101,106 @@ "label.filter-combined": "Skupaj", "label.filter-raw": "Neobdelano", "label.filters": "Filtri", - "label.first-click": "First click", + "label.first-click": "Prvi klik", "label.first-seen": "First seen", "label.funnel": "Prodajni lijak", "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", + "label.funnels": "Lijaki", + "label.goal": "Cilj", + "label.goals": "Cilji", + "label.goals-description": "Spremljajte svoje cilje za oglede strani in dogodke.", "label.greater-than": "Večje od", "label.greater-than-equals": "Večje ali enako kot", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Združeno", + "label.hostname": "Ime gostitelja", + "label.includes": "Vključuje", + "label.insight": "Vpogled", "label.insights": "Vpogled", "label.insights-description": "Dive deeper into your data by using segments and filters.", "label.is": "Je", - "label.is-false": "Is false", + "label.is-false": "Je napačno", "label.is-not": "Ni", "label.is-not-set": "Ni nastavljeno", "label.is-set": "Je nastavljeno", - "label.is-true": "Is true", + "label.is-true": "Je res", "label.join": "Pridruži se", "label.join-team": "Pridruži se ekipi", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.journey": "Potovanje", + "label.journey-description": "Razumite, kako uporabniki krmarijo po vašem spletnem mestu.", + "label.journeys": "Potovanja", "label.language": "Jezik", "label.languages": "Jeziki", "label.laptop": "Prenosni računalnik", - "label.last-click": "Last click", + "label.last-click": "Zadnji klik", "label.last-days": "Zadnjih {x} dni", "label.last-hours": "Zadnjih {x} ur", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", + "label.last-months": "Zadnjih {x} mesecev", + "label.last-seen": "Zadnjič videno", "label.leave": "Zapusti", "label.leave-team": "Zapusti ekipo", "label.less-than": "Manjše kot", "label.less-than-equals": "Manjše ali enako kot", - "label.links": "Links", + "label.links": "Povezave", "label.login": "Prijava", "label.logout": "Odjava", "label.manage": "Manage", "label.manager": "Manager", "label.max": "Največ", - "label.medium": "Medium", - "label.member": "Member", + "label.medium": "Srednje", + "label.member": "Član", "label.members": "Člani", "label.min": "Najmanj", "label.mobile": "Mobilne naprave", "label.model": "Model", "label.more": "Več", - "label.my-account": "My account", + "label.my-account": "Moj račun", "label.my-websites": "Moja spletna mesta", "label.name": "Ime", "label.new-password": "Novo geslo", - "label.none": "Brez", + "label.none": "Noben", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organsko iskanje", + "label.organic-shopping": "Organski nakupi", + "label.organic-social": "Organska družbena omrežja", + "label.organic-video": "Organski video", "label.os": "OS", - "label.other": "Other", + "label.other": "Drugo", "label.overview": "Pregled", "label.owner": "Lastnik", - "label.page": "Page", + "label.page": "Stran", "label.page-of": "Stran {current} od {total}", "label.page-views": "Obiski strani", "label.pageTitle": "Naslov strani", "label.pages": "Strani", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Plačani oglasi", + "label.paid-search": "Plačano iskanje", + "label.paid-shopping": "Plačani nakupi", + "label.paid-social": "Plačana družbena omrežja", + "label.paid-video": "Plačani video", "label.password": "Geslo", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Pot", + "label.paths": "Poti", + "label.pixels": "Pikslov", "label.powered-by": "Poganja {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "Prejšnji", + "label.previous-period": "Prejšnje obdobje", + "label.previous-year": "Prejšnje leto", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Lastnosti", + "label.property": "Lastnost", "label.queries": "Poizvedbe", "label.query": "Poizvedba", "label.query-parameters": "Parametri poizvedbe", "label.realtime": "V živo", - "label.referral": "Referral", + "label.referral": "Napoten", "label.referrer": "Vir", "label.referrers": "Viri", "label.refresh": "Osveži", "label.regenerate": "Ponovno generiraj", "label.region": "Regija", "label.regions": "Regije", - "label.remaining": "Remaining", + "label.remaining": "Preostalo", "label.remove": "Odstrani", "label.remove-member": "Remove member", "label.reports": "Poročila", @@ -209,8 +209,8 @@ "label.reset-website": "Ponastavi statistiko", "label.retention": "Ohranjanje uporabnikov", "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Prihodek", + "label.revenue-description": "Oglejte si svoj prihodek skozi čas.", "label.role": "Vloga", "label.run-query": "Izvedi poizvedbo", "label.save": "Shrani", @@ -218,35 +218,35 @@ "label.search": "Search", "label.select": "Select", "label.select-date": "Izberi datum", - "label.select-filter": "Select filter", + "label.select-filter": "Izberi filter", "label.select-role": "Select role", "label.select-website": "Izberi spletno mesto", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Seja", + "label.session-data": "Podatki seje", "label.sessions": "Seje", "label.settings": "Nastavitve", - "label.share": "Share", + "label.share": "Deli", "label.share-url": "Deli povezavo", "label.single-day": "En dan", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Viri", "label.start-step": "Start Step", "label.steps": "Steps", "label.sum": "Seštevek", "label.tablet": "Tablični računalnik", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Oznaka", + "label.tags": "Oznake", "label.team": "Ekipa", "label.team-id": "ID ekipe", - "label.team-manager": "Team manager", + "label.team-manager": "Vodja ekipe", "label.team-member": "Član ekipe", "label.team-name": "Ime ekipe", "label.team-owner": "Lastnik ekipe", - "label.team-settings": "Team settings", + "label.team-settings": "Nastavitve ekipe", "label.team-view-only": "Team view only", "label.team-websites": "Spletna mesta ekipe", "label.teams": "Ekipe", - "label.terms": "Terms", + "label.terms": "Pogoji", "label.theme": "Tema", "label.this-month": "Ta mesec", "label.this-week": "Ta teden", diff --git a/src/lang/sv-SE.json b/src/lang/sv-SE.json index 27343909..8c7c96f2 100644 --- a/src/lang/sv-SE.json +++ b/src/lang/sv-SE.json @@ -3,47 +3,47 @@ "label.actions": "Händelser", "label.activity": "Aktivitetslogg", "label.add": "Lägg till", - "label.add-board": "Add board", + "label.add-board": "Lägg till anslagstavla", "label.add-description": "Lägg till beskrivning", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.add-member": "Lägg till medlem", + "label.add-step": "Lägg till steg", "label.add-website": "Lägg till webbplats", "label.admin": "Administratör", - "label.affiliate": "Affiliate", + "label.affiliate": "Partner", "label.after": "Efter", "label.all": "Alla", "label.all-time": "Sedan början", "label.analytics": "Webbplats Analys", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Tillämpa", + "label.attribution": "Attribuering", + "label.attribution-description": "Se hur användare interagerar med din marknadsföring och vad som driver konverteringar.", "label.average": "Genomsnitt", "label.back": "Tillbaka", "label.before": "Före", - "label.boards": "Boards", + "label.boards": "Anslagstavlor", "label.bounce-rate": "Avvisningsfrekvens", "label.breakdown": "Analys", "label.browser": "Webbläsare", "label.browsers": "Webbläsare", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampanjer", "label.cancel": "Avbryt", "label.change-password": "Byt lösenord", - "label.channels": "Channels", + "label.channels": "Kanaler", "label.cities": "Städer", "label.city": "Stad", "label.clear-all": "Rensa alla", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", + "label.cohort": "Kohort", + "label.compare": "Jämför", + "label.compare-dates": "Jämför datum", "label.confirm": "Bekräfta", "label.confirm-password": "Bekräfta lösenord", "label.contains": "Innehåller", - "label.content": "Content", + "label.content": "Innehåll", "label.continue": "Fortsätt", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "Konvertering", + "label.conversion-rate": "Konverteringsfrekvens", + "label.conversion-step": "Konverteringssteg", + "label.count": "Antal", "label.countries": "Länder", "label.country": "Land", "label.create": "Skapa", @@ -51,9 +51,9 @@ "label.create-team": "Skapa team", "label.create-user": "Skapa användare", "label.created": "Skapad", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.created-by": "Skapad av", + "label.currency": "Valuta", + "label.current": "Nuvarande", "label.current-password": "Nuvarande lösenord", "label.custom-range": "Anpassat urval", "label.dashboard": "Översikt", @@ -63,7 +63,7 @@ "label.day": "Dag", "label.default-date-range": "Standard datum-urval", "label.delete": "Radera", - "label.delete-report": "Delete report", + "label.delete-report": "Radera rapport", "label.delete-team": "Radera team", "label.delete-user": "Radera användare", "label.delete-website": "Radera webbplats", @@ -72,28 +72,28 @@ "label.details": "Detaljer", "label.device": "Enhet", "label.devices": "Enheter", - "label.direct": "Direct", + "label.direct": "Direkt", "label.dismiss": "Avbryt", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Unikt ID", "label.does-not-contain": "Innehåller inte", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Inkluderar inte", + "label.doest-not-exist": "Existerar inte", "label.domain": "Domän", "label.dropoff": "Bortfall", "label.edit": "Redigera", "label.edit-dashboard": "Redigera översikt", - "label.edit-member": "Edit member", + "label.edit-member": "Redigera medlem", "label.email": "Email", "label.enable-share-url": "Aktivera delningslänk", - "label.end-step": "End Step", - "label.entry": "Entry URL", + "label.end-step": "Slutsteg", + "label.entry": "Ingångs-URL", "label.event": "Händelse", "label.event-data": "Händelsedata", - "label.event-name": "Event name", + "label.event-name": "Händelsenamn", "label.events": "Händelser", - "label.exists": "Exists", + "label.exists": "Existerar", "label.exit": "Exit URL", - "label.expand": "Expand", + "label.expand": "Expandera", "label.false": "Falskt", "label.field": "Fält", "label.fields": "Fältar", @@ -101,106 +101,106 @@ "label.filter-combined": "Kombinerade", "label.filter-raw": "Rådata", "label.filters": "Filter", - "label.first-click": "First click", + "label.first-click": "Första klicket", "label.first-seen": "First seen", "label.funnel": "Funnel", "label.funnel-description": "Förstå omvandlingen och bortfallsfrekvensen för användare.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", + "label.funnels": "Trattar", + "label.goal": "Mål", + "label.goals": "Mål", + "label.goals-description": "Följ dina mål för sidvisningar och händelser.", "label.greater-than": "Större än", "label.greater-than-equals": "Större än eller lika med", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Grupperad", + "label.hostname": "Värdnamn", + "label.includes": "Inkluderar", + "label.insight": "Insikt", "label.insights": "Insikter", "label.insights-description": "Dyk djupare in i din data genom att använda olika segment och filter.", "label.is": "Är", - "label.is-false": "Is false", + "label.is-false": "Är falskt", "label.is-not": "Är inte", "label.is-not-set": "Är inte inställd", "label.is-set": "Är inställd", - "label.is-true": "Is true", + "label.is-true": "Är sant", "label.join": "Gå med", "label.join-team": "Gå med i team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.journey": "Resa", + "label.journey-description": "Förstå hur användare navigerar på din webbplats.", + "label.journeys": "Resor", "label.language": "Språk", "label.languages": "Språk", "label.laptop": "Bärbar", - "label.last-click": "Last click", + "label.last-click": "Sista klicket", "label.last-days": "Senaste {x} dagarna", "label.last-hours": "Senaste {x} timmarna", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", + "label.last-months": "Senaste {x} månaderna", + "label.last-seen": "Senast sedd", "label.leave": "Lämna", "label.leave-team": "Lämna team", "label.less-than": "Mindre än", "label.less-than-equals": "Mindre än eller lika med", - "label.links": "Links", + "label.links": "Länkar", "label.login": "Logga in", "label.logout": "Logga ut", "label.manage": "Manage", "label.manager": "Manager", "label.max": "Max", "label.medium": "Medium", - "label.member": "Member", + "label.member": "Medlem", "label.members": "Medlemmar", "label.min": "Min", "label.mobile": "Mobil", - "label.model": "Model", + "label.model": "Modell", "label.more": "Mer", - "label.my-account": "My account", + "label.my-account": "Mitt konto", "label.my-websites": "Mina webbplatser", "label.name": "Namn", "label.new-password": "Nytt lösenord", - "label.none": "Inga", + "label.none": "Ingen", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organisk sökning", + "label.organic-shopping": "Organisk shopping", + "label.organic-social": "Organisk social", + "label.organic-video": "Organisk video", "label.os": "Operativsystem", - "label.other": "Other", + "label.other": "Annat", "label.overview": "Översikt", "label.owner": "Ägare", - "label.page": "Page", + "label.page": "Sida", "label.page-of": "Sida {current} av {total}", "label.page-views": "Sidvisningar", "label.pageTitle": "Sidtitel", "label.pages": "Sidor", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Betalda annonser", + "label.paid-search": "Betald sökning", + "label.paid-shopping": "Betald shopping", + "label.paid-social": "Betald social", + "label.paid-video": "Betald video", "label.password": "Lösenord", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Sökväg", + "label.paths": "Sökvägar", + "label.pixels": "Pixlar", "label.powered-by": "Drivs av {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "Föregående", + "label.previous-period": "Föregående period", + "label.previous-year": "Föregående år", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Egenskaper", + "label.property": "Egenskap", "label.queries": "Frågor", "label.query": "Fråga", "label.query-parameters": "Frågeparametrar", "label.realtime": "Realtid", - "label.referral": "Referral", + "label.referral": "Hänvisning", "label.referrer": "Hänvisare", "label.referrers": "Hänvisare", "label.refresh": "Uppdatera", "label.regenerate": "Förnya", "label.region": "Region", "label.regions": "Regioner", - "label.remaining": "Remaining", + "label.remaining": "Återstår", "label.remove": "Ta bort", "label.remove-member": "Remove member", "label.reports": "Rapporter", @@ -209,8 +209,8 @@ "label.reset-website": "Återställ webbplats", "label.retention": "Retention", "label.retention-description": "Mät din webbplats engagemang genom att följa hur ofta användare återvänder.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Intäkter", + "label.revenue-description": "Se dina intäkter över tid.", "label.role": "Roll", "label.run-query": "Kör sökning", "label.save": "Spara", @@ -218,35 +218,35 @@ "label.search": "Sök", "label.select": "Select", "label.select-date": "Välj datum", - "label.select-filter": "Select filter", + "label.select-filter": "Välj filter", "label.select-role": "Select role", "label.select-website": "Välj webbplats", "label.session": "Session", - "label.session-data": "Session data", + "label.session-data": "Sessionsdata", "label.sessions": "Sessioner", "label.settings": "Inställningar", - "label.share": "Share", + "label.share": "Dela", "label.share-url": "Delningslänk", "label.single-day": "En dag", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Källor", "label.start-step": "Start Step", "label.steps": "Steps", "label.sum": "Summa", "label.tablet": "Surfplatta", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Tagg", + "label.tags": "Taggar", "label.team": "Team", "label.team-id": "Team ID", - "label.team-manager": "Team manager", + "label.team-manager": "Teamledare", "label.team-member": "Team-medlem", "label.team-name": "Team namn", "label.team-owner": "Team-ägare", - "label.team-settings": "Team settings", + "label.team-settings": "Teaminställningar", "label.team-view-only": "Team view only", "label.team-websites": "Team webbplatser", "label.teams": "Team", - "label.terms": "Terms", + "label.terms": "Villkor", "label.theme": "Tema", "label.this-month": "Denna månad", "label.this-week": "Denna vecka", diff --git a/src/lang/ta-IN.json b/src/lang/ta-IN.json index f1e3e18e..652b00cd 100644 --- a/src/lang/ta-IN.json +++ b/src/lang/ta-IN.json @@ -41,7 +41,7 @@ "label.content": "Content", "label.continue": "Continue", "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", + "label.conversion-rate": "Conversion rate", "label.conversion-step": "Conversion step", "label.count": "Count", "label.countries": "நாடுகள்", diff --git a/src/lang/th-TH.json b/src/lang/th-TH.json index 0e69f451..694870b8 100644 --- a/src/lang/th-TH.json +++ b/src/lang/th-TH.json @@ -41,7 +41,7 @@ "label.content": "Content", "label.continue": "Continue", "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", + "label.conversion-rate": "Conversion rate", "label.conversion-step": "Conversion step", "label.count": "Count", "label.countries": "ประเทศ", diff --git a/src/lang/tr-TR.json b/src/lang/tr-TR.json index 69c6c834..722a5ced 100644 --- a/src/lang/tr-TR.json +++ b/src/lang/tr-TR.json @@ -3,47 +3,47 @@ "label.actions": "Hareketler", "label.activity": "Aktivite Kaydı", "label.add": "Ekle", - "label.add-board": "Add board", + "label.add-board": "Pano ekle", "label.add-description": "Açıklama ekle", "label.add-member": "Üye ekle", "label.add-step": "Adım ekle", "label.add-website": "Web sitesi ekle", "label.admin": "Administrator", - "label.affiliate": "Affiliate", + "label.affiliate": "Ortak", "label.after": "Sonra", "label.all": "Tümü", "label.all-time": "Tüm zamanlar", "label.analytics": "Analitik", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Uygula", + "label.attribution": "Atıf", + "label.attribution-description": "Kullanıcıların pazarlamanızla nasıl etkileşime girdiğini ve dönüşümleri neyin tetiklediğini görün.", "label.average": "Ortalama", "label.back": "Geri", "label.before": "Önce", - "label.boards": "Boards", + "label.boards": "Panolar", "label.bounce-rate": "Tek sayfa ziyaret oranı", "label.breakdown": "Dağılım", "label.browser": "Tarayıcı", "label.browsers": "Tarayıcılar", - "label.campaigns": "Campaigns", + "label.campaigns": "Kampanyalar", "label.cancel": "İptal", "label.change-password": "Şifre değiştir", - "label.channels": "Channels", + "label.channels": "Kanallar", "label.cities": "Şehirler", "label.city": "Şehir", "label.clear-all": "Hepsini temizle", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", + "label.cohort": "Kohort", + "label.compare": "Karşılaştır", + "label.compare-dates": "Tarihleri karşılaştır", "label.confirm": "Onayla", "label.confirm-password": "Parolayı onayla", "label.contains": "İçeriği", - "label.content": "Content", + "label.content": "İçerik", "label.continue": "Devam et", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "Dönüşüm", + "label.conversion-rate": "Dönüşüm oranı", + "label.conversion-step": "Dönüşüm adımı", + "label.count": "Adet", "label.countries": "Ülkeler", "label.country": "Ülke", "label.create": "Oluştur", @@ -52,8 +52,8 @@ "label.create-user": "Kullanıcı oluştur", "label.created": "Oluşturuldu", "label.created-by": "Tarafından oluşturldu", - "label.currency": "Currency", - "label.current": "Current", + "label.currency": "Para birimi", + "label.current": "Mevcut", "label.current-password": "Mevcut parola", "label.custom-range": "Özelleştirilmiş aralık", "label.dashboard": "Kontrol Paneli", @@ -72,12 +72,12 @@ "label.details": "Detaylar", "label.device": "Cihaz", "label.devices": "Cihazlar", - "label.direct": "Direct", + "label.direct": "Doğrudan", "label.dismiss": "Reddet", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Benzersiz ID", "label.does-not-contain": "İçermez", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "İçermiyor", + "label.doest-not-exist": "Mevcut değil", "label.domain": "Alan adı", "label.dropoff": "Bırakma", "label.edit": "Düzenle", @@ -89,11 +89,11 @@ "label.entry": "Entry URL", "label.event": "Olay", "label.event-data": "Olay verisi", - "label.event-name": "Event name", + "label.event-name": "Olay adı", "label.events": "Olaylar", - "label.exists": "Exists", + "label.exists": "Mevcut", "label.exit": "Exit URL", - "label.expand": "Expand", + "label.expand": "Genişlet", "label.false": "Yanlış", "label.field": "Alan", "label.fields": "Alanlar", @@ -101,52 +101,52 @@ "label.filter-combined": "Birleşik filtre", "label.filter-raw": "Ham filtre", "label.filters": "Filtreler", - "label.first-click": "First click", + "label.first-click": "İlk tıklama", "label.first-seen": "First seen", "label.funnel": "Huni", "label.funnel-description": "Kullanıcıların dönüşüm ve ayrılma oranlarını anlayın.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", + "label.funnels": "Huniler", + "label.goal": "Hedef", + "label.goals": "Hedefler", + "label.goals-description": "Sayfa görüntüleme ve olaylar için hedeflerinizi takip edin.", "label.greater-than": "Büyüktür", "label.greater-than-equals": "Büyük veya eşittir", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Gruplandırılmış", + "label.hostname": "Sunucu adı", + "label.includes": "İçerir", + "label.insight": "İçgörü", "label.insights": "Insights", "label.insights-description": "Segmentleri ve filtreleri kullanarak verilerinizi derinlemesine inceleyin.", "label.is": "Is", - "label.is-false": "Is false", + "label.is-false": "Yanlış", "label.is-not": "Değil", "label.is-not-set": "Ayarlanmamış", "label.is-set": "Ayarlandı", - "label.is-true": "Is true", + "label.is-true": "Doğru", "label.join": "Katıl", "label.join-team": "Takıma katıl", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.journey": "Yolculuk", + "label.journey-description": "Kullanıcıların sitenizde nasıl gezindiğini anlayın.", + "label.journeys": "Yolculuklar", "label.language": "Dil", "label.languages": "Diller", "label.laptop": "Dizüstü", - "label.last-click": "Last click", + "label.last-click": "Son tıklama", "label.last-days": "Son {x} gün", "label.last-hours": "Son {x} saat", "label.last-months": "Son {x} ay", - "label.last-seen": "Last seen", + "label.last-seen": "Son görüldü", "label.leave": "Ayrıl", "label.leave-team": "Takımdan Ayrıl", "label.less-than": "Küçüktür", "label.less-than-equals": "Küçük veya eşittir", - "label.links": "Links", + "label.links": "Bağlantılar", "label.login": "Giriş Yap", "label.logout": "Çıkış Yap", "label.manage": "Yönet", "label.manager": "Manager", "label.max": "Max", - "label.medium": "Medium", + "label.medium": "Orta", "label.member": "Üye", "label.members": "Üyeler", "label.min": "Min", @@ -160,47 +160,47 @@ "label.none": "Yok", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "TAMAM", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Organik arama", + "label.organic-shopping": "Organik alışveriş", + "label.organic-social": "Organik sosyal", + "label.organic-video": "Organik video", "label.os": "OS", - "label.other": "Other", + "label.other": "Diğer", "label.overview": "Genel bakış", "label.owner": "Sahibi", - "label.page": "Page", + "label.page": "Sayfa", "label.page-of": "{total} sayfada {current} ", "label.page-views": "Sayfa görünümü", "label.pageTitle": "Sayfa başlığı", "label.pages": "Sayfalar", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Ücretli reklamlar", + "label.paid-search": "Ücretli arama", + "label.paid-shopping": "Ücretli alışveriş", + "label.paid-social": "Ücretli sosyal", + "label.paid-video": "Ücretli video", "label.password": "Parola", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Yol", + "label.paths": "Yollar", + "label.pixels": "Pikseller", "label.powered-by": "Sağlayıcı: {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "Önceki", + "label.previous-period": "Önceki dönem", + "label.previous-year": "Önceki yıl", "label.profile": "Profil", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Özellikler", + "label.property": "Özellik", "label.queries": "Sorgular", "label.query": "Sorgu", "label.query-parameters": "Sorgu parametreleri", "label.realtime": "Gerçek Zamanlı", - "label.referral": "Referral", + "label.referral": "Yönlendirme", "label.referrer": "Referrer", "label.referrers": "Yönlendirenler", "label.refresh": "Yenile", "label.regenerate": "Yeniden Oluştur", "label.region": "Bölge", "label.regions": "Bölgeler", - "label.remaining": "Remaining", + "label.remaining": "Kalan", "label.remove": "Kaldır", "label.remove-member": "Üyeyi kaldır", "label.reports": "Raporlar", @@ -209,8 +209,8 @@ "label.reset-website": "İstatistikleri sıfırla", "label.retention": "Geri dönüş", "label.retention-description": "Kullanıcıların ne sıklıkla geri döndüğünü takip ederek web sitenizin kalıcılığını ölçün.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Gelir", + "label.revenue-description": "Gelirinizi zaman içinde inceleyin.", "label.role": "Rol", "label.run-query": "Sorgu çalıştır", "label.save": "Kaydet", @@ -218,35 +218,35 @@ "label.search": "Ara", "label.select": "Seç", "label.select-date": "Tarih seç", - "label.select-filter": "Select filter", + "label.select-filter": "Filtre seç", "label.select-role": "Rol seç", "label.select-website": "Web sitesi seç", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Oturum", + "label.session-data": "Oturum verisi", "label.sessions": "Sessions", "label.settings": "Ayarlar", - "label.share": "Share", + "label.share": "Paylaş", "label.share-url": "Paylaşım adresi", "label.single-day": "Tekil gün", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Kaynaklar", "label.start-step": "Start Step", "label.steps": "Adımlar", "label.sum": "Toplam", "label.tablet": "Tablet", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Etiket", + "label.tags": "Etiketler", "label.team": "Takım", "label.team-id": "Takım ID", - "label.team-manager": "Team manager", + "label.team-manager": "Takım yöneticisi", "label.team-member": "Takım üyesi", "label.team-name": "Takım ismi", "label.team-owner": "Takım sahibi", - "label.team-settings": "Team settings", + "label.team-settings": "Takım ayarları", "label.team-view-only": "Yalnızca ekip görünümü", "label.team-websites": "Takım web siteleri", "label.teams": "Takımlar", - "label.terms": "Terms", + "label.terms": "Koşullar", "label.theme": "Tema", "label.this-month": "Bu ay", "label.this-week": "Bu hafta", diff --git a/src/lang/uk-UA.json b/src/lang/uk-UA.json index b2309567..530d8818 100644 --- a/src/lang/uk-UA.json +++ b/src/lang/uk-UA.json @@ -3,47 +3,47 @@ "label.actions": "Дії", "label.activity": "Журнал", "label.add": "Додати", - "label.add-board": "Add board", + "label.add-board": "Додати дошку", "label.add-description": "Додати опис", "label.add-member": "Додати учасника", "label.add-step": "Додати крок", "label.add-website": "Додати сайт", "label.admin": "Адміністратор", - "label.affiliate": "Affiliate", + "label.affiliate": "Партнер", "label.after": "Після", "label.all": "Всі", "label.all-time": "Весь час", "label.analytics": "Аналітика", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "Застосувати", + "label.attribution": "Атрибуція", + "label.attribution-description": "Дивіться, як користувачі взаємодіють з вашим маркетингом і що сприяє конверсіям.", "label.average": "Середній", "label.back": "Назад", "label.before": "До", - "label.boards": "Boards", + "label.boards": "Дошки", "label.bounce-rate": "Показник відмов", "label.breakdown": "Розподіл", "label.browser": "Браузер", "label.browsers": "Браузери", - "label.campaigns": "Campaigns", + "label.campaigns": "Кампанії", "label.cancel": "Відмінити", "label.change-password": "Змінити пароль", - "label.channels": "Channels", + "label.channels": "Канали", "label.cities": "Міста", "label.city": "Місто", "label.clear-all": "Очистити все", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", + "label.cohort": "Когорта", + "label.compare": "Порівняти", + "label.compare-dates": "Порівняти дати", "label.confirm": "Підтвердити", "label.confirm-password": "Підтвердити пароль", "label.contains": "Містить", - "label.content": "Content", + "label.content": "Вміст", "label.continue": "Продовжити", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.conversion": "Конверсія", + "label.conversion-rate": "Рівень конверсії", + "label.conversion-step": "Крок конверсії", + "label.count": "Кількість", "label.countries": "Країни", "label.country": "Країна", "label.create": "Створити", @@ -52,8 +52,8 @@ "label.create-user": "Створити користувача", "label.created": "Створено", "label.created-by": "Створено", - "label.currency": "Currency", - "label.current": "Current", + "label.currency": "Валюта", + "label.current": "Поточний", "label.current-password": "Поточний пароль", "label.custom-range": "Довільний період", "label.dashboard": "Інформаційна панель", @@ -72,28 +72,28 @@ "label.details": "Деталі", "label.device": "Пристрій", "label.devices": "Пристрої", - "label.direct": "Direct", + "label.direct": "Прямий", "label.dismiss": "Відхилити", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "Унікальний ID", "label.does-not-contain": "Не містить", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "Не включає", + "label.doest-not-exist": "Не існує", "label.domain": "Домен", "label.dropoff": "Відсів", "label.edit": "Редагувати", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", + "label.edit-dashboard": "Редагувати панель", + "label.edit-member": "Редагувати учасника", "label.email": "Email", - "label.enable-share-url": "Enable share URL", - "label.end-step": "End Step", - "label.entry": "Entry URL", + "label.enable-share-url": "Увімкнути спільне посилання", + "label.end-step": "Кінцевий крок", + "label.entry": "Вхідний URL", "label.event": "Подія", "label.event-data": "Дані події", - "label.event-name": "Event name", + "label.event-name": "Назва події", "label.events": "Події", - "label.exists": "Exists", + "label.exists": "Існує", "label.exit": "Exit URL", - "label.expand": "Expand", + "label.expand": "Розгорнути", "label.false": "False", "label.field": "Поле", "label.fields": "Поля", @@ -101,57 +101,57 @@ "label.filter-combined": "Об'єднані", "label.filter-raw": "Сирі дані", "label.filters": "Фільтри", - "label.first-click": "First click", + "label.first-click": "Перший клік", "label.first-seen": "First seen", "label.funnel": "Воронка", "label.funnel-description": "Зрозуміти рівень конверсії та відсіву користувачів.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", + "label.funnels": "Воронки", + "label.goal": "Мета", + "label.goals": "Мети", + "label.goals-description": "Відстежуйте свої цілі для переглядів сторінок і подій.", "label.greater-than": "Більше ніж", "label.greater-than-equals": "Більше або рівно", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "Груповано", + "label.hostname": "Ім'я хоста", + "label.includes": "Включає", + "label.insight": "Інсайт", "label.insights": "Інсайти", "label.insights-description": "Зануртеся глибше у свої дані за допомогою сегментів та фільтрів.", "label.is": "Є", - "label.is-false": "Is false", + "label.is-false": "Хибно", "label.is-not": "Не є", "label.is-not-set": "Не встановлено", "label.is-set": "Встановлено", - "label.is-true": "Is true", + "label.is-true": "Правдиво", "label.join": "Приєднатись", "label.join-team": "Приєднатись до команди", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", + "label.journey": "Шлях", + "label.journey-description": "Зрозумійте, як користувачі переміщаються вашим сайтом.", + "label.journeys": "Шляхи", "label.language": "Мова", "label.languages": "Мови", "label.laptop": "Ноутбук", - "label.last-click": "Last click", + "label.last-click": "Останній клік", "label.last-days": "Останні {x} днів", "label.last-hours": "Останні {x} годин", "label.last-months": "Останні {x} місяців", - "label.last-seen": "Last seen", + "label.last-seen": "Останній перегляд", "label.leave": "Покинути", "label.leave-team": "Покинути команду", "label.less-than": "Менше ніж", "label.less-than-equals": "Менше або дорівнює", - "label.links": "Links", + "label.links": "Посилання", "label.login": "Увійти", "label.logout": "Вийти", "label.manage": "Керувати", "label.manager": "Manager", "label.max": "Макс.", - "label.medium": "Medium", + "label.medium": "Середній", "label.member": "Учасник", "label.members": "Учасники", "label.min": "Мін.", "label.mobile": "Мобільний", - "label.model": "Model", + "label.model": "Модель", "label.more": "Більше", "label.my-account": "Мій обліковий запис", "label.my-websites": "Мої сайти", @@ -160,47 +160,47 @@ "label.none": "Нічого", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Органічний пошук", + "label.organic-shopping": "Органічні покупки", + "label.organic-social": "Органічні соцмережі", + "label.organic-video": "Органічне відео", "label.os": "ОС", - "label.other": "Other", + "label.other": "Інше", "label.overview": "Огляд", "label.owner": "Власник", - "label.page": "Page", + "label.page": "Сторінка", "label.page-of": "Сторінка {current} з {total}", "label.page-views": "Перегляди сторінок", "label.pageTitle": "Заголовок сторінки", "label.pages": "Сторінки", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Платна реклама", + "label.paid-search": "Платний пошук", + "label.paid-shopping": "Платні покупки", + "label.paid-social": "Платні соцмережі", + "label.paid-video": "Платне відео", "label.password": "Пароль", "label.path": "Path", "label.paths": "Paths", - "label.pixels": "Pixels", + "label.pixels": "Пікселі", "label.powered-by": "На базі {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "Попередній", + "label.previous-period": "Попередній період", + "label.previous-year": "Попередній рік", "label.profile": "Профіль", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Властивості", + "label.property": "Властивість", "label.queries": "Запити", "label.query": "Запит", "label.query-parameters": "Параметри запиту", "label.realtime": "У реальному часі", - "label.referral": "Referral", + "label.referral": "Реферал", "label.referrer": "Джерело", "label.referrers": "Джерела", "label.refresh": "Оновити", "label.regenerate": "Згенерувати знову", "label.region": "Регіон", "label.regions": "Регіони", - "label.remaining": "Remaining", + "label.remaining": "Залишилось", "label.remove": "Видалити", "label.remove-member": "Видалити користувача", "label.reports": "Звіти", @@ -209,8 +209,8 @@ "label.reset-website": "Скинути статистику сайту", "label.retention": "Липкість", "label.retention-description": "Виміряйте липкість вашого сайту, відстежуючи, як часто користувачі повертаються на нього.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Дохід", + "label.revenue-description": "Перегляньте свій дохід за певний період.", "label.role": "Роль", "label.run-query": "Виконати запит", "label.save": "Зберегти", @@ -218,35 +218,35 @@ "label.search": "Пошук", "label.select": "Вибрати", "label.select-date": "Вибрати дату", - "label.select-filter": "Select filter", + "label.select-filter": "Вибрати фільтр", "label.select-role": "Вибрати роль", "label.select-website": "Вибрати сайт", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Сесія", + "label.session-data": "Дані сесії", "label.sessions": "Сесії", "label.settings": "Налаштування", - "label.share": "Share", + "label.share": "Поділитися", "label.share-url": "Поділитися посилання", "label.single-day": "Один день", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Джерела", "label.start-step": "Start Step", "label.steps": "Кроки", "label.sum": "Сума", "label.tablet": "Планшет", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "Тег", + "label.tags": "Теги", "label.team": "Команда", "label.team-id": "Ідентифікатор команди", - "label.team-manager": "Team manager", + "label.team-manager": "Менеджер команди", "label.team-member": "Учасник команди", "label.team-name": "Назва команди", "label.team-owner": "Власник команди", - "label.team-settings": "Team settings", + "label.team-settings": "Налаштування команди", "label.team-view-only": "Тільки для командного перегляду", "label.team-websites": "Сайти команди", "label.teams": "Команди", - "label.terms": "Terms", + "label.terms": "Умови", "label.theme": "Тема", "label.this-month": "Цього місяця", "label.this-week": "Цього тижня", diff --git a/src/lang/ur-PK.json b/src/lang/ur-PK.json index 421d997a..f9ad263c 100644 --- a/src/lang/ur-PK.json +++ b/src/lang/ur-PK.json @@ -41,7 +41,7 @@ "label.content": "Content", "label.continue": "Continue", "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", + "label.conversion-rate": "Conversion rate", "label.conversion-step": "Conversion step", "label.count": "Count", "label.countries": "ممالک", diff --git a/src/lang/vi-VN.json b/src/lang/vi-VN.json index e7369299..2e274177 100644 --- a/src/lang/vi-VN.json +++ b/src/lang/vi-VN.json @@ -1,206 +1,206 @@ { - "label.access-code": "Access code", + "label.access-code": "Mã truy cập", "label.actions": "Hành động", - "label.activity": "Activity log", - "label.add": "Add", - "label.add-board": "Add board", - "label.add-description": "Add description", - "label.add-member": "Add member", - "label.add-step": "Add step", + "label.activity": "Nhật ký hoạt động", + "label.add": "Thêm", + "label.add-board": "Thêm bảng", + "label.add-description": "Thêm mô tả", + "label.add-member": "Thêm thành viên", + "label.add-step": "Thêm bước", "label.add-website": "Thêm website", "label.admin": "Quản trị", - "label.affiliate": "Affiliate", - "label.after": "After", + "label.affiliate": "Liên kết", + "label.after": "Sau", "label.all": "Tất cả", "label.all-time": "Toàn thời gian", - "label.analytics": "Analytics", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", - "label.average": "Average", + "label.analytics": "Phân tích", + "label.apply": "Áp dụng", + "label.attribution": "Phân bổ", + "label.attribution-description": "Xem cách người dùng tương tác với tiếp thị của bạn và điều gì thúc đẩy chuyển đổi.", + "label.average": "Trung bình", "label.back": "Quay về", - "label.before": "Before", - "label.boards": "Boards", + "label.before": "Trước", + "label.boards": "Bảng", "label.bounce-rate": "Tỷ lệ thoát trang", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.breakdown": "Phân tích chi tiết", + "label.browser": "Trình duyệt", "label.browsers": "Trình duyệt", - "label.campaigns": "Campaigns", + "label.campaigns": "Chiến dịch", "label.cancel": "Huỷ bỏ", "label.change-password": "Đổi mật khẩu", - "label.channels": "Channels", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.cohort": "Cohort", - "label.compare": "Compare", - "label.compare-dates": "Compare dates", - "label.confirm": "Confirm", + "label.channels": "Kênh", + "label.cities": "Thành phố", + "label.city": "Thành phố", + "label.clear-all": "Xóa tất cả", + "label.cohort": "Nhóm người dùng", + "label.compare": "So sánh", + "label.compare-dates": "So sánh ngày", + "label.confirm": "Xác nhận", "label.confirm-password": "Xác nhận mật khẩu", - "label.contains": "Contains", - "label.content": "Content", - "label.continue": "Continue", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", - "label.count": "Count", + "label.contains": "Chứa", + "label.content": "Nội dung", + "label.continue": "Tiếp tục", + "label.conversion": "Chuyển đổi", + "label.conversion-rate": "Tỷ lệ chuyển đổi", + "label.conversion-step": "Bước chuyển đổi", + "label.count": "Số lượng", "label.countries": "Quốc gia", - "label.country": "Country", - "label.create": "Create", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", - "label.created-by": "Created By", - "label.currency": "Currency", - "label.current": "Current", + "label.country": "Quốc gia", + "label.create": "Tạo", + "label.create-report": "Tạo báo cáo", + "label.create-team": "Tạo nhóm", + "label.create-user": "Tạo người dùng", + "label.created": "Đã tạo", + "label.created-by": "Tạo bởi", + "label.currency": "Tiền tệ", + "label.current": "Hiện tại", "label.current-password": "Mật khẩu hiện tại", "label.custom-range": "Phạm vi ngày tuỳ chọn", "label.dashboard": "Bảng điều khiển", - "label.data": "Data", - "label.date": "Date", + "label.data": "Dữ liệu", + "label.date": "Ngày", "label.date-range": "Phạm vi ngày", - "label.day": "Day", + "label.day": "Ngày", "label.default-date-range": "Khoảng thời gian mặc định", "label.delete": "Xoá", - "label.delete-report": "Delete report", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-report": "Xóa báo cáo", + "label.delete-team": "Xóa nhóm", + "label.delete-user": "Xóa người dùng", "label.delete-website": "Xóa website", - "label.description": "Description", + "label.description": "Mô tả", "label.desktop": "Máy bàn", - "label.details": "Details", - "label.device": "Device", + "label.details": "Chi tiết", + "label.device": "Thiết bị", "label.devices": "Thiết bị", - "label.direct": "Direct", + "label.direct": "Trực tiếp", "label.dismiss": "Loại trừ", - "label.distinct-id": "Distinct ID", - "label.does-not-contain": "Does not contain", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.distinct-id": "ID riêng biệt", + "label.does-not-contain": "Không chứa", + "label.does-not-include": "Không bao gồm", + "label.doest-not-exist": "Không tồn tại", "label.domain": "Tên miền", - "label.dropoff": "Dropoff", + "label.dropoff": "Rời bỏ", "label.edit": "Chỉnh sửa", - "label.edit-dashboard": "Edit dashboard", - "label.edit-member": "Edit member", + "label.edit-dashboard": "Chỉnh sửa bảng điều khiển", + "label.edit-member": "Chỉnh sửa thành viên", "label.email": "Email", "label.enable-share-url": "Bật khả năng chia sẻ URL", - "label.end-step": "End Step", - "label.entry": "Entry URL", - "label.event": "Event", - "label.event-data": "Event data", - "label.event-name": "Event name", + "label.end-step": "Bước kết thúc", + "label.entry": "URL vào", + "label.event": "Sự kiện", + "label.event-data": "Dữ liệu sự kiện", + "label.event-name": "Tên sự kiện", "label.events": "Sự kiện", - "label.exists": "Exists", - "label.exit": "Exit URL", - "label.expand": "Expand", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", - "label.filter": "Filter", + "label.exists": "Tồn tại", + "label.exit": "URL thoát", + "label.expand": "Mở rộng", + "label.false": "Sai", + "label.field": "Trường", + "label.fields": "Các trường", + "label.filter": "Bộ lọc", "label.filter-combined": "Kết hợp", "label.filter-raw": "Gốc", - "label.filters": "Filters", - "label.first-click": "First click", - "label.first-seen": "First seen", - "label.funnel": "Funnel", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", - "label.funnels": "Funnels", - "label.goal": "Goal", - "label.goals": "Goals", - "label.goals-description": "Track your goals for pageviews and events.", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.filters": "Bộ lọc", + "label.first-click": "Nhấp đầu tiên", + "label.first-seen": "Lần đầu thấy", + "label.funnel": "Phễu", + "label.funnel-description": "Hiểu tỷ lệ chuyển đổi và rời bỏ của người dùng.", + "label.funnels": "Phễu", + "label.goal": "Mục tiêu", + "label.goals": "Mục tiêu", + "label.goals-description": "Theo dõi mục tiêu lượt xem trang và sự kiện.", + "label.greater-than": "Lớn hơn", + "label.greater-than-equals": "Lớn hơn hoặc bằng", + "label.grouped": "Nhóm lại", + "label.hostname": "Tên máy chủ", + "label.includes": "Bao gồm", + "label.insight": "Thông tin chi tiết", "label.insights": "Insights", "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Is", - "label.is-false": "Is false", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", - "label.is-true": "Is true", - "label.join": "Join", - "label.join-team": "Join team", - "label.journey": "Journey", - "label.journey-description": "Understand how users navigate through your website.", - "label.journeys": "Journeys", - "label.language": "Language", + "label.is": "Là", + "label.is-false": "Sai", + "label.is-not": "Không là", + "label.is-not-set": "Chưa đặt", + "label.is-set": "Đã đặt", + "label.is-true": "Đúng", + "label.join": "Tham gia", + "label.join-team": "Tham gia nhóm", + "label.journey": "Hành trình", + "label.journey-description": "Hiểu cách người dùng di chuyển qua website của bạn.", + "label.journeys": "Hành trình", + "label.language": "Ngôn ngữ", "label.languages": "Ngôn ngữ", "label.laptop": "Laptop", - "label.last-click": "Last click", + "label.last-click": "Nhấp cuối cùng", "label.last-days": "{x} ngày gần nhất", "label.last-hours": "{x} giờ gần nhất", - "label.last-months": "Last {x} months", - "label.last-seen": "Last seen", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", - "label.links": "Links", + "label.last-months": "{x} tháng gần nhất", + "label.last-seen": "Lần cuối thấy", + "label.leave": "Rời đi", + "label.leave-team": "Rời nhóm", + "label.less-than": "Nhỏ hơn", + "label.less-than-equals": "Nhỏ hơn hoặc bằng", + "label.links": "Liên kết", "label.login": "Đăng nhập", "label.logout": "Đăng xuất", - "label.manage": "Manage", - "label.manager": "Manager", - "label.max": "Max", - "label.medium": "Medium", - "label.member": "Member", - "label.members": "Members", - "label.min": "Min", + "label.manage": "Quản lý", + "label.manager": "Quản lý viên", + "label.max": "Tối đa", + "label.medium": "Trung bình", + "label.member": "Thành viên", + "label.members": "Các thành viên", + "label.min": "Tối thiểu", "label.mobile": "Di động", - "label.model": "Model", + "label.model": "Mô hình", "label.more": "Thêm", - "label.my-account": "My account", - "label.my-websites": "My websites", + "label.my-account": "Tài khoản của tôi", + "label.my-websites": "Website của tôi", "label.name": "Tên", "label.new-password": "Mật khẩu mới", - "label.none": "None", + "label.none": "Không có", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "Tìm kiếm tự nhiên", + "label.organic-shopping": "Mua sắm tự nhiên", + "label.organic-social": "Mạng xã hội tự nhiên", + "label.organic-video": "Video tự nhiên", "label.os": "OS", - "label.other": "Other", + "label.other": "Khác", "label.overview": "Overview", "label.owner": "Chủ sở hữu", - "label.page": "Page", + "label.page": "Trang", "label.page-of": "Page {current} of {total}", "label.page-views": "Lượt xem", "label.pageTitle": "Page title", "label.pages": "Trang", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "Quảng cáo trả phí", + "label.paid-search": "Tìm kiếm trả phí", + "label.paid-shopping": "Mua sắm trả phí", + "label.paid-social": "Mạng xã hội trả phí", + "label.paid-video": "Video trả phí", "label.password": "Mật khẩu", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "Đường dẫn", + "label.paths": "Các đường dẫn", + "label.pixels": "Pixel", "label.powered-by": "Bản quyền thuộc về {name}", - "label.previous": "Previous", - "label.previous-period": "Previous period", - "label.previous-year": "Previous year", + "label.previous": "Trước đó", + "label.previous-period": "Giai đoạn trước", + "label.previous-year": "Năm trước", "label.profile": "Hồ sơ", - "label.properties": "Properties", - "label.property": "Property", + "label.properties": "Thuộc tính", + "label.property": "Thuộc tính", "label.queries": "Queries", "label.query": "Query", "label.query-parameters": "Query parameters", "label.realtime": "Thời gian thực", - "label.referral": "Referral", + "label.referral": "Giới thiệu", "label.referrer": "Referrer", "label.referrers": "Liên kết giới thiệu", "label.refresh": "Làm mới", "label.regenerate": "Regenerate", "label.region": "Region", "label.regions": "Regions", - "label.remaining": "Remaining", + "label.remaining": "Còn lại", "label.remove": "Remove", "label.remove-member": "Remove member", "label.reports": "Reports", @@ -209,8 +209,8 @@ "label.reset-website": "Tái thiết lập thống kê", "label.retention": "Retention", "label.retention-description": "Measure your website stickiness by tracking how often users return.", - "label.revenue": "Revenue", - "label.revenue-description": "Look into your revenue across time.", + "label.revenue": "Doanh thu", + "label.revenue-description": "Xem doanh thu của bạn theo thời gian.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Lưu", @@ -218,35 +218,35 @@ "label.search": "Search", "label.select": "Select", "label.select-date": "Select date", - "label.select-filter": "Select filter", + "label.select-filter": "Chọn bộ lọc", "label.select-role": "Select role", "label.select-website": "Select website", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "Phiên", + "label.session-data": "Dữ liệu phiên", "label.sessions": "Sessions", "label.settings": "Cài đặt", - "label.share": "Share", + "label.share": "Chia sẻ", "label.share-url": "Chia sẻ URL", "label.single-day": "Trong ngày", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "Nguồn", "label.start-step": "Start Step", "label.steps": "Steps", "label.sum": "Sum", "label.tablet": "Máy tính bảng", - "label.tag": "Tag", - "label.tags": "Tags", - "label.team": "Team", - "label.team-id": "Team ID", - "label.team-manager": "Team manager", - "label.team-member": "Team member", - "label.team-name": "Team name", - "label.team-owner": "Team owner", - "label.team-settings": "Team settings", + "label.tag": "Thẻ", + "label.tags": "Các thẻ", + "label.team": "Nhóm", + "label.team-id": "ID nhóm", + "label.team-manager": "Quản lý nhóm", + "label.team-member": "Thành viên nhóm", + "label.team-name": "Tên nhóm", + "label.team-owner": "Chủ nhóm", + "label.team-settings": "Cài đặt nhóm", "label.team-view-only": "Team view only", "label.team-websites": "Team websites", "label.teams": "Teams", - "label.terms": "Terms", + "label.terms": "Điều khoản", "label.theme": "Giao diện", "label.this-month": "Tháng này", "label.this-week": "Tuần này", diff --git a/src/lang/zh-CN.json b/src/lang/zh-CN.json index 4771627f..ffa10261 100644 --- a/src/lang/zh-CN.json +++ b/src/lang/zh-CN.json @@ -3,46 +3,46 @@ "label.actions": "用户行为", "label.activity": "活动日志", "label.add": "添加", - "label.add-board": "Add board", + "label.add-board": "添加看板", "label.add-description": "添加描述", "label.add-member": "添加成员", "label.add-step": "添加步骤", "label.add-website": "添加网站", "label.admin": "管理员", - "label.affiliate": "Affiliate", + "label.affiliate": "联盟", "label.after": "之后", "label.all": "所有", "label.all-time": "所有时间段", "label.analytics": "分析", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "应用", + "label.attribution": "归因", + "label.attribution-description": "查看用户如何与您的营销互动,以及是什么促成了转化。", "label.average": "平均", "label.back": "返回", "label.before": "之前", - "label.boards": "Boards", + "label.boards": "看板", "label.bounce-rate": "跳出率", "label.breakdown": "故障", "label.browser": "浏览器", "label.browsers": "浏览器", - "label.campaigns": "Campaigns", + "label.campaigns": "活动", "label.cancel": "取消", "label.change-password": "修改密码", "label.channels": "渠道", "label.cities": "市/县", "label.city": "市/县", "label.clear-all": "清除全部", - "label.cohort": "Cohort", + "label.cohort": "队列", "label.compare": "比较", - "label.compare-dates": "Compare dates", + "label.compare-dates": "比较日期", "label.confirm": "确认", "label.confirm-password": "确认密码", "label.contains": "包含", - "label.content": "Content", + "label.content": "内容", "label.continue": "继续", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "转化", + "label.conversion-rate": "转化率", + "label.conversion-step": "转化步骤", "label.count": "统计", "label.countries": "国家/地区", "label.country": "国家/地区", @@ -52,7 +52,7 @@ "label.create-user": "创建用户", "label.created": "已创建", "label.created-by": "创建者", - "label.currency": "Currency", + "label.currency": "货币", "label.current": "当前", "label.current-password": "当前密码", "label.custom-range": "自定义时间段", @@ -72,12 +72,12 @@ "label.details": "详细信息", "label.device": "设备", "label.devices": "设备", - "label.direct": "Direct", + "label.direct": "直接", "label.dismiss": "关闭", - "label.distinct-id": "Distinct ID", + "label.distinct-id": "唯一ID", "label.does-not-contain": "不包含", - "label.does-not-include": "Does not include", - "label.doest-not-exist": "Does not exist", + "label.does-not-include": "不包括", + "label.doest-not-exist": "不存在", "label.domain": "域名", "label.dropoff": "丢弃", "label.edit": "编辑", @@ -89,11 +89,11 @@ "label.entry": "入口 URL", "label.event": "事件", "label.event-data": "事件数据", - "label.event-name": "Event name", + "label.event-name": "事件名称", "label.events": "行为类别", - "label.exists": "Exists", + "label.exists": "存在", "label.exit": "退出 URL", - "label.expand": "Expand", + "label.expand": "展开", "label.false": "否", "label.field": "字段", "label.fields": "字段", @@ -101,37 +101,37 @@ "label.filter-combined": "合并", "label.filter-raw": "原始", "label.filters": "筛选", - "label.first-click": "First click", + "label.first-click": "首次点击", "label.first-seen": "首次出现", "label.funnel": "分析", "label.funnel-description": "了解用户的转化率和跳出率。", - "label.funnels": "Funnels", + "label.funnels": "漏斗", "label.goal": "目标", "label.goals": "目标", "label.goals-description": "跟踪页面浏览量和事件的目标。", "label.greater-than": "大于", "label.greater-than-equals": "大于或等于", - "label.grouped": "Grouped", - "label.hostname": "Hostname", - "label.includes": "Includes", - "label.insight": "Insight", + "label.grouped": "分组", + "label.hostname": "主机名", + "label.includes": "包括", + "label.insight": "洞察", "label.insights": "见解", "label.insights-description": "通过使用筛选器和划分时间段来更深入地研究数据。", "label.is": "等于", - "label.is-false": "Is false", + "label.is-false": "否", "label.is-not": "不等于", "label.is-not-set": "未设置", "label.is-set": "已设置", - "label.is-true": "Is true", + "label.is-true": "是", "label.join": "加入", "label.join-team": "加入团队", "label.journey": "用户浏览轨迹", "label.journey-description": "了解用户如何浏览网站。", - "label.journeys": "Journeys", + "label.journeys": "用户路径", "label.language": "语言", "label.languages": "语言", "label.laptop": "笔记本", - "label.last-click": "Last click", + "label.last-click": "最后点击", "label.last-days": "最近 {x} 天", "label.last-hours": "最近 {x} 小时", "label.last-months": "最近 {x} 个月", @@ -140,18 +140,18 @@ "label.leave-team": "离开团队", "label.less-than": "少于", "label.less-than-equals": "少于等于", - "label.links": "Links", + "label.links": "链接", "label.login": "登录", "label.logout": "退出", "label.manage": "管理", "label.manager": "管理者", "label.max": "最大", - "label.medium": "Medium", + "label.medium": "中等", "label.member": "成员", "label.members": "成员", "label.min": "最小", "label.mobile": "手机", - "label.model": "Model", + "label.model": "模型", "label.more": "更多", "label.my-account": "我的账户", "label.my-websites": "我的网站", @@ -160,28 +160,28 @@ "label.none": "无", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "好的", - "label.organic-search": "Organic search", - "label.organic-shopping": "Organic shopping", - "label.organic-social": "Organic social", - "label.organic-video": "Organic video", + "label.organic-search": "自然搜索", + "label.organic-shopping": "自然购物", + "label.organic-social": "自然社交", + "label.organic-video": "自然视频", "label.os": "操作系统", - "label.other": "Other", + "label.other": "其他", "label.overview": "概览", "label.owner": "所有者", - "label.page": "Page", + "label.page": "页面", "label.page-of": "总 {total} 中的第 {current} 页", "label.page-views": "页面浏览量", "label.pageTitle": "标题", "label.pages": "网页", - "label.paid-ads": "Paid ads", - "label.paid-search": "Paid search", - "label.paid-shopping": "Paid shopping", - "label.paid-social": "Paid social", - "label.paid-video": "Paid video", + "label.paid-ads": "付费广告", + "label.paid-search": "付费搜索", + "label.paid-shopping": "付费购物", + "label.paid-social": "付费社交", + "label.paid-video": "付费视频", "label.password": "密码", - "label.path": "Path", - "label.paths": "Paths", - "label.pixels": "Pixels", + "label.path": "路径", + "label.paths": "路径", + "label.pixels": "像素", "label.powered-by": "由 {name} 提供支持", "label.previous": "先前", "label.previous-period": "上一时期", @@ -200,7 +200,7 @@ "label.regenerate": "重新生成", "label.region": "州/省", "label.regions": "州/省", - "label.remaining": "Remaining", + "label.remaining": "剩余", "label.remove": "移除", "label.remove-member": "移除成员", "label.reports": "报告", @@ -218,35 +218,35 @@ "label.search": "搜索", "label.select": "选择", "label.select-date": "选择日期", - "label.select-filter": "Select filter", + "label.select-filter": "选择筛选器", "label.select-role": "选择角色", "label.select-website": "选择网站", - "label.session": "Session", - "label.session-data": "Session data", + "label.session": "会话", + "label.session-data": "会话数据", "label.sessions": "会话", "label.settings": "设置", - "label.share": "Share", + "label.share": "分享", "label.share-url": "共享链接", "label.single-day": "单日", "label.sms": "SMS", - "label.sources": "Sources", + "label.sources": "来源", "label.start-step": "开始步骤", "label.steps": "步骤", "label.sum": "总和", "label.tablet": "平板", - "label.tag": "Tag", - "label.tags": "Tags", + "label.tag": "标签", + "label.tags": "标签", "label.team": "团队", "label.team-id": "团队 ID", "label.team-manager": "团队管理员", "label.team-member": "团队成员", "label.team-name": "团队名称", "label.team-owner": "团队所有者", - "label.team-settings": "Team settings", + "label.team-settings": "团队设置", "label.team-view-only": "仅团队视图", "label.team-websites": "团队网站", "label.teams": "团队", - "label.terms": "Terms", + "label.terms": "条款", "label.theme": "主题", "label.this-month": "本月", "label.this-week": "本周", diff --git a/src/lang/zh-TW.json b/src/lang/zh-TW.json index 97f93ffc..eb5ca269 100644 --- a/src/lang/zh-TW.json +++ b/src/lang/zh-TW.json @@ -3,46 +3,46 @@ "label.actions": "行為", "label.activity": "活動紀錄", "label.add": "新增", - "label.add-board": "Add board", + "label.add-board": "新增看板", "label.add-description": "新增描述", "label.add-member": "新增成員", "label.add-step": "新增步驟", "label.add-website": "新增網站", "label.admin": "管理員", - "label.affiliate": "Affiliate", + "label.affiliate": "聯盟", "label.after": "之後", "label.all": "全部", "label.all-time": "所有時間", "label.analytics": "分析", - "label.apply": "Apply", - "label.attribution": "Attribution", - "label.attribution-description": "See how users engage with your marketing and what drives conversions.", + "label.apply": "套用", + "label.attribution": "歸因", + "label.attribution-description": "查看使用者如何與您的行銷互動,以及什麼促成了轉換。", "label.average": "平均", "label.back": "返回", "label.before": "之前", - "label.boards": "Boards", + "label.boards": "看板", "label.bounce-rate": "跳出率", "label.breakdown": "細項分析", "label.browser": "瀏覽器", "label.browsers": "瀏覽器", - "label.campaigns": "Campaigns", + "label.campaigns": "活動", "label.cancel": "取消", "label.change-password": "更改密碼", "label.channels": "Channels", "label.cities": "城市", "label.city": "城市", "label.clear-all": "全部清除", - "label.cohort": "Cohort", + "label.cohort": "群組", "label.compare": "比較", - "label.compare-dates": "Compare dates", + "label.compare-dates": "比較日期", "label.confirm": "確認", "label.confirm-password": "確認密碼", "label.contains": "包含", - "label.content": "Content", + "label.content": "內容", "label.continue": "繼續", - "label.conversion": "Conversion", - "label.conversion-ratep": "Conversion rate", - "label.conversion-step": "Conversion step", + "label.conversion": "轉換", + "label.conversion-rate": "轉換率", + "label.conversion-step": "轉換步驟", "label.count": "數量", "label.countries": "國家", "label.country": "國家", From 5c5ec18e671900f0d6b3bc90460a0733b918ff64 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 26 Jun 2025 21:44:00 -0700 Subject: [PATCH 107/399] Added turbo build for CI. --- .github/workflows/ci.yml | 2 +- package.json | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d9d99fe..c4faf887 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,4 +33,4 @@ jobs: - run: pnpm install - run: pnpm test - - run: pnpm build + - run: pnpm build-turbo diff --git a/package.json b/package.json index afc08e6b..e74c9f40 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,14 @@ "dev": "next dev", "dev-turbo": "next dev -p 3001 --turbopack", "build": "npm-run-all check-env build-db check-db build-tracker build-geo build-app", + "build-turbo": "npm-run-all check-env build-db check-db build-tracker build-geo build-app-turbo", "start": "next start", "build-docker": "npm-run-all build-db build-tracker build-geo build-app", "start-docker": "npm-run-all check-db update-tracker set-routes-manifest start-server", "start-env": "node scripts/start-env.js", "start-server": "node server.js", "build-app": "next build", + "build-app-turbo": "next build --turbo", "build-icons": "svgr ./src/assets --out-dir src/components/svg --typescript", "build-components": "rollup -c rollup.components.config.js", "build-tracker": "rollup -c rollup.tracker.config.js", @@ -80,7 +82,7 @@ "@react-spring/web": "^9.7.3", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.80.10", - "@umami/react-zen": "^0.142.0", + "@umami/react-zen": "^0.143.0", "@umami/redis-client": "^0.27.0", "bcryptjs": "^2.4.3", "chalk": "^4.1.1", From 184a387ecd7ff5499f10ea45d6d543b6ffc90dec Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 27 Jun 2025 08:53:10 -0700 Subject: [PATCH 108/399] Lang updates. --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- public/intl/messages/am-ET.json | 2 +- public/intl/messages/ar-SA.json | 18 ++++++++++++------ public/intl/messages/be-BY.json | 18 ++++++++++++------ public/intl/messages/bg-BG.json | 18 ++++++++++++------ public/intl/messages/bn-BD.json | 18 ++++++++++++------ public/intl/messages/bs-BA.json | 18 ++++++++++++------ public/intl/messages/ca-ES.json | 18 ++++++++++++------ public/intl/messages/cs-CZ.json | 18 ++++++++++++------ public/intl/messages/da-DK.json | 18 ++++++++++++------ public/intl/messages/de-CH.json | 18 ++++++++++++------ public/intl/messages/de-DE.json | 18 ++++++++++++------ public/intl/messages/el-GR.json | 18 ++++++++++++------ public/intl/messages/en-GB.json | 18 ++++++++++++------ public/intl/messages/en-US.json | 18 ++++++++++++------ public/intl/messages/es-ES.json | 18 ++++++++++++------ public/intl/messages/fa-IR.json | 18 ++++++++++++------ public/intl/messages/fi-FI.json | 18 ++++++++++++------ public/intl/messages/fo-FO.json | 18 ++++++++++++------ public/intl/messages/fr-FR.json | 18 ++++++++++++------ public/intl/messages/ga-ES.json | 18 ++++++++++++------ public/intl/messages/he-IL.json | 18 ++++++++++++------ public/intl/messages/hi-IN.json | 18 ++++++++++++------ public/intl/messages/hr-HR.json | 18 ++++++++++++------ public/intl/messages/hu-HU.json | 18 ++++++++++++------ public/intl/messages/id-ID.json | 18 ++++++++++++------ public/intl/messages/it-IT.json | 18 ++++++++++++------ public/intl/messages/ja-JP.json | 18 ++++++++++++------ public/intl/messages/km-KH.json | 24 ++++++++++++------------ public/intl/messages/ko-KR.json | 18 ++++++++++++------ public/intl/messages/lt-LT.json | 18 ++++++++++++------ public/intl/messages/mn-MN.json | 18 ++++++++++++------ public/intl/messages/ms-MY.json | 18 ++++++++++++------ public/intl/messages/my-MM.json | 18 ++++++++++++------ public/intl/messages/nb-NO.json | 18 ++++++++++++------ public/intl/messages/nl-NL.json | 18 ++++++++++++------ public/intl/messages/pl-PL.json | 18 ++++++++++++------ public/intl/messages/pt-BR.json | 18 ++++++++++++------ public/intl/messages/pt-PT.json | 18 ++++++++++++------ public/intl/messages/ro-RO.json | 18 ++++++++++++------ public/intl/messages/ru-RU.json | 18 ++++++++++++------ public/intl/messages/si-LK.json | 18 ++++++++++++------ public/intl/messages/sk-SK.json | 18 ++++++++++++------ public/intl/messages/sl-SI.json | 18 ++++++++++++------ public/intl/messages/sv-SE.json | 18 ++++++++++++------ public/intl/messages/ta-IN.json | 18 ++++++++++++------ public/intl/messages/th-TH.json | 18 ++++++++++++------ public/intl/messages/tr-TR.json | 18 ++++++++++++------ public/intl/messages/uk-UA.json | 18 ++++++++++++------ public/intl/messages/ur-PK.json | 18 ++++++++++++------ public/intl/messages/vi-VN.json | 18 ++++++++++++------ public/intl/messages/zh-CN.json | 18 ++++++++++++------ public/intl/messages/zh-TW.json | 18 ++++++++++++------ src/lang/ar-SA.json | 3 ++- src/lang/be-BY.json | 3 ++- src/lang/bg-BG.json | 3 ++- src/lang/bn-BD.json | 3 ++- src/lang/bs-BA.json | 3 ++- src/lang/ca-ES.json | 3 ++- src/lang/cs-CZ.json | 3 ++- src/lang/da-DK.json | 3 ++- src/lang/de-CH.json | 3 ++- src/lang/de-DE.json | 3 ++- src/lang/el-GR.json | 3 ++- src/lang/en-GB.json | 3 ++- src/lang/en-US.json | 3 ++- src/lang/es-ES.json | 3 ++- src/lang/fa-IR.json | 3 ++- src/lang/fi-FI.json | 3 ++- src/lang/fo-FO.json | 3 ++- src/lang/fr-FR.json | 3 ++- src/lang/ga-ES.json | 3 ++- src/lang/he-IL.json | 3 ++- src/lang/hi-IN.json | 3 ++- src/lang/hr-HR.json | 3 ++- src/lang/hu-HU.json | 3 ++- src/lang/id-ID.json | 3 ++- src/lang/it-IT.json | 3 ++- src/lang/ja-JP.json | 3 ++- src/lang/km-KH.json | 4 ++-- src/lang/ko-KR.json | 3 ++- src/lang/lt-LT.json | 3 ++- src/lang/mn-MN.json | 3 ++- src/lang/ms-MY.json | 3 ++- src/lang/my-MM.json | 3 ++- src/lang/nb-NO.json | 3 ++- src/lang/nl-NL.json | 3 ++- src/lang/pl-PL.json | 3 ++- src/lang/pt-BR.json | 3 ++- src/lang/pt-PT.json | 3 ++- src/lang/ro-RO.json | 3 ++- src/lang/ru-RU.json | 3 ++- src/lang/si-LK.json | 3 ++- src/lang/sk-SK.json | 3 ++- src/lang/sl-SI.json | 3 ++- src/lang/sv-SE.json | 3 ++- src/lang/ta-IN.json | 3 ++- src/lang/th-TH.json | 3 ++- src/lang/tr-TR.json | 3 ++- src/lang/uk-UA.json | 3 ++- src/lang/ur-PK.json | 3 ++- src/lang/vi-VN.json | 3 ++- src/lang/zh-CN.json | 3 ++- src/lang/zh-TW.json | 3 ++- 105 files changed, 721 insertions(+), 371 deletions(-) diff --git a/package.json b/package.json index e74c9f40..221cc1fe 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "@react-spring/web": "^9.7.3", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.80.10", - "@umami/react-zen": "^0.143.0", + "@umami/react-zen": "^0.144.0", "@umami/redis-client": "^0.27.0", "bcryptjs": "^2.4.3", "chalk": "^4.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19596963..1ada8af8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^5.80.10 version: 5.80.10(react@19.1.0) '@umami/react-zen': - specifier: ^0.142.0 - version: 0.142.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) + specifier: ^0.144.0 + version: 0.144.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) '@umami/redis-client': specifier: ^0.27.0 version: 0.27.0 @@ -2549,8 +2549,8 @@ packages: resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@umami/react-zen@0.142.0': - resolution: {integrity: sha512-xD0O96c1AsztIbD8DZOszBeXAmEhVJ1isqsms+Nu/Kzf4vkWhEPpu7dbhntroHiA7JLK/uI1bgYHQMJFMM1f4w==} + '@umami/react-zen@0.144.0': + resolution: {integrity: sha512-RpPid2hdXAzbWKlbQWdSCwm6GZMHVs1f6VsVumq7Who/B8wxX0RVBwehHn3/ERwDw+c6ThRzlAZvOO6QLv+tQw==} '@umami/redis-client@0.27.0': resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==} @@ -9733,7 +9733,7 @@ snapshots: '@typescript-eslint/types': 8.34.1 eslint-visitor-keys: 4.2.1 - '@umami/react-zen@0.142.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': + '@umami/react-zen@0.144.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': dependencies: '@fontsource/jetbrains-mono': 5.2.6 '@internationalized/date': 3.8.2 diff --git a/public/intl/messages/am-ET.json b/public/intl/messages/am-ET.json index 1fe020ea..e0332ae0 100644 --- a/public/intl/messages/am-ET.json +++ b/public/intl/messages/am-ET.json @@ -563,7 +563,7 @@ "value": "Exit URL" } ], - "label.expand": [ + "label.maximize": [ { "type": 0, "value": "Expand" diff --git a/public/intl/messages/ar-SA.json b/public/intl/messages/ar-SA.json index 57635e0f..66a88dfb 100644 --- a/public/intl/messages/ar-SA.json +++ b/public/intl/messages/ar-SA.json @@ -563,12 +563,6 @@ "value": "رابط المغادرة" } ], - "label.expand": [ - { - "type": 0, - "value": "توسيع" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "الحد الأقصى" } ], + "label.maximize": [ + { + "type": 0, + "value": "توسيع" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "نعم" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/be-BY.json b/public/intl/messages/be-BY.json index 366993a5..dc6afb79 100644 --- a/public/intl/messages/be-BY.json +++ b/public/intl/messages/be-BY.json @@ -563,12 +563,6 @@ "value": "URL выхаду" } ], - "label.expand": [ - { - "type": 0, - "value": "Разгарнуць" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Максімум" } ], + "label.maximize": [ + { + "type": 0, + "value": "Разгарнуць" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "ОК" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/bg-BG.json b/public/intl/messages/bg-BG.json index 28a3ae76..1ff2a7b7 100644 --- a/public/intl/messages/bg-BG.json +++ b/public/intl/messages/bg-BG.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Разшири" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Максимум" } ], + "label.maximize": [ + { + "type": 0, + "value": "Разшири" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "Добре" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/bn-BD.json b/public/intl/messages/bn-BD.json index 0f1bbdda..aa66cd85 100644 --- a/public/intl/messages/bn-BD.json +++ b/public/intl/messages/bn-BD.json @@ -563,12 +563,6 @@ "value": "প্রস্থান URL" } ], - "label.expand": [ - { - "type": 0, - "value": "বিস্তৃত করুন" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "সর্বাধিক" } ], + "label.maximize": [ + { + "type": 0, + "value": "বিস্তৃত করুন" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/bs-BA.json b/public/intl/messages/bs-BA.json index b0a4b87e..7d115a59 100644 --- a/public/intl/messages/bs-BA.json +++ b/public/intl/messages/bs-BA.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Proširi" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Proširi" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/ca-ES.json b/public/intl/messages/ca-ES.json index 7c75c0be..fab208b9 100644 --- a/public/intl/messages/ca-ES.json +++ b/public/intl/messages/ca-ES.json @@ -563,12 +563,6 @@ "value": "URL de sortida" } ], - "label.expand": [ - { - "type": 0, - "value": "Expandeix" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Màx" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expandeix" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/cs-CZ.json b/public/intl/messages/cs-CZ.json index d1873ffb..d45ef5df 100644 --- a/public/intl/messages/cs-CZ.json +++ b/public/intl/messages/cs-CZ.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Rozbalit" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Rozbalit" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/da-DK.json b/public/intl/messages/da-DK.json index 8d33490c..577d0698 100644 --- a/public/intl/messages/da-DK.json +++ b/public/intl/messages/da-DK.json @@ -563,12 +563,6 @@ "value": "Udgangs-URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Udvid" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Maks" } ], + "label.maximize": [ + { + "type": 0, + "value": "Udvid" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/de-CH.json b/public/intl/messages/de-CH.json index 7f5daed9..58d318c0 100644 --- a/public/intl/messages/de-CH.json +++ b/public/intl/messages/de-CH.json @@ -563,12 +563,6 @@ "value": "Uusgangs URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Uusklappe" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Uusklappe" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/de-DE.json b/public/intl/messages/de-DE.json index f948baae..c78dcf5c 100644 --- a/public/intl/messages/de-DE.json +++ b/public/intl/messages/de-DE.json @@ -563,12 +563,6 @@ "value": "Ausgangs-URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Erweitern" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Erweitern" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/el-GR.json b/public/intl/messages/el-GR.json index 134d06fe..f43e2fd3 100644 --- a/public/intl/messages/el-GR.json +++ b/public/intl/messages/el-GR.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Expand" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expand" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/en-GB.json b/public/intl/messages/en-GB.json index 12d854af..406a1ee0 100644 --- a/public/intl/messages/en-GB.json +++ b/public/intl/messages/en-GB.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Expand" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expand" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/en-US.json b/public/intl/messages/en-US.json index b04d63ec..5cc8c37e 100644 --- a/public/intl/messages/en-US.json +++ b/public/intl/messages/en-US.json @@ -563,12 +563,6 @@ "value": "Exit path" } ], - "label.expand": [ - { - "type": 0, - "value": "Expand" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Maximize" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/es-ES.json b/public/intl/messages/es-ES.json index 3c875dc2..151ab5f4 100644 --- a/public/intl/messages/es-ES.json +++ b/public/intl/messages/es-ES.json @@ -563,12 +563,6 @@ "value": "URL de salida" } ], - "label.expand": [ - { - "type": 0, - "value": "Expandir" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Máximo" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expandir" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/fa-IR.json b/public/intl/messages/fa-IR.json index fa071712..7610a7b5 100644 --- a/public/intl/messages/fa-IR.json +++ b/public/intl/messages/fa-IR.json @@ -563,12 +563,6 @@ "value": "آدرس اینترنتی خروجی" } ], - "label.expand": [ - { - "type": 0, - "value": "گسترش" - } - ], "label.false": [ { "type": 0, @@ -893,6 +887,12 @@ "value": "حداکثر" } ], + "label.maximize": [ + { + "type": 0, + "value": "گسترش" + } + ], "label.medium": [ { "type": 0, @@ -1005,6 +1005,12 @@ "value": "تایید" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/fi-FI.json b/public/intl/messages/fi-FI.json index 232ba4e4..7e2b92ff 100644 --- a/public/intl/messages/fi-FI.json +++ b/public/intl/messages/fi-FI.json @@ -563,12 +563,6 @@ "value": "Poistumis-URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Laajenna" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Maksimi" } ], + "label.maximize": [ + { + "type": 0, + "value": "Laajenna" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/fo-FO.json b/public/intl/messages/fo-FO.json index d02f44c8..9c048263 100644 --- a/public/intl/messages/fo-FO.json +++ b/public/intl/messages/fo-FO.json @@ -563,12 +563,6 @@ "value": "Útgangs URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Víðka" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Mest" } ], + "label.maximize": [ + { + "type": 0, + "value": "Víðka" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/fr-FR.json b/public/intl/messages/fr-FR.json index 79697401..d190ec14 100644 --- a/public/intl/messages/fr-FR.json +++ b/public/intl/messages/fr-FR.json @@ -563,12 +563,6 @@ "value": "Chemin de sortie" } ], - "label.expand": [ - { - "type": 0, - "value": "Développer" - } - ], "label.false": [ { "type": 0, @@ -893,6 +887,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Développer" + } + ], "label.medium": [ { "type": 0, @@ -1005,6 +1005,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/ga-ES.json b/public/intl/messages/ga-ES.json index ca365e91..d0e3d52d 100644 --- a/public/intl/messages/ga-ES.json +++ b/public/intl/messages/ga-ES.json @@ -563,12 +563,6 @@ "value": "URL de saída" } ], - "label.expand": [ - { - "type": 0, - "value": "Expandir" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expandir" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/he-IL.json b/public/intl/messages/he-IL.json index b2196f87..8c73d0ff 100644 --- a/public/intl/messages/he-IL.json +++ b/public/intl/messages/he-IL.json @@ -563,12 +563,6 @@ "value": "כתובת יציאה" } ], - "label.expand": [ - { - "type": 0, - "value": "הרחב" - } - ], "label.false": [ { "type": 0, @@ -893,6 +887,12 @@ "value": "מקסימום" } ], + "label.maximize": [ + { + "type": 0, + "value": "הרחב" + } + ], "label.medium": [ { "type": 0, @@ -1005,6 +1005,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/hi-IN.json b/public/intl/messages/hi-IN.json index 437fc433..493ff994 100644 --- a/public/intl/messages/hi-IN.json +++ b/public/intl/messages/hi-IN.json @@ -563,12 +563,6 @@ "value": "निकास URL" } ], - "label.expand": [ - { - "type": 0, - "value": "विस्तार करें" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "अधिकतम" } ], + "label.maximize": [ + { + "type": 0, + "value": "विस्तार करें" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/hr-HR.json b/public/intl/messages/hr-HR.json index 0b0e8b7d..a6ad7503 100644 --- a/public/intl/messages/hr-HR.json +++ b/public/intl/messages/hr-HR.json @@ -563,12 +563,6 @@ "value": "Izlazni URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Proširi" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Maksimum" } ], + "label.maximize": [ + { + "type": 0, + "value": "Proširi" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/hu-HU.json b/public/intl/messages/hu-HU.json index be086217..3a228f8a 100644 --- a/public/intl/messages/hu-HU.json +++ b/public/intl/messages/hu-HU.json @@ -563,12 +563,6 @@ "value": "Kilépési URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Kibontás" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Maximum" } ], + "label.maximize": [ + { + "type": 0, + "value": "Kibontás" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/id-ID.json b/public/intl/messages/id-ID.json index 06c9e186..1dad7406 100644 --- a/public/intl/messages/id-ID.json +++ b/public/intl/messages/id-ID.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Perluas" - } - ], "label.false": [ { "type": 0, @@ -893,6 +887,12 @@ "value": "Maksimum" } ], + "label.maximize": [ + { + "type": 0, + "value": "Perluas" + } + ], "label.medium": [ { "type": 0, @@ -1005,6 +1005,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/it-IT.json b/public/intl/messages/it-IT.json index a8640bd7..40cac07a 100644 --- a/public/intl/messages/it-IT.json +++ b/public/intl/messages/it-IT.json @@ -563,12 +563,6 @@ "value": "URL di uscita" } ], - "label.expand": [ - { - "type": 0, - "value": "Espandi" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Massimo" } ], + "label.maximize": [ + { + "type": 0, + "value": "Espandi" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/ja-JP.json b/public/intl/messages/ja-JP.json index 9c846ba0..9b7b2e77 100644 --- a/public/intl/messages/ja-JP.json +++ b/public/intl/messages/ja-JP.json @@ -563,12 +563,6 @@ "value": "退出時のURL" } ], - "label.expand": [ - { - "type": 0, - "value": "展開" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "最大" } ], + "label.maximize": [ + { + "type": 0, + "value": "展開" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/km-KH.json b/public/intl/messages/km-KH.json index eb7cd70f..d769a863 100644 --- a/public/intl/messages/km-KH.json +++ b/public/intl/messages/km-KH.json @@ -563,12 +563,6 @@ "value": "URL ចេញ" } ], - "label.expand": [ - { - "type": 0, - "value": "ពង្រីក" - } - ], "label.false": [ { "type": 0, @@ -893,6 +887,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "ពង្រីក" + } + ], "label.medium": [ { "type": 0, @@ -1005,6 +1005,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, @@ -1311,12 +1317,6 @@ "value": " នៅក្នុងប្រអប់ខាងក្រោមដើម្បីបញ្ជាក់។" } ], - "label.reset-website-warning": [ - { - "type": 0, - "value": "ស្ថិតិទាំងអស់សម្រាប់គេហទំព័រនេះនឹងត្រូវបានលុប ប៉ុន្តែកូដតាមដានរបស់អ្នកនឹងនៅដដែល។" - } - ], "label.retention": [ { "type": 0, diff --git a/public/intl/messages/ko-KR.json b/public/intl/messages/ko-KR.json index 638e60f2..239aa6c1 100644 --- a/public/intl/messages/ko-KR.json +++ b/public/intl/messages/ko-KR.json @@ -563,12 +563,6 @@ "value": "퇴장 URL" } ], - "label.expand": [ - { - "type": 0, - "value": "확장" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "최대" } ], + "label.maximize": [ + { + "type": 0, + "value": "확장" + } + ], "label.medium": [ { "type": 0, @@ -993,6 +993,12 @@ "value": "확인" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/lt-LT.json b/public/intl/messages/lt-LT.json index 6ba52cf4..c71d6755 100644 --- a/public/intl/messages/lt-LT.json +++ b/public/intl/messages/lt-LT.json @@ -563,12 +563,6 @@ "value": "Išėjimo URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Išplėsti" - } - ], "label.false": [ { "type": 0, @@ -1010,6 +1004,12 @@ "value": "Maksimumas" } ], + "label.maximize": [ + { + "type": 0, + "value": "Išplėsti" + } + ], "label.medium": [ { "type": 0, @@ -1122,6 +1122,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/mn-MN.json b/public/intl/messages/mn-MN.json index 574875f7..dcc965c4 100644 --- a/public/intl/messages/mn-MN.json +++ b/public/intl/messages/mn-MN.json @@ -563,12 +563,6 @@ "value": "Гарах зам" } ], - "label.expand": [ - { - "type": 0, - "value": "Өргөтгөх" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Өргөтгөх" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "ЗА" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/ms-MY.json b/public/intl/messages/ms-MY.json index b55ab0b0..a2fdd5bb 100644 --- a/public/intl/messages/ms-MY.json +++ b/public/intl/messages/ms-MY.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Expand" - } - ], "label.false": [ { "type": 0, @@ -897,6 +891,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expand" + } + ], "label.medium": [ { "type": 0, @@ -1009,6 +1009,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/my-MM.json b/public/intl/messages/my-MM.json index 91a477ed..74c9909c 100644 --- a/public/intl/messages/my-MM.json +++ b/public/intl/messages/my-MM.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Expand" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "အများဆုံး" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expand" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/nb-NO.json b/public/intl/messages/nb-NO.json index b9090692..34f7c97f 100644 --- a/public/intl/messages/nb-NO.json +++ b/public/intl/messages/nb-NO.json @@ -563,12 +563,6 @@ "value": "Utgangs-URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Utvid" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Maks" } ], + "label.maximize": [ + { + "type": 0, + "value": "Utvid" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/nl-NL.json b/public/intl/messages/nl-NL.json index 0672d332..1c136666 100644 --- a/public/intl/messages/nl-NL.json +++ b/public/intl/messages/nl-NL.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Uitvouwen" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Uitvouwen" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/pl-PL.json b/public/intl/messages/pl-PL.json index 44a4b620..90789641 100644 --- a/public/intl/messages/pl-PL.json +++ b/public/intl/messages/pl-PL.json @@ -563,12 +563,6 @@ "value": "URL wyjściowy" } ], - "label.expand": [ - { - "type": 0, - "value": "Rozwiń" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Maks" } ], + "label.maximize": [ + { + "type": 0, + "value": "Rozwiń" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/pt-BR.json b/public/intl/messages/pt-BR.json index b23bd062..d99a3325 100644 --- a/public/intl/messages/pt-BR.json +++ b/public/intl/messages/pt-BR.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Expandir" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Máximo" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expandir" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/pt-PT.json b/public/intl/messages/pt-PT.json index f6ab5858..630b8a9f 100644 --- a/public/intl/messages/pt-PT.json +++ b/public/intl/messages/pt-PT.json @@ -563,12 +563,6 @@ "value": "URL de saída" } ], - "label.expand": [ - { - "type": 0, - "value": "Expandir" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Máximo" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expandir" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/ro-RO.json b/public/intl/messages/ro-RO.json index a235caee..d434c0b5 100644 --- a/public/intl/messages/ro-RO.json +++ b/public/intl/messages/ro-RO.json @@ -563,12 +563,6 @@ "value": "URL de ieșire" } ], - "label.expand": [ - { - "type": 0, - "value": "Extinde" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Extinde" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/ru-RU.json b/public/intl/messages/ru-RU.json index e6451c1e..b4bf8a27 100644 --- a/public/intl/messages/ru-RU.json +++ b/public/intl/messages/ru-RU.json @@ -563,12 +563,6 @@ "value": "URL-адрес выхода" } ], - "label.expand": [ - { - "type": 0, - "value": "Развернуть" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Максимум" } ], + "label.maximize": [ + { + "type": 0, + "value": "Развернуть" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/si-LK.json b/public/intl/messages/si-LK.json index 6d75c325..2dfa47f0 100644 --- a/public/intl/messages/si-LK.json +++ b/public/intl/messages/si-LK.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Expand" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expand" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/sk-SK.json b/public/intl/messages/sk-SK.json index 7446cd5d..a1f1158b 100644 --- a/public/intl/messages/sk-SK.json +++ b/public/intl/messages/sk-SK.json @@ -563,12 +563,6 @@ "value": "Výstupná URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Rozbaliť" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Maximum" } ], + "label.maximize": [ + { + "type": 0, + "value": "Rozbaliť" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/sl-SI.json b/public/intl/messages/sl-SI.json index d7a39997..73532727 100644 --- a/public/intl/messages/sl-SI.json +++ b/public/intl/messages/sl-SI.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Razširi" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Največ" } ], + "label.maximize": [ + { + "type": 0, + "value": "Razširi" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/sv-SE.json b/public/intl/messages/sv-SE.json index 014be980..684d4450 100644 --- a/public/intl/messages/sv-SE.json +++ b/public/intl/messages/sv-SE.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Expandera" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expandera" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/ta-IN.json b/public/intl/messages/ta-IN.json index 780f2b32..6d36a110 100644 --- a/public/intl/messages/ta-IN.json +++ b/public/intl/messages/ta-IN.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Expand" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expand" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/th-TH.json b/public/intl/messages/th-TH.json index 40ad9a70..cf3e5321 100644 --- a/public/intl/messages/th-TH.json +++ b/public/intl/messages/th-TH.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Expand" - } - ], "label.false": [ { "type": 0, @@ -897,6 +891,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expand" + } + ], "label.medium": [ { "type": 0, @@ -1009,6 +1009,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/tr-TR.json b/public/intl/messages/tr-TR.json index af603ec1..f7774fc7 100644 --- a/public/intl/messages/tr-TR.json +++ b/public/intl/messages/tr-TR.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Genişlet" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Genişlet" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "TAMAM" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/uk-UA.json b/public/intl/messages/uk-UA.json index 2a3e48ec..d3a6dc79 100644 --- a/public/intl/messages/uk-UA.json +++ b/public/intl/messages/uk-UA.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Розгорнути" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Макс." } ], + "label.maximize": [ + { + "type": 0, + "value": "Розгорнути" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/ur-PK.json b/public/intl/messages/ur-PK.json index f5f55b24..8eba7594 100644 --- a/public/intl/messages/ur-PK.json +++ b/public/intl/messages/ur-PK.json @@ -563,12 +563,6 @@ "value": "Exit URL" } ], - "label.expand": [ - { - "type": 0, - "value": "Expand" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "Max" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expand" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/vi-VN.json b/public/intl/messages/vi-VN.json index 5f969518..250f7446 100644 --- a/public/intl/messages/vi-VN.json +++ b/public/intl/messages/vi-VN.json @@ -563,12 +563,6 @@ "value": "URL thoát" } ], - "label.expand": [ - { - "type": 0, - "value": "Mở rộng" - } - ], "label.false": [ { "type": 0, @@ -893,6 +887,12 @@ "value": "Tối đa" } ], + "label.maximize": [ + { + "type": 0, + "value": "Mở rộng" + } + ], "label.medium": [ { "type": 0, @@ -1005,6 +1005,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/zh-CN.json b/public/intl/messages/zh-CN.json index d6b7dba7..b3d2f3c0 100644 --- a/public/intl/messages/zh-CN.json +++ b/public/intl/messages/zh-CN.json @@ -563,12 +563,6 @@ "value": "退出 URL" } ], - "label.expand": [ - { - "type": 0, - "value": "展开" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "最大" } ], + "label.maximize": [ + { + "type": 0, + "value": "展开" + } + ], "label.medium": [ { "type": 0, @@ -1017,6 +1017,12 @@ "value": "好的" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/public/intl/messages/zh-TW.json b/public/intl/messages/zh-TW.json index 68b5e220..db500a4b 100644 --- a/public/intl/messages/zh-TW.json +++ b/public/intl/messages/zh-TW.json @@ -563,12 +563,6 @@ "value": "離開網址" } ], - "label.expand": [ - { - "type": 0, - "value": "Expand" - } - ], "label.false": [ { "type": 0, @@ -905,6 +899,12 @@ "value": "最大值" } ], + "label.maximize": [ + { + "type": 0, + "value": "Expand" + } + ], "label.medium": [ { "type": 0, @@ -993,6 +993,12 @@ "value": "OK" } ], + "label.online": [ + { + "type": 0, + "value": "Online" + } + ], "label.organic-search": [ { "type": 0, diff --git a/src/lang/ar-SA.json b/src/lang/ar-SA.json index b5667c0b..6a60dd53 100644 --- a/src/lang/ar-SA.json +++ b/src/lang/ar-SA.json @@ -93,7 +93,6 @@ "label.events": "الأحداث", "label.exists": "موجود", "label.exit": "رابط المغادرة", - "label.expand": "توسيع", "label.false": "خطأ", "label.field": "الحقل", "label.fields": "الحقول", @@ -146,6 +145,7 @@ "label.manage": "التحكم", "label.manager": "مدير", "label.max": "الحد الأقصى", + "label.maximize": "توسيع", "label.medium": "وسيط", "label.member": "عضو", "label.members": "الأعضاء", @@ -160,6 +160,7 @@ "label.none": "لا شيء", "label.number-of-records": "{x} {x, plural, one {سجل} other {سجلات}}", "label.ok": "نعم", + "label.online": "Online", "label.organic-search": "بحث عضوي", "label.organic-shopping": "تسوق عضوي", "label.organic-social": "اجتماعي عضوي", diff --git a/src/lang/be-BY.json b/src/lang/be-BY.json index 9e7fa18c..932ea557 100644 --- a/src/lang/be-BY.json +++ b/src/lang/be-BY.json @@ -93,7 +93,6 @@ "label.events": "Падзеі", "label.exists": "Існуе", "label.exit": "URL выхаду", - "label.expand": "Разгарнуць", "label.false": "Ложна", "label.field": "Поле", "label.fields": "Палі", @@ -146,6 +145,7 @@ "label.manage": "Кіраваць", "label.manager": "Кіраўнік", "label.max": "Максімум", + "label.maximize": "Разгарнуць", "label.medium": "Сярэдні", "label.member": "Удзельнік", "label.members": "Удзельнікі", @@ -160,6 +160,7 @@ "label.none": "Няма", "label.number-of-records": "{x} {x, plural, one {запіс} other {запісаў}}", "label.ok": "ОК", + "label.online": "Online", "label.organic-search": "Арганічны пошук", "label.organic-shopping": "Арганічныя пакупкі", "label.organic-social": "Арганічныя сацыяльныя сеткі", diff --git a/src/lang/bg-BG.json b/src/lang/bg-BG.json index 3cc7db77..0487498d 100644 --- a/src/lang/bg-BG.json +++ b/src/lang/bg-BG.json @@ -93,7 +93,6 @@ "label.events": "Събития", "label.exists": "Съществува", "label.exit": "Exit URL", - "label.expand": "Разшири", "label.false": "Грешно", "label.field": "Поле", "label.fields": "Полета", @@ -146,6 +145,7 @@ "label.manage": "Управлявай", "label.manager": "Мениджър", "label.max": "Максимум", + "label.maximize": "Разшири", "label.medium": "Среден", "label.member": "Член", "label.members": "Членове", @@ -160,6 +160,7 @@ "label.none": "Няма", "label.number-of-records": "{x} {x, plural, one {един} other {други}}", "label.ok": "Добре", + "label.online": "Online", "label.organic-search": "Органично търсене", "label.organic-shopping": "Органично пазаруване", "label.organic-social": "Органични социални мрежи", diff --git a/src/lang/bn-BD.json b/src/lang/bn-BD.json index 77123fa2..0260558b 100644 --- a/src/lang/bn-BD.json +++ b/src/lang/bn-BD.json @@ -93,7 +93,6 @@ "label.events": "ঘটনা", "label.exists": "অস্তিত্ব আছে", "label.exit": "প্রস্থান URL", - "label.expand": "বিস্তৃত করুন", "label.false": "মিথ্যা", "label.field": "ক্ষেত্র", "label.fields": "ক্ষেত্রসমূহ", @@ -146,6 +145,7 @@ "label.manage": "পরিচালনা করুন", "label.manager": "পরিচালক", "label.max": "সর্বাধিক", + "label.maximize": "বিস্তৃত করুন", "label.medium": "মাঝারি", "label.member": "সদস্য", "label.members": "সদস্যগণ", @@ -160,6 +160,7 @@ "label.none": "কিছুই না", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "অর্গানিক সার্চ", "label.organic-shopping": "অর্গানিক শপিং", "label.organic-social": "অর্গানিক সোশ্যাল", diff --git a/src/lang/bs-BA.json b/src/lang/bs-BA.json index d6d665fb..72d635d4 100644 --- a/src/lang/bs-BA.json +++ b/src/lang/bs-BA.json @@ -93,7 +93,6 @@ "label.events": "Događaji", "label.exists": "Postoji", "label.exit": "Exit URL", - "label.expand": "Proširi", "label.false": "Ne", "label.field": "Polje", "label.fields": "Polja", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Menadžer", "label.max": "Max", + "label.maximize": "Proširi", "label.medium": "Srednje", "label.member": "Član", "label.members": "Članovi", @@ -160,6 +160,7 @@ "label.none": "Nijedno", "label.number-of-records": "{x} {x, plural, one {zapis} other {zapisa}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organska pretraga", "label.organic-shopping": "Organska kupovina", "label.organic-social": "Organske društvene mreže", diff --git a/src/lang/ca-ES.json b/src/lang/ca-ES.json index 9264de7c..7ff46555 100644 --- a/src/lang/ca-ES.json +++ b/src/lang/ca-ES.json @@ -93,7 +93,6 @@ "label.events": "Esdeveniments", "label.exists": "Existeix", "label.exit": "URL de sortida", - "label.expand": "Expandeix", "label.false": "Fals", "label.field": "Camp", "label.fields": "Camps", @@ -146,6 +145,7 @@ "label.manage": "Administrar", "label.manager": "Responsable", "label.max": "Màx", + "label.maximize": "Expandeix", "label.medium": "Mitjà", "label.member": "Membre", "label.members": "Membres", @@ -160,6 +160,7 @@ "label.none": "Cap", "label.number-of-records": "{x} {x, plural, one {registre} other {registres}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Cerca orgànica", "label.organic-shopping": "Compra orgànica", "label.organic-social": "Social orgànic", diff --git a/src/lang/cs-CZ.json b/src/lang/cs-CZ.json index bf6ae63e..a4dbc865 100644 --- a/src/lang/cs-CZ.json +++ b/src/lang/cs-CZ.json @@ -93,7 +93,6 @@ "label.events": "Události", "label.exists": "Existuje", "label.exit": "Exit URL", - "label.expand": "Rozbalit", "label.false": "Nepravda", "label.field": "Pole", "label.fields": "Pole", @@ -146,6 +145,7 @@ "label.manage": "Spravovat", "label.manager": "Správce", "label.max": "Max", + "label.maximize": "Rozbalit", "label.medium": "Střední", "label.member": "Člen", "label.members": "Členové", @@ -160,6 +160,7 @@ "label.none": "Žádný", "label.number-of-records": "{x} {x, plural, one {záznam} other {záznamů}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organické vyhledávání", "label.organic-shopping": "Organický nákup", "label.organic-social": "Organická sociální síť", diff --git a/src/lang/da-DK.json b/src/lang/da-DK.json index 9141f51c..0078bcd3 100644 --- a/src/lang/da-DK.json +++ b/src/lang/da-DK.json @@ -93,7 +93,6 @@ "label.events": "Hændelser", "label.exists": "Findes", "label.exit": "Udgangs-URL", - "label.expand": "Udvid", "label.false": "Falsk", "label.field": "Felt", "label.fields": "Felter", @@ -146,6 +145,7 @@ "label.manage": "Administrer", "label.manager": "Leder", "label.max": "Maks", + "label.maximize": "Udvid", "label.medium": "Medium", "label.member": "Medlem", "label.members": "Medlemmer", @@ -160,6 +160,7 @@ "label.none": "Ingen", "label.number-of-records": "{x} {x, plural, one {post} other {poster}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organisk søgning", "label.organic-shopping": "Organisk shopping", "label.organic-social": "Organisk social", diff --git a/src/lang/de-CH.json b/src/lang/de-CH.json index 7e2fcf39..a770949a 100644 --- a/src/lang/de-CH.json +++ b/src/lang/de-CH.json @@ -93,7 +93,6 @@ "label.events": "Ereigniss", "label.exists": "Existiert", "label.exit": "Uusgangs URL", - "label.expand": "Uusklappe", "label.false": "Falsch", "label.field": "Fäld", "label.fields": "Fälder", @@ -146,6 +145,7 @@ "label.manage": "Verwalte", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Uusklappe", "label.medium": "Medium", "label.member": "Mitglied", "label.members": "Mitglieder", @@ -160,6 +160,7 @@ "label.none": "Keis", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organischi Suechi", "label.organic-shopping": "Organischi Iikauf", "label.organic-social": "Organischi Social Media", diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json index c5070a81..9bbedbf9 100644 --- a/src/lang/de-DE.json +++ b/src/lang/de-DE.json @@ -93,7 +93,6 @@ "label.events": "Ereignisse", "label.exists": "Existiert", "label.exit": "Ausgangs-URL", - "label.expand": "Erweitern", "label.false": "Falsch", "label.field": "Feld", "label.fields": "Felder", @@ -146,6 +145,7 @@ "label.manage": "Verwalten", "label.manager": "Verwaltung", "label.max": "Max", + "label.maximize": "Erweitern", "label.medium": "Medium", "label.member": "Mitglied", "label.members": "Mitglieder", @@ -160,6 +160,7 @@ "label.none": "Keine", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organische Suche", "label.organic-shopping": "Organisches Shopping", "label.organic-social": "Organisches Social Media", diff --git a/src/lang/el-GR.json b/src/lang/el-GR.json index 82de9f47..df44a29d 100644 --- a/src/lang/el-GR.json +++ b/src/lang/el-GR.json @@ -93,7 +93,6 @@ "label.events": "Γεγονότα", "label.exists": "Exists", "label.exit": "Exit URL", - "label.expand": "Expand", "label.false": "False", "label.field": "Field", "label.fields": "Fields", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Expand", "label.medium": "Medium", "label.member": "Member", "label.members": "Members", @@ -160,6 +160,7 @@ "label.none": "None", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organic search", "label.organic-shopping": "Organic shopping", "label.organic-social": "Organic social", diff --git a/src/lang/en-GB.json b/src/lang/en-GB.json index 09ad528f..d2291495 100644 --- a/src/lang/en-GB.json +++ b/src/lang/en-GB.json @@ -93,7 +93,6 @@ "label.events": "Events", "label.exists": "Exists", "label.exit": "Exit URL", - "label.expand": "Expand", "label.false": "False", "label.field": "Field", "label.fields": "Fields", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Expand", "label.medium": "Medium", "label.member": "Member", "label.members": "Members", @@ -160,6 +160,7 @@ "label.none": "None", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organic search", "label.organic-shopping": "Organic shopping", "label.organic-social": "Organic social", diff --git a/src/lang/en-US.json b/src/lang/en-US.json index f7352769..7d5bf884 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -93,7 +93,6 @@ "label.events": "Events", "label.exists": "Exists", "label.exit": "Exit path", - "label.expand": "Expand", "label.false": "False", "label.field": "Field", "label.fields": "Fields", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Maximize", "label.medium": "Medium", "label.member": "Member", "label.members": "Members", @@ -160,6 +160,7 @@ "label.none": "None", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organic search", "label.organic-shopping": "Organic shopping", "label.organic-social": "Organic social", diff --git a/src/lang/es-ES.json b/src/lang/es-ES.json index e4eed919..c17122bd 100644 --- a/src/lang/es-ES.json +++ b/src/lang/es-ES.json @@ -93,7 +93,6 @@ "label.events": "Eventos", "label.exists": "Existe", "label.exit": "URL de salida", - "label.expand": "Expandir", "label.false": "Falso", "label.field": "Campo", "label.fields": "Campos", @@ -146,6 +145,7 @@ "label.manage": "Administrar", "label.manager": "Gerente", "label.max": "Máximo", + "label.maximize": "Expandir", "label.medium": "Medio", "label.member": "Miembro", "label.members": "Miembros", @@ -160,6 +160,7 @@ "label.none": "Ninguno", "label.number-of-records": "{x} {x, plural, one {registro} other {registros}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Búsqueda orgánica", "label.organic-shopping": "Compras orgánicas", "label.organic-social": "Social orgánico", diff --git a/src/lang/fa-IR.json b/src/lang/fa-IR.json index 05e70cfb..4e912fce 100644 --- a/src/lang/fa-IR.json +++ b/src/lang/fa-IR.json @@ -93,7 +93,6 @@ "label.events": "رویدادها", "label.exists": "وجود دارد", "label.exit": "آدرس اینترنتی خروجی", - "label.expand": "گسترش", "label.false": "نادرست", "label.field": "فیلد", "label.fields": "فیلد‌ها", @@ -146,6 +145,7 @@ "label.manage": "مدیریت", "label.manager": "مدیر", "label.max": "حداکثر", + "label.maximize": "گسترش", "label.medium": "متوسط", "label.member": "عضو", "label.members": "اعضا", @@ -160,6 +160,7 @@ "label.none": "هیچ", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "تایید", + "label.online": "Online", "label.organic-search": "جستجوی ارگانیک", "label.organic-shopping": "خرید ارگانیک", "label.organic-social": "شبکه اجتماعی ارگانیک", diff --git a/src/lang/fi-FI.json b/src/lang/fi-FI.json index cacc1d91..06f66d6c 100644 --- a/src/lang/fi-FI.json +++ b/src/lang/fi-FI.json @@ -93,7 +93,6 @@ "label.events": "Tapahtumat", "label.exists": "On olemassa", "label.exit": "Poistumis-URL", - "label.expand": "Laajenna", "label.false": "Epätosi", "label.field": "Kenttä", "label.fields": "Kentät", @@ -146,6 +145,7 @@ "label.manage": "Hallinnoi", "label.manager": "Päällikkö", "label.max": "Maksimi", + "label.maximize": "Laajenna", "label.medium": "Keskitaso", "label.member": "Jäsen", "label.members": "Jäsenet", @@ -160,6 +160,7 @@ "label.none": "Ei mitään", "label.number-of-records": "{x} {x, plural, one {tietue} other {tietuetta}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Orgaaninen haku", "label.organic-shopping": "Orgaaninen ostaminen", "label.organic-social": "Orgaaninen sosiaalinen", diff --git a/src/lang/fo-FO.json b/src/lang/fo-FO.json index 0e5f60eb..e811ab5e 100644 --- a/src/lang/fo-FO.json +++ b/src/lang/fo-FO.json @@ -93,7 +93,6 @@ "label.events": "Hendingar/tiltøk", "label.exists": "Er til", "label.exit": "Útgangs URL", - "label.expand": "Víðka", "label.false": "Falskt", "label.field": "Øki", "label.fields": "Øki", @@ -146,6 +145,7 @@ "label.manage": "Stýra", "label.manager": "Stjóri", "label.max": "Mest", + "label.maximize": "Víðka", "label.medium": "Miðal", "label.member": "Limur", "label.members": "Limir", @@ -160,6 +160,7 @@ "label.none": "Eingin", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organisk leiting", "label.organic-shopping": "Organisk keyp", "label.organic-social": "Organisk sosial miðla", diff --git a/src/lang/fr-FR.json b/src/lang/fr-FR.json index e1f0e945..517633af 100644 --- a/src/lang/fr-FR.json +++ b/src/lang/fr-FR.json @@ -93,7 +93,6 @@ "label.events": "Évènements", "label.exists": "Existe", "label.exit": "Chemin de sortie", - "label.expand": "Développer", "label.false": "Faux", "label.field": "Champ", "label.fields": "Champs", @@ -146,6 +145,7 @@ "label.manage": "Gérer", "label.manager": "Gestionnaire", "label.max": "Max", + "label.maximize": "Développer", "label.medium": "Moyen", "label.member": "Membre", "label.members": "Membres", @@ -160,6 +160,7 @@ "label.none": "Aucun", "label.number-of-records": "{x} {x, plural, one {enregistrement} other {enregistrements}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Recherche organique", "label.organic-shopping": "Achat organique", "label.organic-social": "Réseau social organique", diff --git a/src/lang/ga-ES.json b/src/lang/ga-ES.json index a2b23cab..bce46d3b 100644 --- a/src/lang/ga-ES.json +++ b/src/lang/ga-ES.json @@ -93,7 +93,6 @@ "label.events": "Eventos", "label.exists": "Existe", "label.exit": "URL de saída", - "label.expand": "Expandir", "label.false": "Falso", "label.field": "Campo", "label.fields": "Campos", @@ -146,6 +145,7 @@ "label.manage": "Xestionar", "label.manager": "Xestor", "label.max": "Max", + "label.maximize": "Expandir", "label.medium": "Medio", "label.member": "Membro", "label.members": "Membros", @@ -160,6 +160,7 @@ "label.none": "Ningún", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Busca orgánica", "label.organic-shopping": "Compra orgánica", "label.organic-social": "Social orgánico", diff --git a/src/lang/he-IL.json b/src/lang/he-IL.json index 9de3af45..2345dc44 100644 --- a/src/lang/he-IL.json +++ b/src/lang/he-IL.json @@ -93,7 +93,6 @@ "label.events": "אירועים", "label.exists": "קיים", "label.exit": "כתובת יציאה", - "label.expand": "הרחב", "label.false": "שקר", "label.field": "שדה", "label.fields": "שדות", @@ -146,6 +145,7 @@ "label.manage": "נהל", "label.manager": "מנהל", "label.max": "מקסימום", + "label.maximize": "הרחב", "label.medium": "בינוני", "label.member": "חבר", "label.members": "חברים", @@ -160,6 +160,7 @@ "label.none": "ללא", "label.number-of-records": "{x} {x, plural, one {רשומה} other {רשומות}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "חיפוש אורגני", "label.organic-shopping": "קניות אורגניות", "label.organic-social": "רשת חברתית אורגנית", diff --git a/src/lang/hi-IN.json b/src/lang/hi-IN.json index d15c16ad..513d6742 100644 --- a/src/lang/hi-IN.json +++ b/src/lang/hi-IN.json @@ -93,7 +93,6 @@ "label.events": "स्पर्धाएँ", "label.exists": "मौजूद है", "label.exit": "निकास URL", - "label.expand": "विस्तार करें", "label.false": "गलत", "label.field": "फ़ील्ड", "label.fields": "फ़ील्ड्स", @@ -146,6 +145,7 @@ "label.manage": "प्रबंधित करें", "label.manager": "प्रबंधक", "label.max": "अधिकतम", + "label.maximize": "विस्तार करें", "label.medium": "मध्यम", "label.member": "सदस्य", "label.members": "सदस्यगण", @@ -160,6 +160,7 @@ "label.none": "कोई नहीं", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "ऑर्गेनिक खोज", "label.organic-shopping": "ऑर्गेनिक खरीदारी", "label.organic-social": "ऑर्गेनिक सोशल", diff --git a/src/lang/hr-HR.json b/src/lang/hr-HR.json index 17b6bbf9..c587e92e 100644 --- a/src/lang/hr-HR.json +++ b/src/lang/hr-HR.json @@ -93,7 +93,6 @@ "label.events": "Events", "label.exists": "Postoji", "label.exit": "Izlazni URL", - "label.expand": "Proširi", "label.false": "Netočno", "label.field": "Polje", "label.fields": "Polja", @@ -146,6 +145,7 @@ "label.manage": "Upravljaj", "label.manager": "Upravitelj", "label.max": "Maksimum", + "label.maximize": "Proširi", "label.medium": "Srednje", "label.member": "Član", "label.members": "Članovi", @@ -160,6 +160,7 @@ "label.none": "Nijedan", "label.number-of-records": "{x} {x, plural, one {zapis} other {zapisa}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organsko pretraživanje", "label.organic-shopping": "Organska kupovina", "label.organic-social": "Organska društvena mreža", diff --git a/src/lang/hu-HU.json b/src/lang/hu-HU.json index 58715069..67bafa61 100644 --- a/src/lang/hu-HU.json +++ b/src/lang/hu-HU.json @@ -93,7 +93,6 @@ "label.events": "Események", "label.exists": "Létezik", "label.exit": "Kilépési URL", - "label.expand": "Kibontás", "label.false": "Hamis", "label.field": "Mező", "label.fields": "Mezők", @@ -146,6 +145,7 @@ "label.manage": "Kezelés", "label.manager": "Menedzser", "label.max": "Maximum", + "label.maximize": "Kibontás", "label.medium": "Közepes", "label.member": "Tag", "label.members": "Tagok", @@ -160,6 +160,7 @@ "label.none": "Nincs", "label.number-of-records": "{x} {x, plural, one {rekord} other {rekord}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organikus keresés", "label.organic-shopping": "Organikus vásárlás", "label.organic-social": "Organikus közösségi", diff --git a/src/lang/id-ID.json b/src/lang/id-ID.json index 63114bb8..e7a26470 100644 --- a/src/lang/id-ID.json +++ b/src/lang/id-ID.json @@ -93,7 +93,6 @@ "label.events": "Peristiwa", "label.exists": "Ada", "label.exit": "Exit URL", - "label.expand": "Perluas", "label.false": "Salah", "label.field": "Kolom", "label.fields": "Kolom", @@ -146,6 +145,7 @@ "label.manage": "Kelola", "label.manager": "Manajer", "label.max": "Maksimum", + "label.maximize": "Perluas", "label.medium": "Sedang", "label.member": "Anggota", "label.members": "Anggota", @@ -160,6 +160,7 @@ "label.none": "Tidak ada", "label.number-of-records": "{x} {x, plural, one {catatan} other {catatan}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Pencarian organik", "label.organic-shopping": "Belanja organik", "label.organic-social": "Sosial organik", diff --git a/src/lang/it-IT.json b/src/lang/it-IT.json index fc16f2ea..019b4de5 100644 --- a/src/lang/it-IT.json +++ b/src/lang/it-IT.json @@ -93,7 +93,6 @@ "label.events": "Eventi", "label.exists": "Esiste", "label.exit": "URL di uscita", - "label.expand": "Espandi", "label.false": "Falso", "label.field": "Campo", "label.fields": "Campi", @@ -146,6 +145,7 @@ "label.manage": "Gestisci", "label.manager": "Manager", "label.max": "Massimo", + "label.maximize": "Espandi", "label.medium": "Medio", "label.member": "Membro", "label.members": "Membri", @@ -160,6 +160,7 @@ "label.none": "Nessuno", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Ricerca organica", "label.organic-shopping": "Acquisto organico", "label.organic-social": "Social organico", diff --git a/src/lang/ja-JP.json b/src/lang/ja-JP.json index 5e51efc4..2c6cc2f9 100644 --- a/src/lang/ja-JP.json +++ b/src/lang/ja-JP.json @@ -93,7 +93,6 @@ "label.events": "イベント", "label.exists": "存在する", "label.exit": "退出時のURL", - "label.expand": "展開", "label.false": "偽", "label.field": "フィールド", "label.fields": "フィールド", @@ -146,6 +145,7 @@ "label.manage": "管理", "label.manager": "管理者", "label.max": "最大", + "label.maximize": "展開", "label.medium": "メディア", "label.member": "メンバー", "label.members": "メンバー", @@ -160,6 +160,7 @@ "label.none": "なし", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "オーガニック検索", "label.organic-shopping": "オーガニックショッピング", "label.organic-social": "オーガニックソーシャル", diff --git a/src/lang/km-KH.json b/src/lang/km-KH.json index 79f3d14b..bae63986 100644 --- a/src/lang/km-KH.json +++ b/src/lang/km-KH.json @@ -93,7 +93,6 @@ "label.events": "ព្រឹត្តិការណ៍", "label.exists": "មាន", "label.exit": "URL ចេញ", - "label.expand": "ពង្រីក", "label.false": "មិនពិត", "label.field": "Field", "label.fields": "Fields", @@ -146,6 +145,7 @@ "label.manage": "គ្រប់គ្រង", "label.manager": "អ្នកគ្រប់គ្រង", "label.max": "Max", + "label.maximize": "ពង្រីក", "label.medium": "មធ្យម", "label.member": "សមាជិក", "label.members": "សមាជិក", @@ -160,6 +160,7 @@ "label.none": "គ្មាន", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "ស្វែងរកធម្មជាតិ", "label.organic-shopping": "ការទិញធម្មជាតិ", "label.organic-social": "សង្គមធម្មជាតិ", @@ -207,7 +208,6 @@ "label.required": "ទាមទារ", "label.reset": "កែសម្រួល", "label.reset-website": "ដើម្បីកែគេហទំព័រនេះឡើងវិញ សូមសរសេរ {confirmation} នៅក្នុងប្រអប់ខាងក្រោមដើម្បីបញ្ជាក់។", - "label.reset-website-warning": "ស្ថិតិទាំងអស់សម្រាប់គេហទំព័រនេះនឹងត្រូវបានលុប ប៉ុន្តែកូដតាមដានរបស់អ្នកនឹងនៅដដែល។", "label.retention": "ការរក្សាទុក", "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.revenue": "Revenue", diff --git a/src/lang/ko-KR.json b/src/lang/ko-KR.json index 4962ebf4..5826b1a4 100644 --- a/src/lang/ko-KR.json +++ b/src/lang/ko-KR.json @@ -93,7 +93,6 @@ "label.events": "이벤트", "label.exists": "존재함", "label.exit": "퇴장 URL", - "label.expand": "확장", "label.false": "거짓", "label.field": "필드", "label.fields": "필드", @@ -146,6 +145,7 @@ "label.manage": "관리", "label.manager": "관리자", "label.max": "최대", + "label.maximize": "확장", "label.medium": "미디엄", "label.member": "멤버", "label.members": "멤버", @@ -160,6 +160,7 @@ "label.none": "없음", "label.number-of-records": "{x}개 레코드", "label.ok": "확인", + "label.online": "Online", "label.organic-search": "자연 검색", "label.organic-shopping": "자연 쇼핑", "label.organic-social": "자연 소셜", diff --git a/src/lang/lt-LT.json b/src/lang/lt-LT.json index 8dc4f2f7..2fc89c2c 100644 --- a/src/lang/lt-LT.json +++ b/src/lang/lt-LT.json @@ -93,7 +93,6 @@ "label.events": "Įvykiai", "label.exists": "Egzistuoja", "label.exit": "Išėjimo URL", - "label.expand": "Išplėsti", "label.false": "Netiesa", "label.field": "Laukelis", "label.fields": "Laukeliai", @@ -146,6 +145,7 @@ "label.manage": "Tvarkyti", "label.manager": "Vadovas", "label.max": "Maksimumas", + "label.maximize": "Išplėsti", "label.medium": "Vidutinis", "label.member": "Narys", "label.members": "Nariai", @@ -160,6 +160,7 @@ "label.none": "Nėra", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organinė paieška", "label.organic-shopping": "Organinis apsipirkimas", "label.organic-social": "Organinis socialinis", diff --git a/src/lang/mn-MN.json b/src/lang/mn-MN.json index 03ad8a98..22e37bc4 100644 --- a/src/lang/mn-MN.json +++ b/src/lang/mn-MN.json @@ -93,7 +93,6 @@ "label.events": "Үйлдэл", "label.exists": "Байгаа", "label.exit": "Гарах зам", - "label.expand": "Өргөтгөх", "label.false": "Худал", "label.field": "Талбар", "label.fields": "Талбар", @@ -146,6 +145,7 @@ "label.manage": "Удирдах", "label.manager": "Удирдагч", "label.max": "Max", + "label.maximize": "Өргөтгөх", "label.medium": "Дунд", "label.member": "Гишүүн", "label.members": "Гишүүд", @@ -160,6 +160,7 @@ "label.none": "Байхгүй", "label.number-of-records": "{x} {x, plural, one {бичлэг} other {бичлэг}}", "label.ok": "ЗА", + "label.online": "Online", "label.organic-search": "Байгалийн хайлт", "label.organic-shopping": "Байгалийн дэлгүүр", "label.organic-social": "Байгалийн сошиал", diff --git a/src/lang/ms-MY.json b/src/lang/ms-MY.json index aef880b3..eb5976bd 100644 --- a/src/lang/ms-MY.json +++ b/src/lang/ms-MY.json @@ -93,7 +93,6 @@ "label.events": "Peristiwa", "label.exists": "Exists", "label.exit": "Exit URL", - "label.expand": "Expand", "label.false": "False", "label.field": "Field", "label.fields": "Fields", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Expand", "label.medium": "Medium", "label.member": "Member", "label.members": "Members", @@ -160,6 +160,7 @@ "label.none": "None", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organic search", "label.organic-shopping": "Organic shopping", "label.organic-social": "Organic social", diff --git a/src/lang/my-MM.json b/src/lang/my-MM.json index 3f1c6e5a..77f8e040 100644 --- a/src/lang/my-MM.json +++ b/src/lang/my-MM.json @@ -93,7 +93,6 @@ "label.events": "အဖြစ်အပျက်များ", "label.exists": "Exists", "label.exit": "Exit URL", - "label.expand": "Expand", "label.false": "မှားသည်", "label.field": "Field အမည်", "label.fields": "Field အမည်များ", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "အများဆုံး", + "label.maximize": "Expand", "label.medium": "Medium", "label.member": "Member", "label.members": "အဖွဲ့ဝင်များ", @@ -160,6 +160,7 @@ "label.none": "မရှိပါ", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organic search", "label.organic-shopping": "Organic shopping", "label.organic-social": "Organic social", diff --git a/src/lang/nb-NO.json b/src/lang/nb-NO.json index 51c88032..fc422256 100644 --- a/src/lang/nb-NO.json +++ b/src/lang/nb-NO.json @@ -93,7 +93,6 @@ "label.events": "Hendelser", "label.exists": "Eksisterer", "label.exit": "Utgangs-URL", - "label.expand": "Utvid", "label.false": "Usant", "label.field": "Felt", "label.fields": "Felt", @@ -146,6 +145,7 @@ "label.manage": "Administrer", "label.manager": "Administrator", "label.max": "Maks", + "label.maximize": "Utvid", "label.medium": "Medium", "label.member": "Bruker", "label.members": "Brukere", @@ -160,6 +160,7 @@ "label.none": "Ingen", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organisk søk", "label.organic-shopping": "Organisk handel", "label.organic-social": "Organisk sosial", diff --git a/src/lang/nl-NL.json b/src/lang/nl-NL.json index e199d7db..e48fa89e 100644 --- a/src/lang/nl-NL.json +++ b/src/lang/nl-NL.json @@ -93,7 +93,6 @@ "label.events": "Gebeurtenissen", "label.exists": "Bestaat", "label.exit": "Exit URL", - "label.expand": "Uitvouwen", "label.false": "Onwaar", "label.field": "Veld", "label.fields": "Velden", @@ -146,6 +145,7 @@ "label.manage": "Beheren", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Uitvouwen", "label.medium": "Medium", "label.member": "Gebruiker", "label.members": "Gebruikers", @@ -160,6 +160,7 @@ "label.none": "Geen", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organisch zoeken", "label.organic-shopping": "Organisch winkelen", "label.organic-social": "Organisch sociaal", diff --git a/src/lang/pl-PL.json b/src/lang/pl-PL.json index 5685b1e7..11c76763 100644 --- a/src/lang/pl-PL.json +++ b/src/lang/pl-PL.json @@ -93,7 +93,6 @@ "label.events": "Zdarzenia", "label.exists": "Istnieje", "label.exit": "URL wyjściowy", - "label.expand": "Rozwiń", "label.false": "Fałsz", "label.field": "Pole", "label.fields": "Pola", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Maks", + "label.maximize": "Rozwiń", "label.medium": "Medium", "label.member": "Członek", "label.members": "Członkowie", @@ -160,6 +160,7 @@ "label.none": "Brak", "label.number-of-records": "{x} {x, plural, one {rekord} other {rekordy}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Wyszukiwanie organiczne", "label.organic-shopping": "Zakupy organiczne", "label.organic-social": "Organiczne social media", diff --git a/src/lang/pt-BR.json b/src/lang/pt-BR.json index 263f8340..5ccd4869 100644 --- a/src/lang/pt-BR.json +++ b/src/lang/pt-BR.json @@ -93,7 +93,6 @@ "label.events": "Tipos de eventos", "label.exists": "Existe", "label.exit": "Exit URL", - "label.expand": "Expandir", "label.false": "Não", "label.field": "Campo", "label.fields": "Campos", @@ -146,6 +145,7 @@ "label.manage": "Gerenciar", "label.manager": "Manager", "label.max": "Máximo", + "label.maximize": "Expandir", "label.medium": "Médio", "label.member": "Membro", "label.members": "Membros", @@ -160,6 +160,7 @@ "label.none": "Nenhum", "label.number-of-records": "{x} {x, plural, one {registro} other {registros}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Busca orgânica", "label.organic-shopping": "Compras orgânicas", "label.organic-social": "Social orgânico", diff --git a/src/lang/pt-PT.json b/src/lang/pt-PT.json index 54569525..ba5b3b08 100644 --- a/src/lang/pt-PT.json +++ b/src/lang/pt-PT.json @@ -93,7 +93,6 @@ "label.events": "Eventos", "label.exists": "Existe", "label.exit": "URL de saída", - "label.expand": "Expandir", "label.false": "Falso", "label.field": "Campo", "label.fields": "Campos", @@ -146,6 +145,7 @@ "label.manage": "Gerir", "label.manager": "Gestor", "label.max": "Máximo", + "label.maximize": "Expandir", "label.medium": "Médio", "label.member": "Membro", "label.members": "Membros", @@ -160,6 +160,7 @@ "label.none": "Nenhum", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Pesquisa orgânica", "label.organic-shopping": "Compras orgânicas", "label.organic-social": "Social orgânico", diff --git a/src/lang/ro-RO.json b/src/lang/ro-RO.json index eaeecca3..54707048 100644 --- a/src/lang/ro-RO.json +++ b/src/lang/ro-RO.json @@ -93,7 +93,6 @@ "label.events": "Evenimente", "label.exists": "Există", "label.exit": "URL de ieșire", - "label.expand": "Extinde", "label.false": "Fals", "label.field": "Câmp", "label.fields": "Câmpuri", @@ -146,6 +145,7 @@ "label.manage": "Administrează", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Extinde", "label.medium": "Mediu", "label.member": "Membru", "label.members": "Membri", @@ -160,6 +160,7 @@ "label.none": "Niciunul", "label.number-of-records": "{x} {x, plural, one {înregistrare} other {înregistrări}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Căutare organică", "label.organic-shopping": "Cumpărături organice", "label.organic-social": "Social organic", diff --git a/src/lang/ru-RU.json b/src/lang/ru-RU.json index 3dce74e5..e63e66ab 100644 --- a/src/lang/ru-RU.json +++ b/src/lang/ru-RU.json @@ -93,7 +93,6 @@ "label.events": "События", "label.exists": "Существует", "label.exit": "URL-адрес выхода", - "label.expand": "Развернуть", "label.false": "Ложь", "label.field": "Поле", "label.fields": "Поля", @@ -146,6 +145,7 @@ "label.manage": "Управление", "label.manager": "Менеджер", "label.max": "Максимум", + "label.maximize": "Развернуть", "label.medium": "Средний", "label.member": "Участник", "label.members": "Участники", @@ -160,6 +160,7 @@ "label.none": "Не указано", "label.number-of-records": "{x} {x, plural, one {запись} other {записи}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Органический поиск", "label.organic-shopping": "Органические покупки", "label.organic-social": "Органические соцсети", diff --git a/src/lang/si-LK.json b/src/lang/si-LK.json index 7de3ec70..34de41de 100644 --- a/src/lang/si-LK.json +++ b/src/lang/si-LK.json @@ -93,7 +93,6 @@ "label.events": "Events", "label.exists": "Exists", "label.exit": "Exit URL", - "label.expand": "Expand", "label.false": "False", "label.field": "Field", "label.fields": "Fields", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Expand", "label.medium": "Medium", "label.member": "Member", "label.members": "Members", @@ -160,6 +160,7 @@ "label.none": "කිසිවක් නැත", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organic search", "label.organic-shopping": "Organic shopping", "label.organic-social": "Organic social", diff --git a/src/lang/sk-SK.json b/src/lang/sk-SK.json index 1b9e6033..ed182331 100644 --- a/src/lang/sk-SK.json +++ b/src/lang/sk-SK.json @@ -93,7 +93,6 @@ "label.events": "Udalosti", "label.exists": "Existuje", "label.exit": "Výstupná URL", - "label.expand": "Rozbaliť", "label.false": "Nepravda", "label.field": "Pole", "label.fields": "Polia", @@ -146,6 +145,7 @@ "label.manage": "Spravovať", "label.manager": "Manažér", "label.max": "Maximum", + "label.maximize": "Rozbaliť", "label.medium": "Stredný", "label.member": "Člen", "label.members": "Členovia", @@ -160,6 +160,7 @@ "label.none": "Žiadny", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organické vyhľadávanie", "label.organic-shopping": "Organické nakupovanie", "label.organic-social": "Organické sociálne siete", diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index 48599bf4..42295748 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -93,7 +93,6 @@ "label.events": "Dogodki", "label.exists": "Obstaja", "label.exit": "Exit URL", - "label.expand": "Razširi", "label.false": "Napačno", "label.field": "Polje", "label.fields": "Polja", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Največ", + "label.maximize": "Razširi", "label.medium": "Srednje", "label.member": "Član", "label.members": "Člani", @@ -160,6 +160,7 @@ "label.none": "Noben", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organsko iskanje", "label.organic-shopping": "Organski nakupi", "label.organic-social": "Organska družbena omrežja", diff --git a/src/lang/sv-SE.json b/src/lang/sv-SE.json index 8c7c96f2..18d216f2 100644 --- a/src/lang/sv-SE.json +++ b/src/lang/sv-SE.json @@ -93,7 +93,6 @@ "label.events": "Händelser", "label.exists": "Existerar", "label.exit": "Exit URL", - "label.expand": "Expandera", "label.false": "Falskt", "label.field": "Fält", "label.fields": "Fältar", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Expandera", "label.medium": "Medium", "label.member": "Medlem", "label.members": "Medlemmar", @@ -160,6 +160,7 @@ "label.none": "Ingen", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organisk sökning", "label.organic-shopping": "Organisk shopping", "label.organic-social": "Organisk social", diff --git a/src/lang/ta-IN.json b/src/lang/ta-IN.json index 652b00cd..ad992605 100644 --- a/src/lang/ta-IN.json +++ b/src/lang/ta-IN.json @@ -93,7 +93,6 @@ "label.events": "நிகழ்வுகள்", "label.exists": "Exists", "label.exit": "Exit URL", - "label.expand": "Expand", "label.false": "False", "label.field": "Field", "label.fields": "Fields", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Expand", "label.medium": "Medium", "label.member": "Member", "label.members": "Members", @@ -160,6 +160,7 @@ "label.none": "None", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organic search", "label.organic-shopping": "Organic shopping", "label.organic-social": "Organic social", diff --git a/src/lang/th-TH.json b/src/lang/th-TH.json index 694870b8..97df9fe3 100644 --- a/src/lang/th-TH.json +++ b/src/lang/th-TH.json @@ -93,7 +93,6 @@ "label.events": "เหตุการณ์", "label.exists": "Exists", "label.exit": "Exit URL", - "label.expand": "Expand", "label.false": "False", "label.field": "Field", "label.fields": "Fields", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Expand", "label.medium": "Medium", "label.member": "Member", "label.members": "Members", @@ -160,6 +160,7 @@ "label.none": "ไม่ได้กำหนด", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organic search", "label.organic-shopping": "Organic shopping", "label.organic-social": "Organic social", diff --git a/src/lang/tr-TR.json b/src/lang/tr-TR.json index 722a5ced..4f8af0b3 100644 --- a/src/lang/tr-TR.json +++ b/src/lang/tr-TR.json @@ -93,7 +93,6 @@ "label.events": "Olaylar", "label.exists": "Mevcut", "label.exit": "Exit URL", - "label.expand": "Genişlet", "label.false": "Yanlış", "label.field": "Alan", "label.fields": "Alanlar", @@ -146,6 +145,7 @@ "label.manage": "Yönet", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Genişlet", "label.medium": "Orta", "label.member": "Üye", "label.members": "Üyeler", @@ -160,6 +160,7 @@ "label.none": "Yok", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "TAMAM", + "label.online": "Online", "label.organic-search": "Organik arama", "label.organic-shopping": "Organik alışveriş", "label.organic-social": "Organik sosyal", diff --git a/src/lang/uk-UA.json b/src/lang/uk-UA.json index 530d8818..39c08db9 100644 --- a/src/lang/uk-UA.json +++ b/src/lang/uk-UA.json @@ -93,7 +93,6 @@ "label.events": "Події", "label.exists": "Існує", "label.exit": "Exit URL", - "label.expand": "Розгорнути", "label.false": "False", "label.field": "Поле", "label.fields": "Поля", @@ -146,6 +145,7 @@ "label.manage": "Керувати", "label.manager": "Manager", "label.max": "Макс.", + "label.maximize": "Розгорнути", "label.medium": "Середній", "label.member": "Учасник", "label.members": "Учасники", @@ -160,6 +160,7 @@ "label.none": "Нічого", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Органічний пошук", "label.organic-shopping": "Органічні покупки", "label.organic-social": "Органічні соцмережі", diff --git a/src/lang/ur-PK.json b/src/lang/ur-PK.json index f9ad263c..66f33b9f 100644 --- a/src/lang/ur-PK.json +++ b/src/lang/ur-PK.json @@ -93,7 +93,6 @@ "label.events": "واقعات", "label.exists": "Exists", "label.exit": "Exit URL", - "label.expand": "Expand", "label.false": "False", "label.field": "Field", "label.fields": "Fields", @@ -146,6 +145,7 @@ "label.manage": "Manage", "label.manager": "Manager", "label.max": "Max", + "label.maximize": "Expand", "label.medium": "Medium", "label.member": "Member", "label.members": "Members", @@ -160,6 +160,7 @@ "label.none": "None", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organic search", "label.organic-shopping": "Organic shopping", "label.organic-social": "Organic social", diff --git a/src/lang/vi-VN.json b/src/lang/vi-VN.json index 2e274177..6cc39735 100644 --- a/src/lang/vi-VN.json +++ b/src/lang/vi-VN.json @@ -93,7 +93,6 @@ "label.events": "Sự kiện", "label.exists": "Tồn tại", "label.exit": "URL thoát", - "label.expand": "Mở rộng", "label.false": "Sai", "label.field": "Trường", "label.fields": "Các trường", @@ -146,6 +145,7 @@ "label.manage": "Quản lý", "label.manager": "Quản lý viên", "label.max": "Tối đa", + "label.maximize": "Mở rộng", "label.medium": "Trung bình", "label.member": "Thành viên", "label.members": "Các thành viên", @@ -160,6 +160,7 @@ "label.none": "Không có", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Tìm kiếm tự nhiên", "label.organic-shopping": "Mua sắm tự nhiên", "label.organic-social": "Mạng xã hội tự nhiên", diff --git a/src/lang/zh-CN.json b/src/lang/zh-CN.json index ffa10261..894ac35c 100644 --- a/src/lang/zh-CN.json +++ b/src/lang/zh-CN.json @@ -93,7 +93,6 @@ "label.events": "行为类别", "label.exists": "存在", "label.exit": "退出 URL", - "label.expand": "展开", "label.false": "否", "label.field": "字段", "label.fields": "字段", @@ -146,6 +145,7 @@ "label.manage": "管理", "label.manager": "管理者", "label.max": "最大", + "label.maximize": "展开", "label.medium": "中等", "label.member": "成员", "label.members": "成员", @@ -160,6 +160,7 @@ "label.none": "无", "label.number-of-records": "{x} {x, plural, one {record} other {records}}", "label.ok": "好的", + "label.online": "Online", "label.organic-search": "自然搜索", "label.organic-shopping": "自然购物", "label.organic-social": "自然社交", diff --git a/src/lang/zh-TW.json b/src/lang/zh-TW.json index eb5ca269..7b19cb25 100644 --- a/src/lang/zh-TW.json +++ b/src/lang/zh-TW.json @@ -93,7 +93,6 @@ "label.events": "事件", "label.exists": "Exists", "label.exit": "離開網址", - "label.expand": "Expand", "label.false": "否", "label.field": "欄位", "label.fields": "欄位", @@ -146,6 +145,7 @@ "label.manage": "管理", "label.manager": "管理者", "label.max": "最大值", + "label.maximize": "Expand", "label.medium": "Medium", "label.member": "成員", "label.members": "成員", @@ -160,6 +160,7 @@ "label.none": "無", "label.number-of-records": "{x} 筆紀錄", "label.ok": "OK", + "label.online": "Online", "label.organic-search": "Organic search", "label.organic-shopping": "Organic shopping", "label.organic-social": "Organic social", From ee8750d9df65843006f8e73e88adee12ddaa704b Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 28 Jun 2025 21:16:50 -0700 Subject: [PATCH 109/399] Update Retention report. --- .../[websiteId]/WebsiteChart.module.css | 17 ---- .../WebsiteCompareTables.module.css | 14 --- .../websites/[websiteId]/WebsiteControls.tsx | 10 +- .../websites/[websiteId]/WebsiteHeader.tsx | 18 ++-- .../[websiteId]/WebsiteMetricsBar.module.css | 52 ---------- .../[websiteId]/events/EventsMetricsBar.tsx | 46 ++++----- .../[websiteId]/realtime/RealtimeLog.tsx | 10 +- .../[websiteId]/reports/ReportsNav.tsx | 8 +- .../reports/retention/Retention.tsx | 96 ++++++++++--------- .../reports/retention/RetentionPage.tsx | 10 +- .../sessions/SessionsMetricsBar.tsx | 46 ++++----- src/app/api/reports/retention/route.ts | 2 + src/components/common/Panel.tsx | 2 +- src/components/hooks/useDateRange.ts | 2 +- src/components/hooks/useFilterParams.ts | 4 +- src/components/input/DateFilter.tsx | 2 +- src/components/input/MonthSelect.tsx | 91 +++++++----------- src/components/input/WebsiteDateFilter.tsx | 2 +- src/components/input/WebsiteMonthSelect.tsx | 17 ++++ src/components/messages.ts | 4 +- src/lib/date.ts | 4 + src/queries/sql/reports/getRetention.ts | 37 +++---- 22 files changed, 214 insertions(+), 280 deletions(-) delete mode 100644 src/app/(main)/websites/[websiteId]/WebsiteChart.module.css delete mode 100644 src/app/(main)/websites/[websiteId]/WebsiteCompareTables.module.css delete mode 100644 src/app/(main)/websites/[websiteId]/WebsiteMetricsBar.module.css create mode 100644 src/components/input/WebsiteMonthSelect.tsx diff --git a/src/app/(main)/websites/[websiteId]/WebsiteChart.module.css b/src/app/(main)/websites/[websiteId]/WebsiteChart.module.css deleted file mode 100644 index b795047a..00000000 --- a/src/app/(main)/websites/[websiteId]/WebsiteChart.module.css +++ /dev/null @@ -1,17 +0,0 @@ -.container { - position: relative; - display: flex; - flex-direction: column; - align-self: stretch; -} - -.chart { - position: relative; - overflow: hidden; -} - -.title { - font-size: var(--font-size-lg); - line-height: 60px; - font-weight: 600; -} diff --git a/src/app/(main)/websites/[websiteId]/WebsiteCompareTables.module.css b/src/app/(main)/websites/[websiteId]/WebsiteCompareTables.module.css deleted file mode 100644 index c4821e88..00000000 --- a/src/app/(main)/websites/[websiteId]/WebsiteCompareTables.module.css +++ /dev/null @@ -1,14 +0,0 @@ -.container { - margin-bottom: 60px; -} - -.nav { - width: 200px; - margin-top: 40px; -} - -.title { - color: var(--base800); - text-align: center; - font-weight: 700; -} diff --git a/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx b/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx index fb84df87..1e36b729 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx @@ -2,23 +2,27 @@ import { Column, Row } from '@umami/react-zen'; import { WebsiteFilterButton } from '@/app/(main)/websites/[websiteId]/WebsiteFilterButton'; import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter'; import { FilterBar } from '@/components/input/FilterBar'; +import { WebsiteMonthSelect } from '@/components/input/WebsiteMonthSelect'; export function WebsiteControls({ websiteId, allowFilter = true, + allowDateFilter = true, + allowMonthFilter, allowCompare, }: { websiteId: string; allowFilter?: boolean; allowCompare?: boolean; + allowDateFilter?: boolean; + allowMonthFilter?: boolean; }) { return ( {allowFilter && } - - - + {allowDateFilter && } + {allowMonthFilter && } diff --git a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx index d0a17b7f..4c247dcd 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx @@ -14,15 +14,17 @@ export function WebsiteHeader() { return ( } showBorder={false}> - + - - - - - - Edit - + + + + + + + Edit + + ); diff --git a/src/app/(main)/websites/[websiteId]/WebsiteMetricsBar.module.css b/src/app/(main)/websites/[websiteId]/WebsiteMetricsBar.module.css deleted file mode 100644 index 6c5a0e56..00000000 --- a/src/app/(main)/websites/[websiteId]/WebsiteMetricsBar.module.css +++ /dev/null @@ -1,52 +0,0 @@ -.container { - display: grid; - grid-template-columns: 2fr 1fr; - justify-content: space-between; - align-items: center; - background: var(--base50); - z-index: var(--z-index-above); - min-height: 120px; - padding-bottom: 20px; -} - -.actions { - display: flex; - flex-direction: column; - align-items: flex-end; - gap: 10px; - flex-wrap: wrap; -} - -.vs { - display: flex; - align-items: center; - justify-content: flex-end; - flex-basis: 100%; - gap: 10px; -} - -.dropdown { - min-width: 200px; -} - -@media screen and (max-width: 1200px) { - .container { - grid-template-columns: 1fr; - } - - .actions { - margin: 20px 0; - } -} - -@media screen and (min-width: 992px) { - .sticky { - position: sticky; - top: -1px; - } - - .isSticky { - padding: 10px 0; - border-bottom: 1px solid var(--base300); - } -} diff --git a/src/app/(main)/websites/[websiteId]/events/EventsMetricsBar.tsx b/src/app/(main)/websites/[websiteId]/events/EventsMetricsBar.tsx index 5200ab16..2712c985 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsMetricsBar.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsMetricsBar.tsx @@ -11,28 +11,30 @@ export function EventsMetricsBar({ websiteId }: { websiteId: string }) { return ( - - - - - - + {data && ( + + + + + + + )} ); } diff --git a/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx b/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx index c46ef097..8e965528 100644 --- a/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx +++ b/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx @@ -67,7 +67,7 @@ export function RealtimeLog({ data }: { data: RealtimeData }) { country: string; device: string; }) => { - const { __type, eventName, urlPath: url, browser, os, country, device } = log; + const { __type, eventName, urlPath, browser, os, country, device } = log; if (__type === TYPE_EVENT) { return formatMessage(messages.eventLog, { @@ -75,12 +75,12 @@ export function RealtimeLog({ data }: { data: RealtimeData }) { url: ( - {url} + {urlPath} ), }); @@ -89,12 +89,12 @@ export function RealtimeLog({ data }: { data: RealtimeData }) { if (__type === TYPE_PAGEVIEW) { return ( - {url} + {urlPath} ); } diff --git a/src/app/(main)/websites/[websiteId]/reports/ReportsNav.tsx b/src/app/(main)/websites/[websiteId]/reports/ReportsNav.tsx index 6313ca46..f073a12d 100644 --- a/src/app/(main)/websites/[websiteId]/reports/ReportsNav.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/ReportsNav.tsx @@ -66,7 +66,13 @@ export function ReportsNav({ websiteId }: { websiteId: string }) { const isSelected = selected === id; return ( - + {icon} diff --git a/src/app/(main)/websites/[websiteId]/reports/retention/Retention.tsx b/src/app/(main)/websites/[websiteId]/reports/retention/Retention.tsx index 1667c483..b4bd01a7 100644 --- a/src/app/(main)/websites/[websiteId]/reports/retention/Retention.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/retention/Retention.tsx @@ -1,7 +1,7 @@ import { ReactNode } from 'react'; import { Grid, Row, Column, Text, Icon } from '@umami/react-zen'; import { Users } from '@/components/icons'; -import { useMessages, useLocale, useResultQuery } from '@/components/hooks'; +import { useMessages, useLocale, useResultQuery, useTimezone } from '@/components/hooks'; import { formatDate } from '@/lib/date'; import { formatLongNumber } from '@/lib/format'; import { Panel } from '@/components/common/Panel'; @@ -19,8 +19,10 @@ export interface RetentionProps { export function Retention({ websiteId, days = DAYS, startDate, endDate }: RetentionProps) { const { formatMessage, labels } = useMessages(); const { locale } = useLocale(); + const { timezone } = useTimezone(); const { data, error, isLoading } = useResultQuery('retention', { websiteId, + timezone, dateRange: { startDate, endDate, @@ -51,54 +53,56 @@ export function Retention({ websiteId, days = DAYS, startDate, endDate }: Retent return ( - - - - - - {formatMessage(labels.cohort)} - - - {days.map(n => ( - - - {formatMessage(labels.day)} {n} + {data && ( + + + + + + {formatMessage(labels.cohort)} - ))} - - {rows.map(({ date, visitors, records }: any, rowIndex: number) => { - return ( - - - {formatDate(date, 'PP', locale)} - - - - - {formatLongNumber(visitors)} - + {days.map(n => ( + + + {formatMessage(labels.day)} {n} + - {days.map(day => { - if (totalDays - rowIndex < day) { - return null; - } - const percentage = records.filter(a => a.day === day)[0]?.percentage; - return ( - {percentage ? `${Number(percentage).toFixed(2)}%` : ''} - ); - })} - - ); - })} - - + ))} + + {rows.map(({ date, visitors, records }: any, rowIndex: number) => { + return ( + + + {formatDate(date, 'PP', locale)} + + + + + {formatLongNumber(visitors)} + + + {days.map(day => { + if (totalDays - rowIndex < day) { + return null; + } + const percentage = records.filter(a => a.day === day)[0]?.percentage; + return ( + {percentage ? `${Number(percentage).toFixed(2)}%` : ''} + ); + })} + + ); + })} + + + )} ); } diff --git a/src/app/(main)/websites/[websiteId]/reports/retention/RetentionPage.tsx b/src/app/(main)/websites/[websiteId]/reports/retention/RetentionPage.tsx index 71ffc6fb..64cf6823 100644 --- a/src/app/(main)/websites/[websiteId]/reports/retention/RetentionPage.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/retention/RetentionPage.tsx @@ -3,16 +3,20 @@ import { Column } from '@umami/react-zen'; import { Retention } from './Retention'; import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls'; import { useDateRange } from '@/components/hooks'; +import { endOfMonth, startOfMonth } from 'date-fns'; export function RetentionPage({ websiteId }: { websiteId: string }) { const { - dateRange: { startDate, endDate }, + dateRange: { startDate }, } = useDateRange(websiteId); + const monthStartDate = startOfMonth(startDate); + const monthEndDate = endOfMonth(startDate); + return ( - - + + ); } diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsMetricsBar.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsMetricsBar.tsx index 1da45000..b959f0da 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsMetricsBar.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsMetricsBar.tsx @@ -11,28 +11,30 @@ export function SessionsMetricsBar({ websiteId }: { websiteId: string }) { return ( - - - - - - + {data && ( + + + + + + + )} ); } diff --git a/src/app/api/reports/retention/route.ts b/src/app/api/reports/retention/route.ts index 04842121..cc7433aa 100644 --- a/src/app/api/reports/retention/route.ts +++ b/src/app/api/reports/retention/route.ts @@ -14,6 +14,7 @@ export async function POST(request: Request) { const { websiteId, dateRange: { startDate, endDate }, + timezone, } = body; if (!(await canViewWebsite(auth, websiteId))) { @@ -23,6 +24,7 @@ export async function POST(request: Request) { const data = await getRetention(websiteId, { startDate: new Date(startDate), endDate: new Date(endDate), + timezone, }); return json(data); diff --git a/src/components/common/Panel.tsx b/src/components/common/Panel.tsx index 22f9ab9b..7341b3b5 100644 --- a/src/components/common/Panel.tsx +++ b/src/components/common/Panel.tsx @@ -62,7 +62,7 @@ export function Panel({ - {formatMessage(labels.expand)} + {formatMessage(labels.maximize)} )} diff --git a/src/components/hooks/useDateRange.ts b/src/components/hooks/useDateRange.ts index 6a6e16d4..795c4239 100644 --- a/src/components/hooks/useDateRange.ts +++ b/src/components/hooks/useDateRange.ts @@ -22,7 +22,7 @@ export function useDateRange(websiteId?: string) { ); const dateRange = useMemo( () => (offset ? getOffsetDateRange(dateRangeObject, +offset) : dateRangeObject), - [date, offset], + [date, offset, websiteConfig], ); const dateCompare = useWebsites(state => state[websiteId]?.dateCompare || DEFAULT_DATE_COMPARE); diff --git a/src/components/hooks/useFilterParams.ts b/src/components/hooks/useFilterParams.ts index 55deed14..bee2a649 100644 --- a/src/components/hooks/useFilterParams.ts +++ b/src/components/hooks/useFilterParams.ts @@ -8,7 +8,7 @@ export function useFilterParams(websiteId: string) { const { timezone, toUtc } = useTimezone(); const { query: { - url, + path, referrer, title, query, @@ -29,7 +29,7 @@ export function useFilterParams(websiteId: string) { endAt: +toUtc(endDate), unit, timezone, - url, + path, referrer, title, query, diff --git a/src/components/input/DateFilter.tsx b/src/components/input/DateFilter.tsx index 72be6c6d..3e2c00ed 100644 --- a/src/components/input/DateFilter.tsx +++ b/src/components/input/DateFilter.tsx @@ -99,7 +99,7 @@ export function DateFilter({ }; return ( - + + {months.map(m => { + return ( + + {formatDate(new Date(year, m, 1), 'MMMM', locale)} + + ); + })} + + ); } diff --git a/src/components/input/WebsiteDateFilter.tsx b/src/components/input/WebsiteDateFilter.tsx index afb58631..e78bcd8d 100644 --- a/src/components/input/WebsiteDateFilter.tsx +++ b/src/components/input/WebsiteDateFilter.tsx @@ -55,7 +55,7 @@ export function WebsiteDateFilter({ }; return ( - + {showButtons && !isAllTime && !isCustomRange && ( - - - - {fields.map(({ name, label }) => { - return ( - - {label} - - ); - })} - - - - - - - - + + + + + + {({ close }) => ( + + )} + + + + ); }; diff --git a/src/app/(main)/websites/[websiteId]/reports/breakdown/FieldSelectForm.tsx b/src/app/(main)/websites/[websiteId]/reports/breakdown/FieldSelectForm.tsx new file mode 100644 index 00000000..9d828c7d --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/reports/breakdown/FieldSelectForm.tsx @@ -0,0 +1,46 @@ +import { Column, List, ListItem, Grid, Button } from '@umami/react-zen'; +import { useFields, useMessages } from '@/components/hooks'; +import { useState } from 'react'; + +export function FieldSelectForm({ + selectedFields = [], + onChange, + onClose, +}: { + selectedFields?: string[]; + onChange: (values: string[]) => void; + onClose?: () => void; +}) { + const [selected, setSelected] = useState(selectedFields); + const { formatMessage, labels } = useMessages(); + const { fields } = useFields(); + + const handleChange = (value: string[]) => { + setSelected(value); + }; + + const handleApply = () => { + onChange?.(selected); + onClose(); + }; + + return ( + + + {fields.map(({ name, label }) => { + return ( + + {label} + + ); + })} + + + + + + + ); +} diff --git a/src/app/(main)/websites/[websiteId]/reports/goals/GoalEditForm.tsx b/src/app/(main)/websites/[websiteId]/reports/goals/GoalEditForm.tsx index b42545de..e1a3d97a 100644 --- a/src/app/(main)/websites/[websiteId]/reports/goals/GoalEditForm.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/goals/GoalEditForm.tsx @@ -69,7 +69,7 @@ export function GoalEditForm({ label={formatMessage(labels.name)} rules={{ required: formatMessage(labels.required) }} > - + ('retention', { websiteId, - timezone, dateRange: { startDate, endDate, + timezone, }, }); diff --git a/src/app/api/reports/breakdown/route.ts b/src/app/api/reports/breakdown/route.ts index 55a07369..de822f63 100644 --- a/src/app/api/reports/breakdown/route.ts +++ b/src/app/api/reports/breakdown/route.ts @@ -15,6 +15,7 @@ export async function POST(request: Request) { websiteId, dateRange: { startDate, endDate }, parameters: { fields }, + filters, } = body; if (!(await canViewWebsite(auth, websiteId))) { @@ -24,6 +25,7 @@ export async function POST(request: Request) { const data = await getBreakdown(websiteId, fields, { startDate: new Date(startDate), endDate: new Date(endDate), + ...filters, }); return json(data); diff --git a/src/app/api/reports/retention/route.ts b/src/app/api/reports/retention/route.ts index cc7433aa..76e54e9f 100644 --- a/src/app/api/reports/retention/route.ts +++ b/src/app/api/reports/retention/route.ts @@ -13,8 +13,7 @@ export async function POST(request: Request) { const { websiteId, - dateRange: { startDate, endDate }, - timezone, + dateRange: { startDate, endDate, timezone }, } = body; if (!(await canViewWebsite(auth, websiteId))) { diff --git a/src/components/common/Breadcrumb.module.css b/src/components/common/Breadcrumb.module.css deleted file mode 100644 index 81e7524f..00000000 --- a/src/components/common/Breadcrumb.module.css +++ /dev/null @@ -1,10 +0,0 @@ -.bar { - font-size: 12px; - font-weight: 700; - text-transform: uppercase; - color: var(--base600); -} - -.link span { - color: var(--base700) !important; -} diff --git a/src/components/common/Breadcrumb.tsx b/src/components/common/Breadcrumb.tsx deleted file mode 100644 index 163d33d9..00000000 --- a/src/components/common/Breadcrumb.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { Fragment } from 'react'; -import Link from 'next/link'; -import { Row, Icon, Text } from '@umami/react-zen'; -import { Chevron } from '@/components/icons'; -import styles from './Breadcrumb.module.css'; - -export interface BreadcrumbProps { - data: { - url?: string; - label: string; - }[]; -} - -export function Breadcrumb({ data }: BreadcrumbProps) { - return ( - - {data.map((a, i) => { - return ( - - {a.url ? ( - - {a.label} - - ) : ( - {a.label} - )} - {i !== data.length - 1 ? ( - - - - ) : null} - - ); - })} - - ); -} diff --git a/src/components/common/DataGrid.module.css b/src/components/common/DataGrid.module.css deleted file mode 100644 index 9a7cffb7..00000000 --- a/src/components/common/DataGrid.module.css +++ /dev/null @@ -1,34 +0,0 @@ -.search { - max-width: 300px; - margin: 20px 0; -} - -.body { - display: flex; - flex-direction: column; - position: relative; - overflow-x: auto; -} - -.body td { - display: flex; - gap: 10px; - min-height: 70px; - align-items: center; -} - -.body > div > div > div { - display: flex; - gap: 10px; -} - -.pager { - margin: 20px 0; -} - -.status { - display: flex; - align-items: center; - justify-content: center; - min-height: 200px; -} diff --git a/src/components/common/LinkButton.module.css b/src/components/common/LinkButton.module.css deleted file mode 100644 index bb23aeba..00000000 --- a/src/components/common/LinkButton.module.css +++ /dev/null @@ -1,107 +0,0 @@ -.button { - display: flex; - align-items: center; - align-self: flex-start; - white-space: nowrap; - gap: var(--size200); - font-family: inherit; - color: var(--base900); - background: var(--base100); - border: 1px solid transparent; - border-radius: var(--border-radius); - min-height: var(--base-height); - padding: 0 var(--size600); - position: relative; - cursor: pointer; -} - -.button:hover { - background: var(--base200); -} - -.button:active { - background: var(--base300); -} - -.button:visited { - color: var(--base900); -} - -.button.disabled { - color: var(--disabled-color) !important; - background-color: var(--disabled-background) !important; - border-color: transparent !important; - pointer-events: none; -} - -.button.primary { - color: var(--light50); - background: var(--primary-color); -} - -.button.primary:hover { - color: var(--light50); - background: var(--primary500); -} - -.button.primary:active { - color: var(--light50); - background: var(--primary600); -} - -.button.secondary { - border: 1px solid var(--border-color); - background: var(--base50); -} - -.button.secondary:hover { - background: var(--base75); -} - -.button.secondary:active { - background: var(--base100); -} - -.button.quiet { - color: var(--base900); - background: transparent; -} - -.button.quiet:hover { - background: var(--base100); -} - -.button.quiet:active { - background: var(--base200); -} - -.button.danger { - color: var(--light50); - background: var(--red800); -} - -.button.danger:hover { - color: var(--light50); - background: var(--red900); -} - -.button.danger:active { - color: var(--light50); - background: var(--red1000); -} - -.button.size-sm { - font-size: var(--font-size-sm); - height: calc(var(--base-height) * 0.75); - padding: 0 calc(var(--size600) * 0.75); -} - -.button.size-md { - font-size: var(--font-size-md); -} - -.button.size-lg { - font-size: var(--font-size-lg); - height: calc(var(--base-height) * 1.25); - padding: 0 calc(var(--size600) * 1.25); -} diff --git a/src/components/hooks/queries/useResultQuery.ts b/src/components/hooks/queries/useResultQuery.ts index be84193d..f4e3d5e7 100644 --- a/src/components/hooks/queries/useResultQuery.ts +++ b/src/components/hooks/queries/useResultQuery.ts @@ -1,4 +1,5 @@ -import { useApi } from '@/components/hooks'; +import { useApi } from '../useApi'; +import { useFilterParams } from '../useFilterParams'; import { ReactQueryOptions } from '@/lib/types'; export function useResultQuery( @@ -6,11 +7,21 @@ export function useResultQuery( params?: { [key: string]: any }, options?: ReactQueryOptions, ) { + const { websiteId } = params; const { post, useQuery } = useApi(); + const filterParams = useFilterParams(websiteId); return useQuery({ - queryKey: ['reports', type, params], - queryFn: () => post(`/reports/${type}`, { type, ...params }), + queryKey: [ + 'reports', + { + type, + websiteId, + ...filterParams, + ...params, + }, + ], + queryFn: () => post(`/reports/${type}`, { type, ...filterParams, ...params }), enabled: !!type, ...options, }); diff --git a/src/components/hooks/queries/useWebsiteMetricsQuery.ts b/src/components/hooks/queries/useWebsiteMetricsQuery.ts index 89adf818..5952de44 100644 --- a/src/components/hooks/queries/useWebsiteMetricsQuery.ts +++ b/src/components/hooks/queries/useWebsiteMetricsQuery.ts @@ -11,7 +11,7 @@ export type WebsiteMetricsData = { export function useWebsiteMetricsQuery( websiteId: string, - queryParams: { type: string; limit?: number; search?: string; startAt?: number; endAt?: number }, + params: { type: string; limit?: number; search?: string; startAt?: number; endAt?: number }, options?: ReactQueryOptions, ) { const { get, useQuery } = useApi(); @@ -24,14 +24,14 @@ export function useWebsiteMetricsQuery( { websiteId, ...filterParams, - ...queryParams, + ...params, }, ], queryFn: async () => get(`/websites/${websiteId}/metrics`, { ...filterParams, [searchParams.get('view')]: undefined, - ...queryParams, + ...params, }), enabled: !!websiteId, placeholderData: keepPreviousData, diff --git a/src/components/icons.ts b/src/components/icons.ts index d57d36a9..c566e4b3 100644 --- a/src/components/icons.ts +++ b/src/components/icons.ts @@ -10,6 +10,7 @@ export { Download, Edit, Ellipsis, + Equal, Eye, ExternalLink, File, @@ -20,6 +21,7 @@ export { KeyRound, LayoutDashboard, Link, + ListCheck, ListFilter, LockKeyhole, LogOut, diff --git a/src/lib/schema.ts b/src/lib/schema.ts index fd2e3f8d..fb51c8e4 100644 --- a/src/lib/schema.ts +++ b/src/lib/schema.ts @@ -88,7 +88,8 @@ export const reportParms = { endDate: z.coerce.date(), num: z.coerce.number().optional(), offset: z.coerce.number().optional(), - unit: z.string().optional(), + timezone: timezoneParam.optional(), + unit: unitParam.optional(), value: z.string().optional(), }), }; diff --git a/src/lib/types.ts b/src/lib/types.ts index 3373be34..f6f2c8a1 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -68,7 +68,7 @@ export interface QueryFilters { timezone?: string; unit?: string; eventType?: number; - url?: string; + path?: string; referrer?: string; title?: string; query?: string; diff --git a/src/queries/sql/reports/getRetention.ts b/src/queries/sql/reports/getRetention.ts index 924930db..5e871500 100644 --- a/src/queries/sql/reports/getRetention.ts +++ b/src/queries/sql/reports/getRetention.ts @@ -108,7 +108,7 @@ async function clickhouseQuery( user_activities AS ( select distinct w.session_id, - (${getDateSQL('created_at', unit)} - c.cohort_date) / 86400 as day_number + (${getDateSQL('created_at', unit, timezone)} - c.cohort_date) / 86400 as day_number from website_event w join cohort_items c on w.session_id = c.session_id From 8b64029409f4a5de5c05291126c95dd58ddd4636 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sun, 29 Jun 2025 23:57:11 -0700 Subject: [PATCH 111/399] Made filters work for all reports. --- .../websites/[websiteId]/WebsiteControls.tsx | 2 +- .../[websiteId]/reports/ReportsNav.tsx | 2 +- .../reports/attribution/Attribution.tsx | 120 +++++++++--------- .../reports/revenue/RevenuePage.tsx | 2 +- .../websites/[websiteId]/reports/utm/UTM.tsx | 82 ++++++------ src/app/api/reports/attribution/route.ts | 2 + src/app/api/reports/breakdown/route.ts | 4 +- src/app/api/reports/funnel/route.ts | 2 + src/app/api/reports/goal/route.ts | 6 +- src/app/api/reports/journey/route.ts | 2 + src/app/api/reports/retention/route.ts | 2 + src/app/api/reports/revenue/route.ts | 2 + src/app/api/reports/utm/route.ts | 2 + .../hooks/queries/useResultQuery.ts | 6 +- src/components/hooks/useFilterParams.ts | 2 + src/components/hooks/usePagedQuery.ts | 2 +- src/components/metrics/WorldMap.tsx | 16 +-- src/lib/clickhouse.ts | 2 +- src/lib/prisma.ts | 2 +- src/queries/sql/events/getEventDataEvents.ts | 12 +- src/queries/sql/events/getEventDataFields.ts | 14 +- .../sql/events/getEventDataProperties.ts | 8 +- src/queries/sql/events/getEventDataStats.ts | 8 +- src/queries/sql/events/getEventDataValues.ts | 15 ++- src/queries/sql/events/getEventMetrics.ts | 8 +- src/queries/sql/events/getWebsiteEvents.ts | 8 +- src/queries/sql/getChannelMetrics.ts | 8 +- src/queries/sql/getRealtimeActivity.ts | 8 +- src/queries/sql/getWebsiteDateRange.ts | 12 +- src/queries/sql/getWebsiteStats.ts | 8 +- .../sql/pageviews/getPageviewMetrics.ts | 8 +- src/queries/sql/pageviews/getPageviewStats.ts | 8 +- src/queries/sql/reports/getAttribution.ts | 105 ++++++++------- src/queries/sql/reports/getBreakdown.ts | 8 +- src/queries/sql/reports/getFunnel.ts | 5 +- src/queries/sql/reports/getGoal.ts | 8 +- src/queries/sql/reports/getJourney.ts | 10 +- src/queries/sql/reports/getRetention.ts | 12 +- src/queries/sql/reports/getUTM.ts | 10 +- .../sql/sessions/getSessionDataProperties.ts | 12 +- .../sql/sessions/getSessionDataValues.ts | 8 +- src/queries/sql/sessions/getSessionMetrics.ts | 8 +- src/queries/sql/sessions/getSessionStats.ts | 8 +- .../sql/sessions/getWebsiteSessionStats.ts | 8 +- .../sql/sessions/getWebsiteSessions.ts | 8 +- .../sql/sessions/getWebsiteSessionsWeekly.ts | 8 +- 46 files changed, 328 insertions(+), 275 deletions(-) diff --git a/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx b/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx index 97fabf2a..655e8ea0 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx @@ -24,7 +24,7 @@ export function WebsiteControls({ {allowDateFilter && } {allowMonthFilter && } - + {allowFilter && } ); } diff --git a/src/app/(main)/websites/[websiteId]/reports/ReportsNav.tsx b/src/app/(main)/websites/[websiteId]/reports/ReportsNav.tsx index f073a12d..3741bc53 100644 --- a/src/app/(main)/websites/[websiteId]/reports/ReportsNav.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/ReportsNav.tsx @@ -70,7 +70,7 @@ export function ReportsNav({ websiteId }: { websiteId: string }) { key={id} href={renderUrl( `/websites/${websiteId}/reports${path}`, - path === '/retention' ? false : null, + path === '/retention' ? { date: undefined } : null, )} > diff --git a/src/app/(main)/websites/[websiteId]/reports/attribution/Attribution.tsx b/src/app/(main)/websites/[websiteId]/reports/attribution/Attribution.tsx index ae56329a..87ea170d 100644 --- a/src/app/(main)/websites/[websiteId]/reports/attribution/Attribution.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/attribution/Attribution.tsx @@ -48,8 +48,8 @@ export function Attribution({ const metrics = data ? [ { - value: pageviews, - label: formatMessage(labels.views), + value: visitors, + label: formatMessage(labels.visitors), formatValue: formatLongNumber, }, { @@ -58,8 +58,8 @@ export function Attribution({ formatValue: formatLongNumber, }, { - value: visitors, - label: formatMessage(labels.visitors), + value: pageviews, + label: formatMessage(labels.views), formatValue: formatLongNumber, }, ] @@ -83,60 +83,64 @@ export function Attribution({ return ( - - - {metrics?.map(({ label, value, formatValue }) => { - return ; - })} - - - - - ({ - x: name, - y: Number(value), - })), - )} - /> - - - ({ - x: name, - y: Number(value), - })), - )} - /> - - - - - - - - - - - - - - - - - - - - - + {data && ( + + + {metrics?.map(({ label, value, formatValue }) => { + return ( + + ); + })} + + + + + ({ + x: name, + y: Number(value), + })), + )} + /> + + + ({ + x: name, + y: Number(value), + })), + )} + /> + + + + + + + + + + + + + + + + + + + + + + )} ); } diff --git a/src/app/(main)/websites/[websiteId]/reports/revenue/RevenuePage.tsx b/src/app/(main)/websites/[websiteId]/reports/revenue/RevenuePage.tsx index 4c5998d5..9232d7be 100644 --- a/src/app/(main)/websites/[websiteId]/reports/revenue/RevenuePage.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/revenue/RevenuePage.tsx @@ -11,7 +11,7 @@ export function RevenuePage({ websiteId }: { websiteId: string }) { return ( - + ); diff --git a/src/app/(main)/websites/[websiteId]/reports/utm/UTM.tsx b/src/app/(main)/websites/[websiteId]/reports/utm/UTM.tsx index fa9383e1..afa8c842 100644 --- a/src/app/(main)/websites/[websiteId]/reports/utm/UTM.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/utm/UTM.tsx @@ -26,47 +26,49 @@ export function UTM({ websiteId, startDate, endDate }: UTMProps) { return ( - - {UTM_PARAMS.map(param => { - const items = toArray(data?.[param]); - const chartData = { - labels: items.map(({ name }) => name), - datasets: [ - { - data: items.map(({ value }) => value), - backgroundColor: CHART_COLORS, - borderWidth: 0, - }, - ], - }; - const total = items.reduce((sum, { value }) => { - return +sum + +value; - }, 0); + {data && ( + + {UTM_PARAMS.map(param => { + const items = toArray(data?.[param]); + const chartData = { + labels: items.map(({ name }) => name), + datasets: [ + { + data: items.map(({ value }) => value), + backgroundColor: CHART_COLORS, + borderWidth: 0, + }, + ], + }; + const total = items.reduce((sum, { value }) => { + return +sum + +value; + }, 0); - return ( - - - - - {param.replace(/^utm_/, '')} - - ({ - x: name, - y: value, - z: (value / total) * 100, - }))} - /> - - - - - - - ); - })} - + return ( + + + + + {param.replace(/^utm_/, '')} + + ({ + x: name, + y: value, + z: (value / total) * 100, + }))} + /> + + + + + + + ); + })} + + )} ); } diff --git a/src/app/api/reports/attribution/route.ts b/src/app/api/reports/attribution/route.ts index ef6f8650..e8384895 100644 --- a/src/app/api/reports/attribution/route.ts +++ b/src/app/api/reports/attribution/route.ts @@ -15,6 +15,7 @@ export async function POST(request: Request) { websiteId, dateRange: { startDate, endDate }, parameters: { model, type, step, currency }, + ...filters } = body; if (!(await canViewWebsite(auth, websiteId))) { @@ -22,6 +23,7 @@ export async function POST(request: Request) { } const data = await getAttribution(websiteId, { + ...filters, startDate: new Date(startDate), endDate: new Date(endDate), model, diff --git a/src/app/api/reports/breakdown/route.ts b/src/app/api/reports/breakdown/route.ts index de822f63..d97a552c 100644 --- a/src/app/api/reports/breakdown/route.ts +++ b/src/app/api/reports/breakdown/route.ts @@ -15,7 +15,7 @@ export async function POST(request: Request) { websiteId, dateRange: { startDate, endDate }, parameters: { fields }, - filters, + ...filters } = body; if (!(await canViewWebsite(auth, websiteId))) { @@ -23,9 +23,9 @@ export async function POST(request: Request) { } const data = await getBreakdown(websiteId, fields, { + ...filters, startDate: new Date(startDate), endDate: new Date(endDate), - ...filters, }); return json(data); diff --git a/src/app/api/reports/funnel/route.ts b/src/app/api/reports/funnel/route.ts index 7c50b8aa..335776bf 100644 --- a/src/app/api/reports/funnel/route.ts +++ b/src/app/api/reports/funnel/route.ts @@ -15,6 +15,7 @@ export async function POST(request: Request) { websiteId, dateRange: { startDate, endDate }, parameters: { steps, window }, + ...filters } = body; if (!(await canViewWebsite(auth, websiteId))) { @@ -22,6 +23,7 @@ export async function POST(request: Request) { } const data = await getFunnel(websiteId, { + ...filters, startDate: new Date(startDate), endDate: new Date(endDate), steps, diff --git a/src/app/api/reports/goal/route.ts b/src/app/api/reports/goal/route.ts index bbf0f229..fe893571 100644 --- a/src/app/api/reports/goal/route.ts +++ b/src/app/api/reports/goal/route.ts @@ -15,6 +15,7 @@ export async function POST(request: Request) { websiteId, dateRange: { startDate, endDate }, parameters: { type, value, property, operator }, + ...filters } = body; if (!(await canViewWebsite(auth, websiteId))) { @@ -22,12 +23,13 @@ export async function POST(request: Request) { } const data = await getGoal(websiteId, { + ...filters, + startDate: new Date(startDate), + endDate: new Date(endDate), type, value, property, operator, - startDate: new Date(startDate), - endDate: new Date(endDate), }); return json(data); diff --git a/src/app/api/reports/journey/route.ts b/src/app/api/reports/journey/route.ts index 130a494e..20675bdf 100644 --- a/src/app/api/reports/journey/route.ts +++ b/src/app/api/reports/journey/route.ts @@ -15,6 +15,7 @@ export async function POST(request: Request) { websiteId, dateRange: { startDate, endDate }, parameters: { steps, startStep, endStep }, + ...filters } = body; if (!(await canViewWebsite(auth, websiteId))) { @@ -22,6 +23,7 @@ export async function POST(request: Request) { } const data = await getJourney(websiteId, { + ...filters, startDate: new Date(startDate), endDate: new Date(endDate), steps, diff --git a/src/app/api/reports/retention/route.ts b/src/app/api/reports/retention/route.ts index 76e54e9f..b569e13a 100644 --- a/src/app/api/reports/retention/route.ts +++ b/src/app/api/reports/retention/route.ts @@ -14,6 +14,7 @@ export async function POST(request: Request) { const { websiteId, dateRange: { startDate, endDate, timezone }, + ...filters } = body; if (!(await canViewWebsite(auth, websiteId))) { @@ -21,6 +22,7 @@ export async function POST(request: Request) { } const data = await getRetention(websiteId, { + ...filters, startDate: new Date(startDate), endDate: new Date(endDate), timezone, diff --git a/src/app/api/reports/revenue/route.ts b/src/app/api/reports/revenue/route.ts index fbec6bca..ff4f4de4 100644 --- a/src/app/api/reports/revenue/route.ts +++ b/src/app/api/reports/revenue/route.ts @@ -15,6 +15,7 @@ export async function POST(request: Request) { websiteId, dateRange: { startDate, endDate, unit }, parameters: { currency }, + ...filters } = body; if (!(await canViewWebsite(auth, websiteId))) { @@ -22,6 +23,7 @@ export async function POST(request: Request) { } const data = await getRevenue(websiteId, { + ...filters, startDate: new Date(startDate), endDate: new Date(endDate), unit, diff --git a/src/app/api/reports/utm/route.ts b/src/app/api/reports/utm/route.ts index 36a434ad..a2845b25 100644 --- a/src/app/api/reports/utm/route.ts +++ b/src/app/api/reports/utm/route.ts @@ -14,6 +14,7 @@ export async function POST(request: Request) { const { websiteId, dateRange: { startDate, endDate }, + ...filters } = body; if (!(await canViewWebsite(auth, websiteId))) { @@ -21,6 +22,7 @@ export async function POST(request: Request) { } const data = await getUTM(websiteId, { + ...filters, startDate: new Date(startDate), endDate: new Date(endDate), }); diff --git a/src/components/hooks/queries/useResultQuery.ts b/src/components/hooks/queries/useResultQuery.ts index f4e3d5e7..e82e4519 100644 --- a/src/components/hooks/queries/useResultQuery.ts +++ b/src/components/hooks/queries/useResultQuery.ts @@ -9,7 +9,7 @@ export function useResultQuery( ) { const { websiteId } = params; const { post, useQuery } = useApi(); - const filterParams = useFilterParams(websiteId); + const filters = useFilterParams(websiteId); return useQuery({ queryKey: [ @@ -17,11 +17,11 @@ export function useResultQuery( { type, websiteId, - ...filterParams, + ...filters, ...params, }, ], - queryFn: () => post(`/reports/${type}`, { type, ...filterParams, ...params }), + queryFn: () => post(`/reports/${type}`, { type, ...filters, ...params }), enabled: !!type, ...options, }); diff --git a/src/components/hooks/useFilterParams.ts b/src/components/hooks/useFilterParams.ts index bee2a649..f725eb80 100644 --- a/src/components/hooks/useFilterParams.ts +++ b/src/components/hooks/useFilterParams.ts @@ -21,6 +21,7 @@ export function useFilterParams(websiteId: string) { city, event, tag, + hostname, }, } = useNavigation(); @@ -42,5 +43,6 @@ export function useFilterParams(websiteId: string) { city, event, tag, + hostname, }; } diff --git a/src/components/hooks/usePagedQuery.ts b/src/components/hooks/usePagedQuery.ts index 06b0e211..1f85afc0 100644 --- a/src/components/hooks/usePagedQuery.ts +++ b/src/components/hooks/usePagedQuery.ts @@ -25,7 +25,7 @@ export function usePagedQuery({ return { result: data as PageResult, query, - params, + filterParams: params, setParams, }; } diff --git a/src/components/metrics/WorldMap.tsx b/src/components/metrics/WorldMap.tsx index b3908698..76ec1abc 100644 --- a/src/components/metrics/WorldMap.tsx +++ b/src/components/metrics/WorldMap.tsx @@ -1,5 +1,5 @@ -import { FloatingTooltip, Column, useTheme } from '@umami/react-zen'; -import { useState, useMemo, HTMLAttributes } from 'react'; +import { FloatingTooltip, Column, useTheme, ColumnProps } from '@umami/react-zen'; +import { useState, useMemo } from 'react'; import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps'; import classNames from 'classnames'; import { colord } from 'colord'; @@ -16,16 +16,12 @@ import { percentFilter } from '@/lib/filters'; import styles from './WorldMap.module.css'; import { getThemeColors } from '@/lib/colors'; -export function WorldMap({ - websiteId, - data, - className, - ...props -}: { +export interface WorldMapProps extends ColumnProps { websiteId?: string; data?: any[]; - className?: string; -} & HTMLAttributes) { +} + +export function WorldMap({ websiteId, data, className, ...props }: WorldMapProps) { const [tooltip, setTooltipPopup] = useState(); const { theme } = useTheme(); const { colors } = getThemeColors(theme); diff --git a/src/lib/clickhouse.ts b/src/lib/clickhouse.ts index 38b93975..f59058cf 100644 --- a/src/lib/clickhouse.ts +++ b/src/lib/clickhouse.ts @@ -141,7 +141,7 @@ async function parseFilters(websiteId: string, filters: QueryFilters = {}, optio return { filterQuery: getFilterQuery(filters, options), dateQuery: getDateQuery(filters), - params: { + filterParams: { ...getFilterParams(filters), websiteId, startDate: maxDate(filters.startDate, new Date(website?.resetAt)), diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index ecbe3e53..89728bb5 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -215,7 +215,7 @@ async function parseFilters( : '', filterQuery: getFilterQuery(filters, options), dateQuery: getDateQuery(filters), - params: { + filterParams: { ...getFilterParams(filters), websiteId, startDate: maxDate(filters.startDate, website?.resetAt), diff --git a/src/queries/sql/events/getEventDataEvents.ts b/src/queries/sql/events/getEventDataEvents.ts index 83a5c319..1922edab 100644 --- a/src/queries/sql/events/getEventDataEvents.ts +++ b/src/queries/sql/events/getEventDataEvents.ts @@ -23,7 +23,7 @@ export async function getEventDataEvents( async function relationalQuery(websiteId: string, filters: QueryFilters) { const { rawQuery, parseFilters } = prisma; const { event } = filters; - const { params } = await parseFilters(websiteId, filters); + const { filterParams } = await parseFilters(websiteId, filters); if (event) { return rawQuery( @@ -43,7 +43,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { group by website_event.event_name, event_data.data_key, event_data.data_type, event_data.string_value order by 1 asc, 2 asc, 3 asc, 5 desc `, - params, + filterParams, ); } @@ -63,7 +63,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { order by 1 asc, 2 asc limit 500 `, - params, + filterParams, ); } @@ -73,7 +73,7 @@ async function clickhouseQuery( ): Promise<{ eventName: string; propertyName: string; dataType: number; total: number }[]> { const { rawQuery, parseFilters } = clickhouse; const { event } = filters; - const { params } = await parseFilters(websiteId, filters); + const { filterParams } = await parseFilters(websiteId, filters); if (event) { return rawQuery( @@ -92,7 +92,7 @@ async function clickhouseQuery( order by 1 asc, 2 asc, 3 asc, 5 desc limit 500 `, - params, + filterParams, ); } @@ -110,6 +110,6 @@ async function clickhouseQuery( order by 1 asc, 2 asc limit 500 `, - params, + filterParams, ); } diff --git a/src/queries/sql/events/getEventDataFields.ts b/src/queries/sql/events/getEventDataFields.ts index 33b4e0f5..266c50ad 100644 --- a/src/queries/sql/events/getEventDataFields.ts +++ b/src/queries/sql/events/getEventDataFields.ts @@ -1,11 +1,9 @@ import prisma from '@/lib/prisma'; import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; -import { QueryFilters, WebsiteEventData } from '@/lib/types'; +import { QueryFilters } from '@/lib/types'; -export async function getEventDataFields( - ...args: [websiteId: string, filters: QueryFilters] -): Promise { +export async function getEventDataFields(...args: [websiteId: string, filters: QueryFilters]) { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), @@ -14,7 +12,7 @@ export async function getEventDataFields( async function relationalQuery(websiteId: string, filters: QueryFilters) { const { rawQuery, parseFilters, getDateSQL } = prisma; - const { filterQuery, params } = await parseFilters(websiteId, filters); + const { filterQuery, filterParams } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -36,7 +34,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { order by 2 desc limit 100 `, - params, + filterParams, ); } @@ -45,7 +43,7 @@ async function clickhouseQuery( filters: QueryFilters, ): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, filters); + const { filterQuery, filterParams } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -64,6 +62,6 @@ async function clickhouseQuery( order by 2 desc limit 100 `, - params, + filterParams, ); } diff --git a/src/queries/sql/events/getEventDataProperties.ts b/src/queries/sql/events/getEventDataProperties.ts index 73fb8fec..5781df82 100644 --- a/src/queries/sql/events/getEventDataProperties.ts +++ b/src/queries/sql/events/getEventDataProperties.ts @@ -17,7 +17,7 @@ async function relationalQuery( filters: QueryFilters & { propertyName?: string }, ) { const { rawQuery, parseFilters } = prisma; - const { filterQuery, params } = await parseFilters(websiteId, filters, { + const { filterQuery, filterParams } = await parseFilters(websiteId, filters, { columns: { propertyName: 'data_key' }, }); @@ -36,7 +36,7 @@ async function relationalQuery( order by 3 desc limit 500 `, - params, + filterParams, ); } @@ -45,7 +45,7 @@ async function clickhouseQuery( filters: QueryFilters & { propertyName?: string }, ): Promise<{ eventName: string; propertyName: string; total: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, filters, { + const { filterQuery, filterParams } = await parseFilters(websiteId, filters, { columns: { propertyName: 'data_key' }, }); @@ -63,6 +63,6 @@ async function clickhouseQuery( order by 1, 3 desc limit 500 `, - params, + filterParams, ); } diff --git a/src/queries/sql/events/getEventDataStats.ts b/src/queries/sql/events/getEventDataStats.ts index 98347960..fd9b7a8b 100644 --- a/src/queries/sql/events/getEventDataStats.ts +++ b/src/queries/sql/events/getEventDataStats.ts @@ -18,7 +18,7 @@ export async function getEventDataStats( async function relationalQuery(websiteId: string, filters: QueryFilters) { const { rawQuery, parseFilters } = prisma; - const { filterQuery, params } = await parseFilters(websiteId, filters); + const { filterQuery, filterParams } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -38,7 +38,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { group by website_event_id, data_key ) as t `, - params, + filterParams, ); } @@ -47,7 +47,7 @@ async function clickhouseQuery( filters: QueryFilters, ): Promise<{ events: number; properties: number; records: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, filters); + const { filterQuery, filterParams } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -67,6 +67,6 @@ async function clickhouseQuery( group by event_id, data_key ) as t `, - params, + filterParams, ); } diff --git a/src/queries/sql/events/getEventDataValues.ts b/src/queries/sql/events/getEventDataValues.ts index c8d63362..5041bdc3 100644 --- a/src/queries/sql/events/getEventDataValues.ts +++ b/src/queries/sql/events/getEventDataValues.ts @@ -1,7 +1,12 @@ import prisma from '@/lib/prisma'; import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; -import { QueryFilters, WebsiteEventData } from '@/lib/types'; +import { QueryFilters } from '@/lib/types'; + +export interface WebsiteEventData { + value: string; + total: number; +} export async function getEventDataValues( ...args: [ @@ -20,7 +25,7 @@ async function relationalQuery( filters: QueryFilters & { eventName?: string; propertyName?: string }, ) { const { rawQuery, parseFilters, getDateSQL } = prisma; - const { filterQuery, params } = await parseFilters(websiteId, filters); + const { filterQuery, filterParams } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -42,7 +47,7 @@ async function relationalQuery( order by 2 desc limit 100 `, - params, + filterParams, ); } @@ -51,7 +56,7 @@ async function clickhouseQuery( filters: QueryFilters & { eventName?: string; propertyName?: string }, ): Promise<{ value: string; total: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, filters); + const { filterQuery, filterParams } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -70,6 +75,6 @@ async function clickhouseQuery( order by 2 desc limit 100 `, - params, + filterParams, ); } diff --git a/src/queries/sql/events/getEventMetrics.ts b/src/queries/sql/events/getEventMetrics.ts index e777e907..39e6003a 100644 --- a/src/queries/sql/events/getEventMetrics.ts +++ b/src/queries/sql/events/getEventMetrics.ts @@ -22,7 +22,7 @@ export async function getEventMetrics( async function relationalQuery(websiteId: string, filters: QueryFilters) { const { timezone = 'utc', unit = 'day' } = filters; const { rawQuery, getDateSQL, parseFilters } = prisma; - const { filterQuery, joinSession, params } = await parseFilters(websiteId, { + const { filterQuery, joinSession, filterParams } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.customEvent, }); @@ -42,7 +42,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { group by 1, 2 order by 2 `, - params, + filterParams, ); } @@ -52,7 +52,7 @@ async function clickhouseQuery( ): Promise<{ x: string; t: string; y: number }[]> { const { timezone = 'UTC', unit = 'day' } = filters; const { rawQuery, getDateSQL, parseFilters } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.customEvent, }); @@ -92,5 +92,5 @@ async function clickhouseQuery( `; } - return rawQuery(sql, params); + return rawQuery(sql, filterParams); } diff --git a/src/queries/sql/events/getWebsiteEvents.ts b/src/queries/sql/events/getWebsiteEvents.ts index 9ec24a8a..31787873 100644 --- a/src/queries/sql/events/getWebsiteEvents.ts +++ b/src/queries/sql/events/getWebsiteEvents.ts @@ -15,7 +15,7 @@ export function getWebsiteEvents( async function relationalQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) { const { pagedRawQuery, parseFilters } = prisma; const { search } = pageParams; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, }); @@ -49,14 +49,14 @@ async function relationalQuery(websiteId: string, filters: QueryFilters, pagePar } order by created_at desc `, - { ...params, search: `%${search}%` }, + { ...filterParams, search: `%${search}%` }, pageParams, ); } async function clickhouseQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) { const { pagedQuery, parseFilters } = clickhouse; - const { params, dateQuery, filterQuery } = await parseFilters(websiteId, filters); + const { filterParams, dateQuery, filterQuery } = await parseFilters(websiteId, filters); const { search } = pageParams; return pagedQuery( @@ -86,7 +86,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters, pagePar } order by created_at desc `, - { ...params, search }, + { ...filterParams, search }, pageParams, ); } diff --git a/src/queries/sql/getChannelMetrics.ts b/src/queries/sql/getChannelMetrics.ts index 433c5e81..aa0919ad 100644 --- a/src/queries/sql/getChannelMetrics.ts +++ b/src/queries/sql/getChannelMetrics.ts @@ -12,7 +12,7 @@ export async function getChannelMetrics(...args: [websiteId: string, filters?: Q async function relationalQuery(websiteId: string, filters: QueryFilters) { const { rawQuery, parseFilters } = prisma; - const { params, filterQuery, dateQuery } = await parseFilters(websiteId, filters); + const { filterParams, filterQuery, dateQuery } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -27,7 +27,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { group by 1, 2 order by visitors desc `, - params, + filterParams, ); } @@ -36,7 +36,7 @@ async function clickhouseQuery( filters: QueryFilters, ): Promise<{ x: string; y: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { params, filterQuery, dateQuery } = await parseFilters(websiteId, filters); + const { filterParams, filterQuery, dateQuery } = await parseFilters(websiteId, filters); const sql = ` select @@ -51,5 +51,5 @@ async function clickhouseQuery( order by visitors desc `; - return rawQuery(sql, params); + return rawQuery(sql, filterParams); } diff --git a/src/queries/sql/getRealtimeActivity.ts b/src/queries/sql/getRealtimeActivity.ts index 5d1fa001..1bfd06eb 100644 --- a/src/queries/sql/getRealtimeActivity.ts +++ b/src/queries/sql/getRealtimeActivity.ts @@ -12,7 +12,7 @@ export async function getRealtimeActivity(...args: [websiteId: string, filters: async function relationalQuery(websiteId: string, filters: QueryFilters) { const { rawQuery, parseFilters } = prisma; - const { params, filterQuery, dateQuery } = await parseFilters(websiteId, filters); + const { filterParams, filterQuery, dateQuery } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -35,13 +35,13 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { order by website_event.created_at desc limit 100 `, - params, + filterParams, ); } async function clickhouseQuery(websiteId: string, filters: QueryFilters): Promise<{ x: number }> { const { rawQuery, parseFilters } = clickhouse; - const { params, filterQuery, dateQuery } = await parseFilters(websiteId, filters); + const { filterParams, filterQuery, dateQuery } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -62,6 +62,6 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters): Promis order by createdAt desc limit 100 `, - { ...filters, ...params }, + { ...filters, ...filterParams }, ); } diff --git a/src/queries/sql/getWebsiteDateRange.ts b/src/queries/sql/getWebsiteDateRange.ts index 953fa5eb..917d058c 100644 --- a/src/queries/sql/getWebsiteDateRange.ts +++ b/src/queries/sql/getWebsiteDateRange.ts @@ -12,7 +12,9 @@ export async function getWebsiteDateRange(...args: [websiteId: string]) { async function relationalQuery(websiteId: string) { const { rawQuery, parseFilters } = prisma; - const { params } = await parseFilters(websiteId, { startDate: new Date(DEFAULT_RESET_DATE) }); + const { filterParams } = await parseFilters(websiteId, { + startDate: new Date(DEFAULT_RESET_DATE), + }); const result = await rawQuery( ` @@ -23,7 +25,7 @@ async function relationalQuery(websiteId: string) { where website_id = {{websiteId::uuid}} and created_at >= {{startDate}} `, - params, + filterParams, ); return result[0] ?? null; @@ -31,7 +33,9 @@ async function relationalQuery(websiteId: string) { async function clickhouseQuery(websiteId: string) { const { rawQuery, parseFilters } = clickhouse; - const { params } = await parseFilters(websiteId, { startDate: new Date(DEFAULT_RESET_DATE) }); + const { filterParams } = await parseFilters(websiteId, { + startDate: new Date(DEFAULT_RESET_DATE), + }); const result = await rawQuery( ` @@ -42,7 +46,7 @@ async function clickhouseQuery(websiteId: string) { where website_id = {websiteId:UUID} and created_at >= {startDate:DateTime64} `, - params, + filterParams, ); return result[0] ?? null; diff --git a/src/queries/sql/getWebsiteStats.ts b/src/queries/sql/getWebsiteStats.ts index 421515c9..947654a6 100644 --- a/src/queries/sql/getWebsiteStats.ts +++ b/src/queries/sql/getWebsiteStats.ts @@ -23,7 +23,7 @@ async function relationalQuery( { pageviews: number; visitors: number; visits: number; bounces: number; totaltime: number }[] > { const { getTimestampDiffSQL, parseFilters, rawQuery } = prisma; - const { filterQuery, joinSession, params } = await parseFilters(websiteId, { + const { filterQuery, joinSession, filterParams } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.pageView, }); @@ -52,7 +52,7 @@ async function relationalQuery( group by 1, 2 ) as t `, - params, + filterParams, ); } @@ -63,7 +63,7 @@ async function clickhouseQuery( { pageviews: number; visitors: number; visits: number; bounces: number; totaltime: number }[] > { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.pageView, }); @@ -117,5 +117,5 @@ async function clickhouseQuery( `; } - return rawQuery(sql, params).then(result => result?.[0]); + return rawQuery(sql, filterParams).then(result => result?.[0]); } diff --git a/src/queries/sql/pageviews/getPageviewMetrics.ts b/src/queries/sql/pageviews/getPageviewMetrics.ts index 9e681b7f..7d73d08a 100644 --- a/src/queries/sql/pageviews/getPageviewMetrics.ts +++ b/src/queries/sql/pageviews/getPageviewMetrics.ts @@ -28,7 +28,7 @@ async function relationalQuery( ) { const column = FILTER_COLUMNS[type] || type; const { rawQuery, parseFilters } = prisma; - const { filterQuery, joinSession, params } = await parseFilters( + const { filterQuery, joinSession, filterParams } = await parseFilters( websiteId, { ...filters, @@ -82,7 +82,7 @@ async function relationalQuery( limit ${limit} offset ${offset} `, - params, + filterParams, ); } @@ -95,7 +95,7 @@ async function clickhouseQuery( ): Promise<{ x: string; y: number }[]> { const column = FILTER_COLUMNS[type] || type; const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView, }); @@ -180,5 +180,5 @@ async function clickhouseQuery( `; } - return rawQuery(sql, params); + return rawQuery(sql, filterParams); } diff --git a/src/queries/sql/pageviews/getPageviewStats.ts b/src/queries/sql/pageviews/getPageviewStats.ts index fe696616..5af44020 100644 --- a/src/queries/sql/pageviews/getPageviewStats.ts +++ b/src/queries/sql/pageviews/getPageviewStats.ts @@ -14,7 +14,7 @@ export async function getPageviewStats(...args: [websiteId: string, filters: Que async function relationalQuery(websiteId: string, filters: QueryFilters) { const { timezone = 'utc', unit = 'day' } = filters; const { getDateSQL, parseFilters, rawQuery } = prisma; - const { filterQuery, joinSession, params } = await parseFilters(websiteId, { + const { filterQuery, joinSession, filterParams } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.pageView, }); @@ -33,7 +33,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { group by 1 order by 1 `, - params, + filterParams, ); } @@ -43,7 +43,7 @@ async function clickhouseQuery( ): Promise<{ x: string; y: number }[]> { const { timezone = 'utc', unit = 'day' } = filters; const { parseFilters, rawQuery, getDateSQL } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.pageView, }); @@ -88,5 +88,5 @@ async function clickhouseQuery( `; } - return rawQuery(sql, params); + return rawQuery(sql, filterParams); } diff --git a/src/queries/sql/reports/getAttribution.ts b/src/queries/sql/reports/getAttribution.ts index 5f3deb1b..212ef548 100644 --- a/src/queries/sql/reports/getAttribution.ts +++ b/src/queries/sql/reports/getAttribution.ts @@ -1,6 +1,6 @@ import clickhouse from '@/lib/clickhouse'; import { EVENT_TYPE } from '@/lib/constants'; -import { CLICKHOUSE, getDatabaseType, POSTGRESQL, PRISMA, runQuery } from '@/lib/db'; +import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; export interface AttributionCriteria { @@ -38,8 +38,6 @@ async function relationalQuery( const { rawQuery } = prisma; const eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent; const column = type === 'page' ? 'url_path' : 'event_name'; - const db = getDatabaseType(); - const like = db === POSTGRESQL ? 'ilike' : 'like'; function getUTMQuery(utmColumn: string) { return ` @@ -79,7 +77,7 @@ async function relationalQuery( where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} and ${column} = {{conversionStep}} - and currency ${like} {{currency}} + and currency = {{currency}} group by 1),`; function getModelQuery(model: string) { @@ -243,26 +241,57 @@ async function clickhouseQuery( criteria: AttributionCriteria, ): Promise { const { startDate, endDate, model, type, step, currency } = criteria; - const { rawQuery } = clickhouse; + const { rawQuery, parseFilters } = clickhouse; const eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent; const column = type === 'page' ? 'url_path' : 'event_name'; + const { filterQuery, filterParams } = await parseFilters(websiteId, criteria); function getUTMQuery(utmColumn: string) { return ` - select - we.${utmColumn} name, - ${currency ? 'sum(e.value)' : 'uniqExact(we.session_id)'} value - from model m - join website_event we - on we.created_at = m.created_at - and we.session_id = m.session_id - ${currency ? 'join events e on e.session_id = m.session_id' : ''} - where we.website_id = {websiteId:UUID} + select + we.${utmColumn} name, + ${currency ? 'sum(e.value)' : 'uniqExact(we.session_id)'} value + from model m + join website_event we + on we.created_at = m.created_at + and we.session_id = m.session_id + ${currency ? 'join events e on e.session_id = m.session_id' : ''} + where we.website_id = {websiteId:UUID} + and we.created_at between {startDate:DateTime64} and {endDate:DateTime64} + ${currency ? '' : `and we.${utmColumn} != ''`} + group by 1 + order by 2 desc + limit 20 + `; + } + + function getModelQuery(model: string) { + if (model === 'first-click') { + return ` + model AS (select e.session_id, + min(we.created_at) created_at + from events e + join website_event we + on we.session_id = e.session_id + where we.website_id = {websiteId:UUID} and we.created_at between {startDate:DateTime64} and {endDate:DateTime64} - ${currency ? '' : `and we.${utmColumn} != ''`} - group by 1 - order by 2 desc - limit 20`; + ${filterQuery} + group by e.session_id) + `; + } + + return ` + model AS (select e.session_id, + max(we.created_at) created_at + from events e + join website_event we + on we.session_id = e.session_id + where we.website_id = {websiteId:UUID} + and we.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and we.created_at < e.max_dt + ${filterQuery} + group by e.session_id) + `; } const eventQuery = `WITH events AS ( @@ -288,29 +317,6 @@ async function clickhouseQuery( and currency = {currency:String} group by 1),`; - function getModelQuery(model: string) { - return model === 'first-click' - ? `\n - model AS (select e.session_id, - min(we.created_at) created_at - from events e - join website_event we - on we.session_id = e.session_id - where we.website_id = {websiteId:UUID} - and we.created_at between {startDate:DateTime64} and {endDate:DateTime64} - group by e.session_id)` - : `\n - model AS (select e.session_id, - max(we.created_at) created_at - from events e - join website_event we - on we.session_id = e.session_id - where we.website_id = {websiteId:UUID} - and we.created_at between {startDate:DateTime64} and {endDate:DateTime64} - and we.created_at < e.max_dt - group by e.session_id)`; - } - const referrerRes = await rawQuery< { name: string; @@ -339,7 +345,7 @@ async function clickhouseQuery( order by 2 desc limit 20 `, - { websiteId, startDate, endDate, conversionStep: step, eventType, currency }, + { ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency }, ); const paidAdsres = await rawQuery< @@ -370,7 +376,7 @@ async function clickhouseQuery( order by 2 desc limit 20 `, - { websiteId, startDate, endDate, conversionStep: step, eventType, currency }, + { ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency }, ); const sourceRes = await rawQuery< @@ -384,7 +390,7 @@ async function clickhouseQuery( ${getModelQuery(model)} ${getUTMQuery('utm_source')} `, - { websiteId, startDate, endDate, conversionStep: step, eventType, currency }, + { ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency }, ); const mediumRes = await rawQuery< @@ -398,7 +404,7 @@ async function clickhouseQuery( ${getModelQuery(model)} ${getUTMQuery('utm_medium')} `, - { websiteId, startDate, endDate, conversionStep: step, eventType, currency }, + { ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency }, ); const campaignRes = await rawQuery< @@ -412,7 +418,7 @@ async function clickhouseQuery( ${getModelQuery(model)} ${getUTMQuery('utm_campaign')} `, - { websiteId, startDate, endDate, conversionStep: step, eventType, currency }, + { ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency }, ); const contentRes = await rawQuery< @@ -426,7 +432,7 @@ async function clickhouseQuery( ${getModelQuery(model)} ${getUTMQuery('utm_content')} `, - { websiteId, startDate, endDate, conversionStep: step, eventType, currency }, + { ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency }, ); const termRes = await rawQuery< @@ -440,7 +446,7 @@ async function clickhouseQuery( ${getModelQuery(model)} ${getUTMQuery('utm_term')} `, - { websiteId, startDate, endDate, conversionStep: step, eventType, currency }, + { ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency }, ); const totalRes = await rawQuery<{ pageviews: number; visitors: number; visits: number }>( @@ -454,8 +460,9 @@ async function clickhouseQuery( and created_at between {startDate:DateTime64} and {endDate:DateTime64} and ${column} = {conversionStep:String} and event_type = {eventType:UInt32} + ${filterQuery} `, - { websiteId, startDate, endDate, conversionStep: step, eventType, currency }, + { ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency }, ).then(result => result?.[0]); return { diff --git a/src/queries/sql/reports/getBreakdown.ts b/src/queries/sql/reports/getBreakdown.ts index 0965bf43..353761ad 100644 --- a/src/queries/sql/reports/getBreakdown.ts +++ b/src/queries/sql/reports/getBreakdown.ts @@ -24,7 +24,7 @@ async function relationalQuery( }[] > { const { getTimestampDiffSQL, parseFilters, rawQuery } = prisma; - const { filterQuery, joinSession, params } = await parseFilters( + const { filterQuery, joinSession, filterParams } = await parseFilters( websiteId, { ...filters, @@ -65,7 +65,7 @@ async function relationalQuery( order by 1 desc, 2 desc limit 500 `, - params, + filterParams, ); } @@ -80,7 +80,7 @@ async function clickhouseQuery( }[] > { const { parseFilters, rawQuery } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.pageView, }); @@ -114,7 +114,7 @@ async function clickhouseQuery( order by 1 desc, 2 desc limit 500 `, - params, + filterParams, ); } diff --git a/src/queries/sql/reports/getFunnel.ts b/src/queries/sql/reports/getFunnel.ts index d256bd08..45dc21df 100644 --- a/src/queries/sql/reports/getFunnel.ts +++ b/src/queries/sql/reports/getFunnel.ts @@ -121,11 +121,12 @@ async function clickhouseQuery( }[] > { const { windowMinutes, startDate, endDate, steps } = criteria; - const { rawQuery } = clickhouse; + const { rawQuery, parseFilters } = clickhouse; const { levelOneQuery, levelQuery, sumQuery, stepFilterQuery, params } = getFunnelQuery( steps, windowMinutes, ); + const { filterQuery, filterParams: filterParams } = await parseFilters(websiteId, criteria); function getFunnelQuery( steps: { type: string; value: string }[], @@ -200,6 +201,7 @@ async function clickhouseQuery( where (${stepFilterQuery}) and website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} + ${filterQuery} ), ${levelOneQuery} ${levelQuery} @@ -213,6 +215,7 @@ async function clickhouseQuery( startDate, endDate, ...params, + ...filterParams, }, ).then(formatResults(steps)); } diff --git a/src/queries/sql/reports/getGoal.ts b/src/queries/sql/reports/getGoal.ts index 0def8bcd..b2351e51 100644 --- a/src/queries/sql/reports/getGoal.ts +++ b/src/queries/sql/reports/getGoal.ts @@ -21,7 +21,7 @@ export async function getGoal(...args: [websiteId: string, criteria: GoalCriteri async function relationalQuery(websiteId: string, criteria: GoalCriteria) { const { type, value } = criteria; const { rawQuery, parseFilters } = prisma; - const { filterQuery, dateQuery, params } = await parseFilters(websiteId, criteria); + const { filterQuery, dateQuery, filterParams } = await parseFilters(websiteId, criteria); const isPage = type === 'page'; const column = isPage ? 'url_path' : 'event_name'; const eventType = isPage ? 1 : 2; @@ -43,14 +43,14 @@ async function relationalQuery(websiteId: string, criteria: GoalCriteria) { ${dateQuery} ${filterQuery} `, - { ...params, value }, + { ...filterParams, value }, ); } async function clickhouseQuery(websiteId: string, criteria: GoalCriteria) { const { type, value } = criteria; const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, dateQuery, params } = await parseFilters(websiteId, criteria); + const { filterQuery, dateQuery, filterParams } = await parseFilters(websiteId, criteria); const isPage = type === 'page'; const column = isPage ? 'url_path' : 'event_name'; const eventType = isPage ? 1 : 2; @@ -71,6 +71,6 @@ async function clickhouseQuery(websiteId: string, criteria: GoalCriteria) { ${dateQuery} ${filterQuery} `, - { ...params, value }, + { ...filterParams, value }, ).then(results => results?.[0]); } diff --git a/src/queries/sql/reports/getJourney.ts b/src/queries/sql/reports/getJourney.ts index 4c43cc03..b31824e2 100644 --- a/src/queries/sql/reports/getJourney.ts +++ b/src/queries/sql/reports/getJourney.ts @@ -108,7 +108,7 @@ async function relationalQuery( sequenceQuery, startStepQuery, endStepQuery, - params, + filterParams: params, }; } @@ -152,7 +152,7 @@ async function clickhouseQuery( }, ): Promise { const { startDate, endDate, steps, startStep, endStep } = filters; - const { rawQuery } = clickhouse; + const { rawQuery, parseFilters } = clickhouse; const { sequenceQuery, startStepQuery, endStepQuery, params } = getJourneyQuery( steps, startStep, @@ -218,10 +218,12 @@ async function clickhouseQuery( sequenceQuery, startStepQuery, endStepQuery, - params, + filterParams: params, }; } + const { filterQuery, filterParams: filterParams } = await parseFilters(websiteId, filters); + return rawQuery( ` WITH events AS ( @@ -231,6 +233,7 @@ async function clickhouseQuery( row_number() OVER (PARTITION BY visit_id ORDER BY created_at) AS event_number from umami.website_event where website_id = {websiteId:UUID} + ${filterQuery} and created_at between {startDate:DateTime64} and {endDate:DateTime64}), ${sequenceQuery} select * @@ -246,6 +249,7 @@ async function clickhouseQuery( startDate, endDate, ...params, + ...filterParams, }, ).then(parseResult); } diff --git a/src/queries/sql/reports/getRetention.ts b/src/queries/sql/reports/getRetention.ts index 5e871500..76129fd2 100644 --- a/src/queries/sql/reports/getRetention.ts +++ b/src/queries/sql/reports/getRetention.ts @@ -28,9 +28,11 @@ async function relationalQuery( criteria: RetentionCriteria, ): Promise { const { startDate, endDate, timezone } = criteria; - const { getDateSQL, getDayDiffQuery, getCastColumnQuery, rawQuery } = prisma; + const { getDateSQL, getDayDiffQuery, getCastColumnQuery, rawQuery, parseFilters } = prisma; const unit = 'day'; + const { filterQuery, filterParams } = await parseFilters(websiteId, criteria); + return rawQuery( ` WITH cohort_items AS ( @@ -49,6 +51,7 @@ async function relationalQuery( on w.session_id = c.session_id where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} + ${filterQuery} ), cohort_size as ( select cohort_date, @@ -82,6 +85,7 @@ async function relationalQuery( websiteId, startDate, endDate, + ...filterParams, }, ); } @@ -91,9 +95,11 @@ async function clickhouseQuery( criteria: RetentionCriteria, ): Promise { const { startDate, endDate, timezone } = criteria; - const { getDateSQL, rawQuery } = clickhouse; + const { getDateSQL, rawQuery, parseFilters } = clickhouse; const unit = 'day'; + const { filterQuery, filterParams } = await parseFilters(websiteId, criteria); + return rawQuery( ` WITH cohort_items AS ( @@ -114,6 +120,7 @@ async function clickhouseQuery( on w.session_id = c.session_id where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} + ${filterQuery} ), cohort_size as ( select cohort_date, @@ -147,6 +154,7 @@ async function clickhouseQuery( websiteId, startDate, endDate, + ...filterParams, }, ); } diff --git a/src/queries/sql/reports/getUTM.ts b/src/queries/sql/reports/getUTM.ts index 134e14b3..cb318bf3 100644 --- a/src/queries/sql/reports/getUTM.ts +++ b/src/queries/sql/reports/getUTM.ts @@ -16,7 +16,8 @@ export async function getUTM(...args: [websiteId: string, criteria: UTMCriteria] async function relationalQuery(websiteId: string, criteria: UTMCriteria) { const { startDate, endDate } = criteria; - const { rawQuery } = prisma; + const { rawQuery, parseFilters } = prisma; + const { filterQuery, filterParams } = await parseFilters(websiteId, criteria); return rawQuery( ` @@ -26,9 +27,11 @@ async function relationalQuery(websiteId: string, criteria: UTMCriteria) { and created_at between {{startDate}} and {{endDate}} and coalesce(url_query, '') != '' and event_type = 1 + ${filterQuery} group by 1 `, { + ...filterParams, websiteId, startDate, endDate, @@ -38,7 +41,8 @@ async function relationalQuery(websiteId: string, criteria: UTMCriteria) { async function clickhouseQuery(websiteId: string, criteria: UTMCriteria) { const { startDate, endDate } = criteria; - const { rawQuery } = clickhouse; + const { rawQuery, parseFilters } = clickhouse; + const { filterQuery, filterParams } = await parseFilters(websiteId, criteria); return rawQuery( ` @@ -48,9 +52,11 @@ async function clickhouseQuery(websiteId: string, criteria: UTMCriteria) { and created_at between {startDate:DateTime64} and {endDate:DateTime64} and url_query != '' and event_type = 1 + ${filterQuery} group by 1 `, { + ...filterParams, websiteId, startDate, endDate, diff --git a/src/queries/sql/sessions/getSessionDataProperties.ts b/src/queries/sql/sessions/getSessionDataProperties.ts index 20fb11d5..173d5df2 100644 --- a/src/queries/sql/sessions/getSessionDataProperties.ts +++ b/src/queries/sql/sessions/getSessionDataProperties.ts @@ -1,11 +1,11 @@ import prisma from '@/lib/prisma'; import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; -import { QueryFilters, WebsiteEventData } from '@/lib/types'; +import { QueryFilters } from '@/lib/types'; export async function getSessionDataProperties( ...args: [websiteId: string, filters: QueryFilters & { propertyName?: string }] -): Promise { +) { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), @@ -17,7 +17,7 @@ async function relationalQuery( filters: QueryFilters & { propertyName?: string }, ) { const { rawQuery, parseFilters } = prisma; - const { filterQuery, params } = await parseFilters(websiteId, filters, { + const { filterQuery, filterParams } = await parseFilters(websiteId, filters, { columns: { propertyName: 'data_key' }, }); @@ -36,7 +36,7 @@ async function relationalQuery( order by 2 desc limit 500 `, - params, + filterParams, ); } @@ -45,7 +45,7 @@ async function clickhouseQuery( filters: QueryFilters & { propertyName?: string }, ): Promise<{ propertyName: string; total: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, filters, { + const { filterQuery, filterParams } = await parseFilters(websiteId, filters, { columns: { propertyName: 'data_key' }, }); @@ -65,6 +65,6 @@ async function clickhouseQuery( order by 2 desc limit 500 `, - params, + filterParams, ); } diff --git a/src/queries/sql/sessions/getSessionDataValues.ts b/src/queries/sql/sessions/getSessionDataValues.ts index 8cd6a4ab..20248fb8 100644 --- a/src/queries/sql/sessions/getSessionDataValues.ts +++ b/src/queries/sql/sessions/getSessionDataValues.ts @@ -17,7 +17,7 @@ async function relationalQuery( filters: QueryFilters & { propertyName?: string }, ) { const { rawQuery, parseFilters, getDateSQL } = prisma; - const { filterQuery, params } = await parseFilters(websiteId, filters); + const { filterQuery, filterParams } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -39,7 +39,7 @@ async function relationalQuery( order by 2 desc limit 100 `, - params, + filterParams, ); } @@ -48,7 +48,7 @@ async function clickhouseQuery( filters: QueryFilters & { propertyName?: string }, ): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, filters); + const { filterQuery, filterParams } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -68,6 +68,6 @@ async function clickhouseQuery( order by 2 desc limit 100 `, - params, + filterParams, ); } diff --git a/src/queries/sql/sessions/getSessionMetrics.ts b/src/queries/sql/sessions/getSessionMetrics.ts index ef787920..acd1bcad 100644 --- a/src/queries/sql/sessions/getSessionMetrics.ts +++ b/src/queries/sql/sessions/getSessionMetrics.ts @@ -28,7 +28,7 @@ async function relationalQuery( ) { const column = FILTER_COLUMNS[type] || type; const { parseFilters, rawQuery } = prisma; - const { filterQuery, joinSession, params } = await parseFilters( + const { filterQuery, joinSession, filterParams } = await parseFilters( websiteId, { ...filters, @@ -58,7 +58,7 @@ async function relationalQuery( limit ${limit} offset ${offset} `, - params, + filterParams, ); } @@ -71,7 +71,7 @@ async function clickhouseQuery( ): Promise<{ x: string; y: number }[]> { const column = FILTER_COLUMNS[type] || type; const { parseFilters, rawQuery } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.pageView, }); @@ -115,5 +115,5 @@ async function clickhouseQuery( `; } - return rawQuery(sql, params); + return rawQuery(sql, filterParams); } diff --git a/src/queries/sql/sessions/getSessionStats.ts b/src/queries/sql/sessions/getSessionStats.ts index 22cc04a7..a870ff20 100644 --- a/src/queries/sql/sessions/getSessionStats.ts +++ b/src/queries/sql/sessions/getSessionStats.ts @@ -14,7 +14,7 @@ export async function getSessionStats(...args: [websiteId: string, filters: Quer async function relationalQuery(websiteId: string, filters: QueryFilters) { const { timezone = 'utc', unit = 'day' } = filters; const { getDateSQL, parseFilters, rawQuery } = prisma; - const { filterQuery, joinSession, params } = await parseFilters(websiteId, { + const { filterQuery, joinSession, filterParams } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.pageView, }); @@ -33,7 +33,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { group by 1 order by 1 `, - params, + filterParams, ); } @@ -43,7 +43,7 @@ async function clickhouseQuery( ): Promise<{ x: string; y: number }[]> { const { timezone = 'utc', unit = 'day' } = filters; const { parseFilters, rawQuery, getDateSQL } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.pageView, }); @@ -88,5 +88,5 @@ async function clickhouseQuery( `; } - return rawQuery(sql, params); + return rawQuery(sql, filterParams); } diff --git a/src/queries/sql/sessions/getWebsiteSessionStats.ts b/src/queries/sql/sessions/getWebsiteSessionStats.ts index 2463b7ad..16cebf2e 100644 --- a/src/queries/sql/sessions/getWebsiteSessionStats.ts +++ b/src/queries/sql/sessions/getWebsiteSessionStats.ts @@ -21,7 +21,7 @@ async function relationalQuery( { pageviews: number; visitors: number; visits: number; countries: number; events: number }[] > { const { parseFilters, rawQuery } = prisma; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, }); @@ -39,7 +39,7 @@ async function relationalQuery( and website_event.created_at between {{startDate}} and {{endDate}} ${filterQuery} `, - params, + filterParams, ); } @@ -50,7 +50,7 @@ async function clickhouseQuery( { pageviews: number; visitors: number; visits: number; countries: number; events: number }[] > { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, }); @@ -67,6 +67,6 @@ async function clickhouseQuery( and created_at between {startDate:DateTime64} and {endDate:DateTime64} ${filterQuery} `, - params, + filterParams, ); } diff --git a/src/queries/sql/sessions/getWebsiteSessions.ts b/src/queries/sql/sessions/getWebsiteSessions.ts index 0d25de2b..81208cb1 100644 --- a/src/queries/sql/sessions/getWebsiteSessions.ts +++ b/src/queries/sql/sessions/getWebsiteSessions.ts @@ -15,7 +15,7 @@ export async function getWebsiteSessions( async function relationalQuery(websiteId: string, filters: QueryFilters, pageParams: PageParams) { const { pagedRawQuery, parseFilters } = prisma; const { search } = pageParams; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, filterParams } = await parseFilters(websiteId, { ...filters, }); @@ -68,14 +68,14 @@ async function relationalQuery(websiteId: string, filters: QueryFilters, pagePar session.city order by max(website_event.created_at) desc `, - { ...params, search: `%${search}%` }, + { ...filterParams, search: `%${search}%` }, pageParams, ); } async function clickhouseQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) { const { pagedQuery, parseFilters, getDateStringSQL } = clickhouse; - const { params, dateQuery, filterQuery } = await parseFilters(websiteId, filters); + const { filterParams, dateQuery, filterQuery } = await parseFilters(websiteId, filters); const { search } = pageParams; return pagedQuery( @@ -113,7 +113,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters, pagePar group by session_id, website_id, hostname, browser, os, device, screen, language, country, region, city order by lastAt desc `, - { ...params, search }, + { ...filterParams, search }, pageParams, ); } diff --git a/src/queries/sql/sessions/getWebsiteSessionsWeekly.ts b/src/queries/sql/sessions/getWebsiteSessionsWeekly.ts index 58f8d692..3fafcc92 100644 --- a/src/queries/sql/sessions/getWebsiteSessionsWeekly.ts +++ b/src/queries/sql/sessions/getWebsiteSessionsWeekly.ts @@ -15,7 +15,7 @@ export async function getWebsiteSessionsWeekly( async function relationalQuery(websiteId: string, filters: QueryFilters) { const { timezone = 'utc' } = filters; const { rawQuery, getDateWeeklySQL, parseFilters } = prisma; - const { params } = await parseFilters(websiteId, filters); + const { filterParams } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -28,14 +28,14 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { group by time order by 2 `, - params, + filterParams, ).then(formatResults); } async function clickhouseQuery(websiteId: string, filters: QueryFilters) { const { timezone = 'utc' } = filters; const { rawQuery, parseFilters } = clickhouse; - const { params } = await parseFilters(websiteId, filters); + const { filterParams } = await parseFilters(websiteId, filters); return rawQuery( ` @@ -48,7 +48,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) { group by time order by time `, - params, + filterParams, ).then(formatResults); } From 5b300f1ff56f755b821af8f466c1955ae2ed9f98 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 30 Jun 2025 21:34:56 -0700 Subject: [PATCH 112/399] Updated events/sessions pages. Added DateDistance component. --- .../websites/[websiteId]/events/EventsPage.tsx | 2 -- .../websites/[websiteId]/events/EventsTable.tsx | 8 ++++---- .../[websiteId]/sessions/SessionsPage.tsx | 13 ------------- .../[websiteId]/sessions/SessionsTable.tsx | 6 +++--- .../api/websites/[websiteId]/events/route.ts | 2 +- src/components/charts/BarChart.tsx | 2 +- src/components/common/DateDistance.tsx | 17 +++++++++++++++++ src/components/hooks/queries/useResultQuery.ts | 2 +- src/components/hooks/queries/useTeamsQuery.ts | 5 ++--- .../hooks/queries/useWebsiteEventsQuery.ts | 7 +++---- src/components/hooks/useFilterParams.ts | 9 +++++++++ src/components/hooks/usePagedQuery.ts | 4 ++-- src/lib/types.ts | 2 +- 13 files changed, 44 insertions(+), 35 deletions(-) create mode 100644 src/components/common/DateDistance.tsx diff --git a/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx b/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx index 7e7e0440..fbf11e8e 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx @@ -3,7 +3,6 @@ import { TabList, Tab, Tabs, TabPanel, Column } from '@umami/react-zen'; import { EventsTable } from '@/components/metrics/EventsTable'; import { useState } from 'react'; import { EventsDataTable } from './EventsDataTable'; -import { EventsMetricsBar } from './EventsMetricsBar'; import { Panel } from '@/components/common/Panel'; import { EventsChart } from '@/components/metrics/EventsChart'; import { GridRow } from '@/components/common/GridRow'; @@ -23,7 +22,6 @@ export function EventsPage({ websiteId }) { return ( - diff --git a/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx b/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx index 3cb1a750..9a21f21d 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx @@ -1,12 +1,12 @@ import { DataTable, DataColumn, Icon, Row } from '@umami/react-zen'; -import { useMessages, useNavigation, useTimezone } from '@/components/hooks'; +import { useMessages, useNavigation } from '@/components/hooks'; import { Empty } from '@/components/common/Empty'; import { Avatar } from '@/components/common/Avatar'; import Link from 'next/link'; import { Bolt, Eye } from '@/components/icons'; +import { DateDistance } from '@/components/common/DateDistance'; export function EventsTable({ data = [] }) { - const { formatTimezoneDate } = useTimezone(); const { formatMessage, labels } = useMessages(); const { renderUrl } = useNavigation(); @@ -34,8 +34,8 @@ export function EventsTable({ data = [] }) { ); }} - - {(row: any) => formatTimezoneDate(row.createdAt, 'PPPpp')} + + {(row: any) => } ); diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx index 1ff848e7..7e18bbed 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx @@ -2,12 +2,8 @@ import { useState } from 'react'; import { TabList, Tab, Tabs, TabPanel, Column } from '@umami/react-zen'; import { SessionsDataTable } from './SessionsDataTable'; -import { SessionsMetricsBar } from './SessionsMetricsBar'; import { SessionProperties } from './SessionProperties'; -import { WorldMap } from '@/components/metrics/WorldMap'; -import { GridRow } from '@/components/common/GridRow'; import { useMessages } from '@/components/hooks'; -import { SessionsWeekly } from './SessionsWeekly'; import { Panel } from '@/components/common/Panel'; import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls'; @@ -18,15 +14,6 @@ export function SessionsPage({ websiteId }) { return ( - - - - - - - - - setTab(value)}> diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx index 901d5473..0b9ad43b 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx @@ -1,11 +1,11 @@ import Link from 'next/link'; import { DataColumn, DataTable } from '@umami/react-zen'; -import { useFormat, useMessages, useTimezone } from '@/components/hooks'; +import { useFormat, useMessages } from '@/components/hooks'; import { Avatar } from '@/components/common/Avatar'; import { TypeIcon } from '@/components/common/TypeIcon'; +import { DateDistance } from '@/components/common/DateDistance'; export function SessionsTable({ data = [] }: { data: any[]; showDomain?: boolean }) { - const { formatTimezoneDate } = useTimezone(); const { formatMessage, labels } = useMessages(); const { formatValue } = useFormat(); @@ -50,7 +50,7 @@ export function SessionsTable({ data = [] }: { data: any[]; showDomain?: boolean )} - {(row: any) => formatTimezoneDate(row.createdAt, 'PPPpp')} + {(row: any) => }
); diff --git a/src/app/api/websites/[websiteId]/events/route.ts b/src/app/api/websites/[websiteId]/events/route.ts index fb3db328..ef20dd7c 100644 --- a/src/app/api/websites/[websiteId]/events/route.ts +++ b/src/app/api/websites/[websiteId]/events/route.ts @@ -28,7 +28,7 @@ export async function GET( return unauthorized(); } - const data = await getWebsiteEvents(websiteId, { startDate, endDate }, query); + const data = await getWebsiteEvents(websiteId, { ...query, startDate, endDate }, query); return json(data); } diff --git a/src/components/charts/BarChart.tsx b/src/components/charts/BarChart.tsx index 8cbf5f8d..3f3efd3b 100644 --- a/src/components/charts/BarChart.tsx +++ b/src/components/charts/BarChart.tsx @@ -21,7 +21,7 @@ const dateFormats = { }; export interface BarChartProps extends ChartProps { - unit: string; + unit?: string; stacked?: boolean; currency?: string; renderXLabel?: (label: string, index: number, values: any[]) => string; diff --git a/src/components/common/DateDistance.tsx b/src/components/common/DateDistance.tsx new file mode 100644 index 00000000..43056b0c --- /dev/null +++ b/src/components/common/DateDistance.tsx @@ -0,0 +1,17 @@ +import { Tooltip, TooltipTrigger, Text, Focusable } from '@umami/react-zen'; +import { formatDistanceToNow } from 'date-fns'; +import { useLocale, useTimezone } from '@/components/hooks'; + +export function DateDistance({ date }: { date: Date }) { + const { formatTimezoneDate } = useTimezone(); + const { dateLocale } = useLocale(); + + return ( + + + {formatDistanceToNow(date, { addSuffix: true, locale: dateLocale })} + + {formatTimezoneDate(date.toISOString(), 'PPPpp')} + + ); +} diff --git a/src/components/hooks/queries/useResultQuery.ts b/src/components/hooks/queries/useResultQuery.ts index e82e4519..098124c5 100644 --- a/src/components/hooks/queries/useResultQuery.ts +++ b/src/components/hooks/queries/useResultQuery.ts @@ -2,7 +2,7 @@ import { useApi } from '../useApi'; import { useFilterParams } from '../useFilterParams'; import { ReactQueryOptions } from '@/lib/types'; -export function useResultQuery( +export function useResultQuery( type: string, params?: { [key: string]: any }, options?: ReactQueryOptions, diff --git a/src/components/hooks/queries/useTeamsQuery.ts b/src/components/hooks/queries/useTeamsQuery.ts index a4edc287..a70aca24 100644 --- a/src/components/hooks/queries/useTeamsQuery.ts +++ b/src/components/hooks/queries/useTeamsQuery.ts @@ -1,12 +1,11 @@ import { useApi } from '../useApi'; -import { usePagedQuery } from '../usePagedQuery'; import { useModified } from '../useModified'; export function useTeamsQuery(userId: string) { - const { get } = useApi(); + const { get, useQuery } = useApi(); const { modified } = useModified(`teams`); - return usePagedQuery({ + return useQuery({ queryKey: ['teams', { userId, modified }], queryFn: (params: any) => { return get(`/users/${userId}/teams`, params); diff --git a/src/components/hooks/queries/useWebsiteEventsQuery.ts b/src/components/hooks/queries/useWebsiteEventsQuery.ts index 8699ab31..7b465f70 100644 --- a/src/components/hooks/queries/useWebsiteEventsQuery.ts +++ b/src/components/hooks/queries/useWebsiteEventsQuery.ts @@ -5,12 +5,11 @@ import { ReactQueryOptions } from '@/lib/types'; export function useWebsiteEventsQuery(websiteId: string, options?: ReactQueryOptions) { const { get } = useApi(); - const params = useFilterParams(websiteId); + const filterParams = useFilterParams(websiteId); return usePagedQuery({ - queryKey: ['websites:events', { websiteId, ...params }], - queryFn: pageParams => - get(`/websites/${websiteId}/events`, { ...params, ...pageParams, pageSize: 20 }), + queryKey: ['websites:events', { websiteId, ...filterParams }], + queryFn: () => get(`/websites/${websiteId}/events`, { ...filterParams, pageSize: 20 }), enabled: !!websiteId, ...options, }); diff --git a/src/components/hooks/useFilterParams.ts b/src/components/hooks/useFilterParams.ts index f725eb80..d0b84f95 100644 --- a/src/components/hooks/useFilterParams.ts +++ b/src/components/hooks/useFilterParams.ts @@ -22,14 +22,19 @@ export function useFilterParams(websiteId: string) { event, tag, hostname, + page, + pageSize, + search, }, } = useNavigation(); return { + // Date range startAt: +toUtc(startDate), endAt: +toUtc(endDate), unit, timezone, + // Filters path, referrer, title, @@ -44,5 +49,9 @@ export function useFilterParams(websiteId: string) { event, tag, hostname, + // Paging + page, + pageSize, + search, }; } diff --git a/src/components/hooks/usePagedQuery.ts b/src/components/hooks/usePagedQuery.ts index 1f85afc0..6b995ea5 100644 --- a/src/components/hooks/usePagedQuery.ts +++ b/src/components/hooks/usePagedQuery.ts @@ -12,7 +12,7 @@ export function usePagedQuery({ const { query: queryParams } = useNavigation(); const [params, setParams] = useState({ search: '', - page: +queryParams?.page || 1, + page: queryParams?.page || '1', }); const { useQuery } = useApi(); @@ -25,7 +25,7 @@ export function usePagedQuery({ return { result: data as PageResult, query, - filterParams: params, + params, setParams, }; } diff --git a/src/lib/types.ts b/src/lib/types.ts index f6f2c8a1..2bc4bc61 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -29,7 +29,7 @@ export interface PageResult { sortDescending?: boolean; } -export interface PagedQueryResult { +export interface PagedQueryResult { result: PageResult; query: any; params: PageParams; From ee6c68d27cdfd9574d59359cd2f0d8d4f4627f72 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 2 Jul 2025 01:44:12 -0700 Subject: [PATCH 113/399] Refactor filter handling for queries. --- .github/workflows/cd-manual.yml | 4 +- .github/workflows/cd.yml | 4 +- .../console/[websiteId]/TestConsolePage.tsx | 159 +++++++++--------- .../settings/profile/PasswordEditForm.tsx | 2 +- .../settings/users/[userId]/UserWebsites.tsx | 4 +- .../settings/websites/WebsitesDataTable.tsx | 6 +- .../settings/websites/WebsitesTable.tsx | 2 +- .../websites/[websiteId]/WebsiteChart.tsx | 21 +-- .../[websiteId]/WebsiteDetailsPage.tsx | 7 +- .../websites/[websiteId]/WebsiteMenu.tsx | 3 +- .../[websiteId]/WebsiteMetricsBar.tsx | 13 +- .../[websiteId]/reports/goals/GoalsPage.tsx | 20 ++- .../websites/[websiteId]/reports/utm/UTM.tsx | 2 +- .../sessions/SessionsDataTable.tsx | 2 +- .../sessions/[sessionId]/SessionInfo.tsx | 8 +- src/app/api/realtime/[websiteId]/route.ts | 12 +- src/app/api/reports/goal/route.ts | 7 +- src/app/api/teams/[teamId]/websites/route.ts | 6 +- src/app/api/users/[userId]/usage/route.ts | 8 +- src/app/api/users/[userId]/websites/route.ts | 6 +- .../[websiteId]/event-data/events/route.ts | 10 +- .../[websiteId]/event-data/fields/route.ts | 10 +- .../event-data/properties/route.ts | 9 +- .../[websiteId]/event-data/stats/route.ts | 7 +- .../[websiteId]/event-data/values/route.ts | 10 +- .../api/websites/[websiteId]/events/route.ts | 7 +- .../[websiteId]/events/series/route.ts | 12 +- .../api/websites/[websiteId]/metrics/route.ts | 9 +- .../websites/[websiteId]/pageviews/route.ts | 33 ++-- .../session-data/properties/route.ts | 6 +- .../[websiteId]/session-data/values/route.ts | 7 +- .../sessions/[sessionId]/activity/route.ts | 7 +- .../websites/[websiteId]/sessions/route.ts | 13 +- .../[websiteId]/sessions/stats/route.ts | 12 +- .../[websiteId]/sessions/weekly/route.ts | 8 +- .../api/websites/[websiteId]/stats/route.ts | 25 +-- .../api/websites/[websiteId]/values/route.ts | 8 +- src/components/common/DataGrid.tsx | 35 ++-- src/components/common/FilterEditForm.tsx | 2 +- src/components/hooks/index.ts | 2 +- .../hooks/queries/useDeleteQuery.ts | 2 +- .../hooks/queries/useRealtimeQuery.ts | 21 ++- .../hooks/queries/useResultQuery.ts | 4 +- src/components/hooks/queries/useUserQuery.ts | 2 +- .../hooks/queries/useWebsiteEventsQuery.ts | 6 +- .../hooks/queries/useWebsiteMetricsQuery.ts | 6 +- .../hooks/queries/useWebsitePageviewsQuery.ts | 6 +- .../hooks/queries/useWebsiteQuery.ts | 2 +- .../queries/useWebsiteSessionStatsQuery.ts | 5 +- .../hooks/queries/useWebsiteSessionsQuery.ts | 2 +- .../queries/useWebsiteSessionsWeeklyQuery.ts | 2 +- .../hooks/queries/useWebsiteStatsQuery.ts | 7 +- .../{useWebsites.ts => useWebsitesQuery.ts} | 10 +- src/components/hooks/useFormat.ts | 2 +- src/components/hooks/useMessages.ts | 2 +- src/components/hooks/useNavigation.ts | 4 +- src/components/hooks/usePagedQuery.ts | 23 ++- src/components/input/WebsiteSelect.tsx | 17 +- src/components/metrics/MetricCard.tsx | 6 - src/components/metrics/MetricsTable.tsx | 2 +- src/lib/clickhouse.ts | 55 +++--- src/lib/constants.ts | 2 +- src/lib/data.ts | 2 +- src/lib/date.ts | 8 +- src/lib/kafka.ts | 2 +- src/lib/params.ts | 2 +- src/lib/prisma.ts | 113 ++++--------- src/lib/request.ts | 39 ++++- src/lib/schema.ts | 36 ++-- src/lib/types.ts | 119 +++++-------- src/queries/prisma/report.ts | 12 +- src/queries/prisma/team.ts | 6 +- src/queries/prisma/teamUser.ts | 4 +- src/queries/prisma/user.ts | 8 +- src/queries/prisma/website.ts | 12 +- src/queries/sql/events/getEventDataEvents.ts | 12 +- src/queries/sql/events/getEventDataFields.ts | 8 +- .../sql/events/getEventDataProperties.ts | 12 +- src/queries/sql/events/getEventDataStats.ts | 8 +- src/queries/sql/events/getEventDataUsage.ts | 7 +- src/queries/sql/events/getEventDataValues.ts | 8 +- src/queries/sql/events/getEventMetrics.ts | 10 +- src/queries/sql/events/getEventUsage.ts | 7 +- src/queries/sql/events/getWebsiteEvents.ts | 60 ++++--- src/queries/sql/getChannelMetrics.ts | 8 +- src/queries/sql/getRealtimeActivity.ts | 8 +- src/queries/sql/getRealtimeData.ts | 8 +- src/queries/sql/getValues.ts | 23 +-- src/queries/sql/getWebsiteDateRange.ts | 10 +- src/queries/sql/getWebsiteStats.ts | 32 ++-- .../sql/pageviews/getPageviewMetrics.ts | 11 +- src/queries/sql/pageviews/getPageviewStats.ts | 12 +- src/queries/sql/reports/getAttribution.ts | 18 +- src/queries/sql/reports/getBreakdown.ts | 11 +- src/queries/sql/reports/getFunnel.ts | 6 +- src/queries/sql/reports/getGoal.ts | 22 ++- src/queries/sql/reports/getJourney.ts | 12 +- src/queries/sql/reports/getRetention.ts | 8 +- src/queries/sql/reports/getUTM.ts | 8 +- .../sql/sessions/getSessionActivity.ts | 20 +-- .../sql/sessions/getSessionDataProperties.ts | 8 +- .../sql/sessions/getSessionDataValues.ts | 12 +- src/queries/sql/sessions/getSessionMetrics.ts | 11 +- src/queries/sql/sessions/getSessionStats.ts | 10 +- .../sql/sessions/getWebsiteSessionStats.ts | 32 ++-- .../sql/sessions/getWebsiteSessions.ts | 55 ++---- .../sql/sessions/getWebsiteSessionsWeekly.ts | 10 +- 107 files changed, 731 insertions(+), 835 deletions(-) rename src/components/hooks/queries/{useWebsites.ts => useWebsitesQuery.ts} (73%) diff --git a/.github/workflows/cd-manual.yml b/.github/workflows/cd-manual.yml index 1f8651fa..df6aa628 100644 --- a/.github/workflows/cd-manual.yml +++ b/.github/workflows/cd-manual.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: - db-type: [postgresql, mysql] + db-type: [postgresql] steps: - uses: actions/checkout@v3 @@ -55,4 +55,4 @@ jobs: buildArgs: DATABASE_TYPE=${{ matrix.db-type }} registry: docker.io username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} \ No newline at end of file + password: ${{ secrets.DOCKER_PASSWORD }} diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index f67f51c3..cf275cb8 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: - db-type: [postgresql, mysql] + db-type: [postgresql] steps: - uses: actions/checkout@v3 @@ -47,4 +47,4 @@ jobs: buildArgs: DATABASE_TYPE=${{ matrix.db-type }} registry: docker.io username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} \ No newline at end of file + password: ${{ secrets.DOCKER_PASSWORD }} diff --git a/src/app/(main)/console/[websiteId]/TestConsolePage.tsx b/src/app/(main)/console/[websiteId]/TestConsolePage.tsx index e0ae696b..e44ea95d 100644 --- a/src/app/(main)/console/[websiteId]/TestConsolePage.tsx +++ b/src/app/(main)/console/[websiteId]/TestConsolePage.tsx @@ -2,6 +2,7 @@ import { Button, Grid, Column, Heading } from '@umami/react-zen'; import Link from 'next/link'; import Script from 'next/script'; +import { Panel } from '@/components/common/Panel'; import { PageBody } from '@/components/common/PageBody'; import { EventsChart } from '@/components/metrics/EventsChart'; import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart'; @@ -115,87 +116,91 @@ export function TestConsolePage({ websiteId }: { websiteId: string }) { src={`${process.env.basePath || ''}/script.js`} data-cache="true" /> - - - Page links -
- page one -
-
- page two -
- - -
- - Click events - - - - -
DIV with attribute
-
-
-
Nested DIV
+ + + + Page links +
+ page one
-
- - - Javascript events - - - - - +
+ page two +
+ + + + + Click events + + + + +
DIV with attribute
+
+
+
Nested DIV
+
+
+
+ + Javascript events + + + + + + Pageviews Events - + + + ); diff --git a/src/app/(main)/settings/profile/PasswordEditForm.tsx b/src/app/(main)/settings/profile/PasswordEditForm.tsx index b29d4989..8d8b6b56 100644 --- a/src/app/(main)/settings/profile/PasswordEditForm.tsx +++ b/src/app/(main)/settings/profile/PasswordEditForm.tsx @@ -24,7 +24,7 @@ export function PasswordEditForm({ onSave, onClose }) { }); }; - const samePassword = (value: string, values: { [key: string]: any }) => { + const samePassword = (value: string, values: Record) => { if (value !== values.newPassword) { return formatMessage(messages.noMatchPassword); } diff --git a/src/app/(main)/settings/users/[userId]/UserWebsites.tsx b/src/app/(main)/settings/users/[userId]/UserWebsites.tsx index 023b3420..8f096353 100644 --- a/src/app/(main)/settings/users/[userId]/UserWebsites.tsx +++ b/src/app/(main)/settings/users/[userId]/UserWebsites.tsx @@ -1,9 +1,9 @@ import { WebsitesTable } from '@/app/(main)/settings/websites/WebsitesTable'; import { DataGrid } from '@/components/common/DataGrid'; -import { useWebsites } from '@/components/hooks'; +import { useWebsitesQuery } from '@/components/hooks'; export function UserWebsites({ userId }) { - const queryResult = useWebsites({ userId }); + const queryResult = useWebsitesQuery({ userId }); return ( diff --git a/src/app/(main)/settings/websites/WebsitesDataTable.tsx b/src/app/(main)/settings/websites/WebsitesDataTable.tsx index 48bb0922..c1aa0cd4 100644 --- a/src/app/(main)/settings/websites/WebsitesDataTable.tsx +++ b/src/app/(main)/settings/websites/WebsitesDataTable.tsx @@ -1,7 +1,7 @@ import { ReactNode } from 'react'; import { WebsitesTable } from '@/app/(main)/settings/websites/WebsitesTable'; import { DataGrid } from '@/components/common/DataGrid'; -import { useWebsites } from '@/components/hooks'; +import { useWebsitesQuery } from '@/components/hooks'; export function WebsitesDataTable({ teamId, @@ -16,10 +16,10 @@ export function WebsitesDataTable({ showActions?: boolean; children?: ReactNode; }) { - const queryResult = useWebsites({ teamId }); + const queryResult = useWebsitesQuery({ teamId }); return ( - children}> + children} allowSearch allowPaging> {({ data }) => ( - {(row: any) => {row.name}} + {(row: any) => {row.name}} {showActions && ( diff --git a/src/app/(main)/websites/[websiteId]/WebsiteChart.tsx b/src/app/(main)/websites/[websiteId]/WebsiteChart.tsx index 2bb2146d..743b4f62 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteChart.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteChart.tsx @@ -3,7 +3,6 @@ import { LoadingPanel } from '@/components/common/LoadingPanel'; import { PageviewsChart } from '@/components/metrics/PageviewsChart'; import { useWebsitePageviewsQuery } from '@/components/hooks/queries/useWebsitePageviewsQuery'; import { useDateRange } from '@/components/hooks'; -import { Panel } from '@/components/common/Panel'; export function WebsiteChart({ websiteId, @@ -48,16 +47,14 @@ export function WebsiteChart({ }, [data, startDate, endDate, unit]); return ( - - - - - + + + ); } diff --git a/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx b/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx index 87b3aca2..bdf7ef74 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx @@ -1,6 +1,7 @@ 'use client'; import { Column } from '@umami/react-zen'; import { useNavigation } from '@/components/hooks'; +import { Panel } from '@/components/common/Panel'; import { WebsiteChart } from './WebsiteChart'; import { WebsiteExpandedView } from './WebsiteExpandedView'; import { WebsiteMetricsBar } from './WebsiteMetricsBar'; @@ -16,8 +17,10 @@ export function WebsiteDetailsPage({ websiteId }: { websiteId: string }) { return ( - - + + + + {!view && !compare && } {view && !compare && } {compare && } diff --git a/src/app/(main)/websites/[websiteId]/WebsiteMenu.tsx b/src/app/(main)/websites/[websiteId]/WebsiteMenu.tsx index 55f89d83..6aa67df1 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteMenu.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteMenu.tsx @@ -11,13 +11,12 @@ import { import { Fragment } from 'react'; import { More, Share, Edit } from '@/components/icons'; import { useMessages, useNavigation } from '@/components/hooks'; -import { InputItem } from '@/lib/types'; export function WebsiteMenu({ websiteId }: { websiteId: string }) { const { formatMessage, labels } = useMessages(); const { router, updateParams, renderUrl } = useNavigation(); - const menuItems: InputItem[] = [ + const menuItems = [ { id: 'share', label: formatMessage(labels.share), icon: }, { id: 'edit', label: formatMessage(labels.edit), icon: , seperator: true }, ]; diff --git a/src/app/(main)/websites/[websiteId]/WebsiteMetricsBar.tsx b/src/app/(main)/websites/[websiteId]/WebsiteMetricsBar.tsx index 246fa576..d2ef3f4b 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteMetricsBar.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteMetricsBar.tsx @@ -3,26 +3,18 @@ import { MetricCard } from '@/components/metrics/MetricCard'; import { MetricsBar } from '@/components/metrics/MetricsBar'; import { formatShortTime, formatLongNumber } from '@/lib/format'; import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery'; -import { useWebsites } from '@/store/websites'; import { LoadingPanel } from '@/components/common/LoadingPanel'; export function WebsiteMetricsBar({ websiteId, - showChange = false, - compareMode = false, }: { websiteId: string; showChange?: boolean; compareMode?: boolean; - showFilter?: boolean; }) { const { dateRange } = useDateRange(websiteId); const { formatMessage, labels } = useMessages(); - const dateCompare = useWebsites(state => state[websiteId]?.dateCompare); - const { data, isLoading, isFetching, error } = useWebsiteStatsQuery( - websiteId, - compareMode && dateCompare, - ); + const { data, isLoading, isFetching, error } = useWebsiteStatsQuery(websiteId); const isAllTime = dateRange.value === 'all'; const { pageviews, visitors, visits, bounces, totaltime, previous } = data || {}; @@ -87,8 +79,7 @@ export function WebsiteMetricsBar({ change={change} formatValue={formatValue} reverseColors={reverseColors} - showChange={!isAllTime && (compareMode || showChange)} - showPrevious={!isAllTime && compareMode} + showChange={!isAllTime} /> ); })} diff --git a/src/app/(main)/websites/[websiteId]/reports/goals/GoalsPage.tsx b/src/app/(main)/websites/[websiteId]/reports/goals/GoalsPage.tsx index f9923871..30f92325 100644 --- a/src/app/(main)/websites/[websiteId]/reports/goals/GoalsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/goals/GoalsPage.tsx @@ -9,7 +9,7 @@ import { LoadingPanel } from '@/components/common/LoadingPanel'; import { Panel } from '@/components/common/Panel'; export function GoalsPage({ websiteId }: { websiteId: string }) { - const { result, query } = useReportsQuery({ websiteId, type: 'goal' }); + const { data, isLoading, error } = useReportsQuery({ websiteId, type: 'goal' }); const { dateRange: { startDate, endDate }, } = useDateRange(websiteId); @@ -20,14 +20,16 @@ export function GoalsPage({ websiteId }: { websiteId: string }) { - - - {result?.data?.map((report: any) => ( - - - - ))} - + + {data && ( + + {data['data'].map((report: any) => ( + + + + ))} + + )} ); diff --git a/src/app/(main)/websites/[websiteId]/reports/utm/UTM.tsx b/src/app/(main)/websites/[websiteId]/reports/utm/UTM.tsx index afa8c842..a1469de6 100644 --- a/src/app/(main)/websites/[websiteId]/reports/utm/UTM.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/utm/UTM.tsx @@ -73,7 +73,7 @@ export function UTM({ websiteId, startDate, endDate }: UTMProps) { ); } -function toArray(data: { [key: string]: number } = {}) { +function toArray(data: Record = {}) { return Object.keys(data) .map(key => { return { name: key, value: data[key] }; diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsDataTable.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsDataTable.tsx index 84a722ac..06323447 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsDataTable.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsDataTable.tsx @@ -14,7 +14,7 @@ export function SessionsDataTable({ const queryResult = useWebsiteSessionsQuery(websiteId); return ( - children}> + children} allowPaging> {({ data }) => } ); diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx index a3336fde..3a1d6829 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx @@ -1,12 +1,12 @@ import { ReactNode } from 'react'; import { Icon, TextField, Column, Row, Label, Text } from '@umami/react-zen'; -import { useFormat, useLocale, useMessages, useRegionNames, useTimezone } from '@/components/hooks'; +import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks'; import { TypeIcon } from '@/components/common/TypeIcon'; import { Location, KeyRound, Calendar } from '@/components/icons'; +import { DateDistance } from '@/components/common/DateDistance'; export function SessionInfo({ data }) { const { locale } = useLocale(); - const { formatTimezoneDate } = useTimezone(); const { formatMessage, labels } = useMessages(); const { formatValue } = useFormat(); const { getRegionName } = useRegionNames(locale); @@ -22,11 +22,11 @@ export function SessionInfo({ data }) { }> - {formatTimezoneDate(data?.lastAt, 'PPPPpp')} + }> - {formatTimezoneDate(data?.firstAt, 'PPPPpp')} + }) { const schema = z.object({ @@ -22,14 +22,14 @@ export async function GET(request: Request, { params }: { params: Promise<{ user } const { userId } = await params; - const { startDate, endDate } = await getRequestDateRange(query); + const filters = await getQueryFilters(query); const websites = await getAllUserWebsitesIncludingTeamOwner(userId); const websiteIds = websites.map(a => a.id); - const websiteEventUsage = await getEventUsage(websiteIds, startDate, endDate); - const eventDataUsage = await getEventDataUsage(websiteIds, startDate, endDate); + const websiteEventUsage = await getEventUsage(websiteIds, filters); + const eventDataUsage = await getEventDataUsage(websiteIds, filters); const websiteUsage = websites.map(a => ({ websiteId: a.id, diff --git a/src/app/api/users/[userId]/websites/route.ts b/src/app/api/users/[userId]/websites/route.ts index 77d41084..d19d754f 100644 --- a/src/app/api/users/[userId]/websites/route.ts +++ b/src/app/api/users/[userId]/websites/route.ts @@ -2,7 +2,7 @@ import { z } from 'zod'; import { unauthorized, json } from '@/lib/response'; import { getUserWebsites } from '@/queries/prisma/website'; import { pagingParams } from '@/lib/schema'; -import { parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; export async function GET(request: Request, { params }: { params: Promise<{ userId: string }> }) { const schema = z.object({ @@ -21,7 +21,9 @@ export async function GET(request: Request, { params }: { params: Promise<{ user return unauthorized(); } - const websites = await getUserWebsites(userId, query); + const filters = await getQueryFilters(query); + + const websites = await getUserWebsites(userId, filters); return json(websites); } diff --git a/src/app/api/websites/[websiteId]/event-data/events/route.ts b/src/app/api/websites/[websiteId]/event-data/events/route.ts index f4b950c4..eb984207 100644 --- a/src/app/api/websites/[websiteId]/event-data/events/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/events/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { getRequestDateRange, parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getEventDataEvents } from '@/queries/sql/events/getEventDataEvents'; @@ -20,16 +20,16 @@ export async function GET( } const { websiteId } = await params; - const { event } = query; - const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } + const { event } = query; + const filters = await getQueryFilters(query); + const data = await getEventDataEvents(websiteId, { - startDate, - endDate, + ...filters, event, }); diff --git a/src/app/api/websites/[websiteId]/event-data/fields/route.ts b/src/app/api/websites/[websiteId]/event-data/fields/route.ts index fa31ca69..34aa6162 100644 --- a/src/app/api/websites/[websiteId]/event-data/fields/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/fields/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { getRequestDateRange, parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getEventDataFields } from '@/queries'; @@ -20,16 +20,14 @@ export async function GET( } const { websiteId } = await params; - const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const data = await getEventDataFields(websiteId, { - startDate, - endDate, - }); + const filters = await getQueryFilters(query); + + const data = await getEventDataFields(websiteId, filters); return json(data); } diff --git a/src/app/api/websites/[websiteId]/event-data/properties/route.ts b/src/app/api/websites/[websiteId]/event-data/properties/route.ts index 2fa7a335..ad39e37a 100644 --- a/src/app/api/websites/[websiteId]/event-data/properties/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/properties/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { getRequestDateRange, parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getEventDataProperties } from '@/queries'; @@ -21,14 +21,15 @@ export async function GET( } const { websiteId } = await params; - const { propertyName } = query; - const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const data = await getEventDataProperties(websiteId, { startDate, endDate, propertyName }); + const { propertyName } = query; + const filters = await getQueryFilters(query); + + const data = await getEventDataProperties(websiteId, { ...filters, propertyName }); return json(data); } diff --git a/src/app/api/websites/[websiteId]/event-data/stats/route.ts b/src/app/api/websites/[websiteId]/event-data/stats/route.ts index ccc45b75..79dd0059 100644 --- a/src/app/api/websites/[websiteId]/event-data/stats/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/stats/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { getRequestDateRange, parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getEventDataStats } from '@/queries'; @@ -21,13 +21,14 @@ export async function GET( } const { websiteId } = await params; - const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const data = await getEventDataStats(websiteId, { startDate, endDate }); + const filters = await getQueryFilters(query); + + const data = await getEventDataStats(websiteId, filters); return json(data); } diff --git a/src/app/api/websites/[websiteId]/event-data/values/route.ts b/src/app/api/websites/[websiteId]/event-data/values/route.ts index c25dc014..1eab63b5 100644 --- a/src/app/api/websites/[websiteId]/event-data/values/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/values/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { getRequestDateRange, parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getEventDataValues } from '@/queries'; @@ -22,16 +22,16 @@ export async function GET( } const { websiteId } = await params; - const { eventName, propertyName } = query; - const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } + const { eventName, propertyName } = query; + const filters = await getQueryFilters(query); + const data = await getEventDataValues(websiteId, { - startDate, - endDate, + ...filters, eventName, propertyName, }); diff --git a/src/app/api/websites/[websiteId]/events/route.ts b/src/app/api/websites/[websiteId]/events/route.ts index ef20dd7c..86f6dec8 100644 --- a/src/app/api/websites/[websiteId]/events/route.ts +++ b/src/app/api/websites/[websiteId]/events/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { getRequestDateRange, parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { pagingParams } from '@/lib/schema'; @@ -22,13 +22,14 @@ export async function GET( } const { websiteId } = await params; - const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const data = await getWebsiteEvents(websiteId, { ...query, startDate, endDate }, query); + const filters = await getQueryFilters(query); + + const data = await getWebsiteEvents(websiteId, filters); return json(data); } diff --git a/src/app/api/websites/[websiteId]/events/series/route.ts b/src/app/api/websites/[websiteId]/events/series/route.ts index 43bd23a7..98d26c0d 100644 --- a/src/app/api/websites/[websiteId]/events/series/route.ts +++ b/src/app/api/websites/[websiteId]/events/series/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest, getRequestDateRange, getRequestFilters } from '@/lib/request'; +import { parseRequest, getQueryFilters } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { filterParams, timezoneParam, unitParam } from '@/lib/schema'; @@ -24,20 +24,12 @@ export async function GET( } const { websiteId } = await params; - const { timezone } = query; - const { startDate, endDate, unit } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const filters = { - ...getRequestFilters(query), - startDate, - endDate, - timezone, - unit, - }; + const filters = await getQueryFilters({ ...query, websiteId }); const data = await getEventMetrics(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/metrics/route.ts b/src/app/api/websites/[websiteId]/metrics/route.ts index 85433904..22fa5b30 100644 --- a/src/app/api/websites/[websiteId]/metrics/route.ts +++ b/src/app/api/websites/[websiteId]/metrics/route.ts @@ -13,7 +13,7 @@ import { VIDEO_DOMAINS, PAID_AD_PARAMS, } from '@/lib/constants'; -import { getRequestFilters, getRequestDateRange, parseRequest } from '@/lib/request'; +import { parseRequest, getQueryFilters } from '@/lib/request'; import { json, unauthorized, badRequest } from '@/lib/response'; import { getPageviewMetrics, getSessionMetrics, getChannelMetrics } from '@/queries'; import { filterParams } from '@/lib/schema'; @@ -45,13 +45,8 @@ export async function GET( return unauthorized(); } - const { startDate, endDate } = await getRequestDateRange(query); const column = FILTER_COLUMNS[type] || type; - const filters = { - ...getRequestFilters(query), - startDate, - endDate, - }; + const filters = await getQueryFilters({ ...query, websiteId }); if (search) { filters[type] = { diff --git a/src/app/api/websites/[websiteId]/pageviews/route.ts b/src/app/api/websites/[websiteId]/pageviews/route.ts index e603ae9c..b25f1895 100644 --- a/src/app/api/websites/[websiteId]/pageviews/route.ts +++ b/src/app/api/websites/[websiteId]/pageviews/route.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; import { canViewWebsite } from '@/lib/auth'; -import { getRequestFilters, getRequestDateRange, parseRequest } from '@/lib/request'; -import { unitParam, timezoneParam, filterParams } from '@/lib/schema'; +import { getQueryFilters, parseRequest } from '@/lib/request'; +import { dateRangeParams, filterParams } from '@/lib/schema'; import { getCompareDate } from '@/lib/date'; import { unauthorized, json } from '@/lib/response'; import { getPageviewStats, getSessionStats } from '@/queries'; @@ -11,11 +11,7 @@ export async function GET( { params }: { params: Promise<{ websiteId: string }> }, ) { const schema = z.object({ - startAt: z.coerce.number().int(), - endAt: z.coerce.number().int(), - unit: unitParam, - timezone: timezoneParam, - compare: z.string().optional(), + ...dateRangeParams, ...filterParams, }); @@ -26,32 +22,23 @@ export async function GET( } const { websiteId } = await params; - const { timezone, compare } = query; if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const { startDate, endDate, unit } = await getRequestDateRange(query); - - const filters = { - ...getRequestFilters(query), - startDate, - endDate, - timezone, - unit, - }; + const filters = await getQueryFilters({ ...query, websiteId }); const [pageviews, sessions] = await Promise.all([ getPageviewStats(websiteId, filters), getSessionStats(websiteId, filters), ]); - if (compare) { + if (filters.compare) { const { startDate: compareStartDate, endDate: compareEndDate } = getCompareDate( - compare, - startDate, - endDate, + filters.compare, + filters.startDate, + filters.endDate, ); const [comparePageviews, compareSessions] = await Promise.all([ @@ -70,8 +57,8 @@ export async function GET( return json({ pageviews, sessions, - startDate, - endDate, + startDate: filters.startDate, + endDate: filters.endDate, compare: { pageviews: comparePageviews, sessions: compareSessions, diff --git a/src/app/api/websites/[websiteId]/session-data/properties/route.ts b/src/app/api/websites/[websiteId]/session-data/properties/route.ts index 901dcdf5..bdc7c53c 100644 --- a/src/app/api/websites/[websiteId]/session-data/properties/route.ts +++ b/src/app/api/websites/[websiteId]/session-data/properties/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { getRequestDateRange, parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getSessionDataProperties } from '@/queries'; @@ -22,13 +22,13 @@ export async function GET( const { websiteId } = await params; const { propertyName } = query; - const { startDate, endDate } = await getRequestDateRange(query); + const filters = await getQueryFilters(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const data = await getSessionDataProperties(websiteId, { startDate, endDate, propertyName }); + const data = await getSessionDataProperties(websiteId, { ...filters, propertyName }); return json(data); } diff --git a/src/app/api/websites/[websiteId]/session-data/values/route.ts b/src/app/api/websites/[websiteId]/session-data/values/route.ts index 0730a70b..5564b4d8 100644 --- a/src/app/api/websites/[websiteId]/session-data/values/route.ts +++ b/src/app/api/websites/[websiteId]/session-data/values/route.ts @@ -1,5 +1,5 @@ import { canViewWebsite } from '@/lib/auth'; -import { getRequestDateRange, parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; import { getSessionDataValues } from '@/queries'; import { z } from 'zod'; @@ -22,15 +22,14 @@ export async function GET( const { propertyName } = query; const { websiteId } = await params; - const { startDate, endDate } = await getRequestDateRange(query); + const filters = await getQueryFilters({ ...query, websiteId }); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } const data = await getSessionDataValues(websiteId, { - startDate, - endDate, + ...filters, propertyName, }); diff --git a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts index 831d0064..5daf2dfb 100644 --- a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest, getRequestDateRange } from '@/lib/request'; +import { parseRequest, getQueryFilters } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { getSessionActivity } from '@/queries'; @@ -20,13 +20,14 @@ export async function GET( } const { websiteId, sessionId } = await params; - const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const data = await getSessionActivity(websiteId, sessionId, startDate, endDate); + const filters = await getQueryFilters(query); + + const data = await getSessionActivity(websiteId, sessionId, filters); return json(data); } diff --git a/src/app/api/websites/[websiteId]/sessions/route.ts b/src/app/api/websites/[websiteId]/sessions/route.ts index 6f8a671e..c6afc638 100644 --- a/src/app/api/websites/[websiteId]/sessions/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/route.ts @@ -1,8 +1,8 @@ import { z } from 'zod'; -import { getRequestDateRange, parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; -import { pagingParams } from '@/lib/schema'; +import { dateRangeParams, filterParams, pagingParams } from '@/lib/schema'; import { getWebsiteSessions } from '@/queries'; export async function GET( @@ -10,8 +10,8 @@ export async function GET( { params }: { params: Promise<{ websiteId: string }> }, ) { const schema = z.object({ - startAt: z.coerce.number().int(), - endAt: z.coerce.number().int(), + ...dateRangeParams, + ...filterParams, ...pagingParams, }); @@ -21,14 +21,15 @@ export async function GET( return error(); } - const { startDate, endDate } = await getRequestDateRange(query); const { websiteId } = await params; if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const data = await getWebsiteSessions(websiteId, { startDate, endDate }, query); + const filters = await getQueryFilters({ ...query, websiteId }); + + const data = await getWebsiteSessions(websiteId, filters); return json(data); } diff --git a/src/app/api/websites/[websiteId]/sessions/stats/route.ts b/src/app/api/websites/[websiteId]/sessions/stats/route.ts index e8e8e6c8..a1746514 100644 --- a/src/app/api/websites/[websiteId]/sessions/stats/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/stats/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest, getRequestDateRange, getRequestFilters } from '@/lib/request'; +import { parseRequest, getQueryFilters } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { filterParams } from '@/lib/schema'; @@ -27,15 +27,9 @@ export async function GET( return unauthorized(); } - const { startDate, endDate } = await getRequestDateRange(query); + const filters = await getQueryFilters(query); - const filters = getRequestFilters(query); - - const metrics = await getWebsiteSessionStats(websiteId, { - ...filters, - startDate, - endDate, - }); + const metrics = await getWebsiteSessionStats(websiteId, filters); const data = Object.keys(metrics[0]).reduce((obj, key) => { obj[key] = { diff --git a/src/app/api/websites/[websiteId]/sessions/weekly/route.ts b/src/app/api/websites/[websiteId]/sessions/weekly/route.ts index a8216123..757e9da3 100644 --- a/src/app/api/websites/[websiteId]/sessions/weekly/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/weekly/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { getRequestDateRange, parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { pagingParams, timezoneParam } from '@/lib/schema'; @@ -23,14 +23,14 @@ export async function GET( } const { websiteId } = await params; - const { timezone } = query; - const { startDate, endDate } = await getRequestDateRange(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const data = await getWebsiteSessionsWeekly(websiteId, { startDate, endDate, timezone }); + const filters = await getQueryFilters(query); + + const data = await getWebsiteSessionsWeekly(websiteId, filters); return json(data); } diff --git a/src/app/api/websites/[websiteId]/stats/route.ts b/src/app/api/websites/[websiteId]/stats/route.ts index 70c0110e..8e2dd3cb 100644 --- a/src/app/api/websites/[websiteId]/stats/route.ts +++ b/src/app/api/websites/[websiteId]/stats/route.ts @@ -1,8 +1,7 @@ import { z } from 'zod'; -import { parseRequest, getRequestDateRange, getRequestFilters } from '@/lib/request'; +import { parseRequest, getQueryFilters } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; -import { getCompareDate } from '@/lib/date'; import { filterParams } from '@/lib/schema'; import { getWebsiteStats } from '@/queries'; @@ -24,32 +23,20 @@ export async function GET( } const { websiteId } = await params; - const { compare } = query; if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const { startDate, endDate } = await getRequestDateRange(query); - const { startDate: compareStartDate, endDate: compareEndDate } = getCompareDate( - compare, - startDate, - endDate, - ); + const filters = await getQueryFilters({ ...query, websiteId }); - const filters = getRequestFilters(query); - - const metrics = await getWebsiteStats(websiteId, { - ...filters, - startDate, - endDate, - }); + const data = await getWebsiteStats(websiteId, filters); const previous = await getWebsiteStats(websiteId, { ...filters, - startDate: compareStartDate, - endDate: compareEndDate, + startDate: filters.compareStartDate, + endDate: filters.compareEndDate, }); - return json({ ...metrics, previous }); + return json({ ...data, previous }); } diff --git a/src/app/api/websites/[websiteId]/values/route.ts b/src/app/api/websites/[websiteId]/values/route.ts index 4dcab3a0..290e0db8 100644 --- a/src/app/api/websites/[websiteId]/values/route.ts +++ b/src/app/api/websites/[websiteId]/values/route.ts @@ -2,7 +2,7 @@ import { z } from 'zod'; import { canViewWebsite } from '@/lib/auth'; import { EVENT_COLUMNS, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; import { getValues } from '@/queries'; -import { parseRequest, getRequestDateRange } from '@/lib/request'; +import { parseRequest, getQueryFilters } from '@/lib/request'; import { badRequest, json, unauthorized } from '@/lib/response'; export async function GET( @@ -23,7 +23,7 @@ export async function GET( } const { websiteId } = await params; - const { type, search } = query; + const { type } = query; if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); @@ -33,9 +33,9 @@ export async function GET( return badRequest('Invalid type.'); } - const { startDate, endDate } = await getRequestDateRange(query); + const filters = await getQueryFilters(query); - const values = await getValues(websiteId, FILTER_COLUMNS[type], startDate, endDate, search); + const values = await getValues(websiteId, FILTER_COLUMNS[type], { ...filters }); return json(values.filter(n => n).sort()); } diff --git a/src/components/common/DataGrid.tsx b/src/components/common/DataGrid.tsx index 339a9c8c..5b23b8f6 100644 --- a/src/components/common/DataGrid.tsx +++ b/src/components/common/DataGrid.tsx @@ -1,14 +1,13 @@ -import { ReactNode } from 'react'; +import { ReactNode, useState } from 'react'; import { SearchField, Row, Column } from '@umami/react-zen'; import { useMessages, useNavigation } from '@/components/hooks'; import { Pager } from '@/components/common/Pager'; import { LoadingPanel } from '@/components/common/LoadingPanel'; -import { PagedQueryResult } from '@/lib/types'; const DEFAULT_SEARCH_DELAY = 600; export interface DataTableProps { - queryResult: PagedQueryResult; + queryResult: any; searchDelay?: number; allowSearch?: boolean; allowPaging?: boolean; @@ -20,31 +19,30 @@ export interface DataTableProps { export function DataGrid({ queryResult, searchDelay = 600, - allowSearch = true, - allowPaging = true, + allowSearch, + allowPaging, autoFocus, children, }: DataTableProps) { const { formatMessage, labels } = useMessages(); - const { result, params, setParams, query } = queryResult || {}; - const { error, isLoading, isFetching } = query || {}; - const { page, pageSize, count, data } = result || {}; - const { search } = params || {}; - const hasData = Boolean(!isLoading && data?.length); + const { data, error, isLoading, isFetching, setParams } = queryResult || {}; const { router, updateParams } = useNavigation(); + const [search, setSearch] = useState(''); const handleSearch = (search: string) => { - setParams({ ...params, search }); + setSearch(search); + setParams(params => ({ ...params, search })); + router.push(updateParams({ search })); }; const handlePageChange = (page: number) => { - setParams({ ...params, page }); + setParams(params => ({ ...params, page })); router.push(updateParams({ page })); }; return ( - {allowSearch && (hasData || search) && ( + {allowSearch && (data || search) && ( - {hasData ? (typeof children === 'function' ? children(result) : children) : null} + {data ? (typeof children === 'function' ? children(data) : children) : null} - {allowPaging && hasData && ( + {allowPaging && data && ( - + )} diff --git a/src/components/common/FilterEditForm.tsx b/src/components/common/FilterEditForm.tsx index 8448dab8..850bd91d 100644 --- a/src/components/common/FilterEditForm.tsx +++ b/src/components/common/FilterEditForm.tsx @@ -19,7 +19,7 @@ export function FilterEditForm({ websiteId, data = [], onChange, onClose }: Filt dateRange: { startDate, endDate }, } = useDateRange(websiteId); - const updateFilter = (name: string, props: { [key: string]: any }) => { + const updateFilter = (name: string, props: Record) => { setFilters(filters => filters.map(filter => (filter.name === name ? { ...filter, ...props } : filter)), ); diff --git a/src/components/hooks/index.ts b/src/components/hooks/index.ts index 28a55345..5fb5c61e 100644 --- a/src/components/hooks/index.ts +++ b/src/components/hooks/index.ts @@ -24,7 +24,7 @@ export * from './queries/useTeamMembersQuery'; export * from './queries/useUserQuery'; export * from './queries/useUsersQuery'; export * from './queries/useWebsiteQuery'; -export * from './queries/useWebsites'; +export * from './queries/useWebsitesQuery'; export * from './queries/useWebsiteEventsQuery'; export * from './queries/useWebsiteEventsSeriesQuery'; export * from './queries/useWebsiteMetricsQuery'; diff --git a/src/components/hooks/queries/useDeleteQuery.ts b/src/components/hooks/queries/useDeleteQuery.ts index bf5d8f5d..db5e91d8 100644 --- a/src/components/hooks/queries/useDeleteQuery.ts +++ b/src/components/hooks/queries/useDeleteQuery.ts @@ -1,6 +1,6 @@ import { useApi, useModified } from '@/components/hooks'; -export function useDeleteQuery(path: string, params?: { [key: string]: any }) { +export function useDeleteQuery(path: string, params?: Record) { const { del, useMutation } = useApi(); const { mutate, isPending, error } = useMutation({ mutationFn: () => del(path, params), diff --git a/src/components/hooks/queries/useRealtimeQuery.ts b/src/components/hooks/queries/useRealtimeQuery.ts index 58e72ef5..582fe9fa 100644 --- a/src/components/hooks/queries/useRealtimeQuery.ts +++ b/src/components/hooks/queries/useRealtimeQuery.ts @@ -1,8 +1,27 @@ import { useTimezone } from '@/components/hooks/useTimezone'; import { REALTIME_INTERVAL } from '@/lib/constants'; -import { RealtimeData } from '@/lib/types'; import { useApi } from '../useApi'; +export interface RealtimeData { + countries: Record; + events: any[]; + pageviews: any[]; + referrers: Record; + timestamp: number; + series: { + views: any[]; + visitors: any[]; + }; + totals: { + views: number; + visitors: number; + events: number; + countries: number; + }; + urls: Record; + visitors: any[]; +} + export function useRealtimeQuery(websiteId: string) { const { get, useQuery } = useApi(); const { timezone } = useTimezone(); diff --git a/src/components/hooks/queries/useResultQuery.ts b/src/components/hooks/queries/useResultQuery.ts index 098124c5..bbdf0dff 100644 --- a/src/components/hooks/queries/useResultQuery.ts +++ b/src/components/hooks/queries/useResultQuery.ts @@ -4,7 +4,7 @@ import { ReactQueryOptions } from '@/lib/types'; export function useResultQuery( type: string, - params?: { [key: string]: any }, + params?: Record, options?: ReactQueryOptions, ) { const { websiteId } = params; @@ -21,7 +21,7 @@ export function useResultQuery( ...params, }, ], - queryFn: () => post(`/reports/${type}`, { type, ...filters, ...params }), + queryFn: () => post(`/reports/${type}`, { type, filters, ...params }), enabled: !!type, ...options, }); diff --git a/src/components/hooks/queries/useUserQuery.ts b/src/components/hooks/queries/useUserQuery.ts index f454b96a..baaa084b 100644 --- a/src/components/hooks/queries/useUserQuery.ts +++ b/src/components/hooks/queries/useUserQuery.ts @@ -1,6 +1,6 @@ import { useApi } from '../useApi'; -export function useUserQuery(userId: string, options?: { [key: string]: any }) { +export function useUserQuery(userId: string, options?: Record) { const { get, useQuery } = useApi(); return useQuery({ queryKey: ['users', userId], diff --git a/src/components/hooks/queries/useWebsiteEventsQuery.ts b/src/components/hooks/queries/useWebsiteEventsQuery.ts index 7b465f70..a40f00bc 100644 --- a/src/components/hooks/queries/useWebsiteEventsQuery.ts +++ b/src/components/hooks/queries/useWebsiteEventsQuery.ts @@ -5,11 +5,11 @@ import { ReactQueryOptions } from '@/lib/types'; export function useWebsiteEventsQuery(websiteId: string, options?: ReactQueryOptions) { const { get } = useApi(); - const filterParams = useFilterParams(websiteId); + const queryParams = useFilterParams(websiteId); return usePagedQuery({ - queryKey: ['websites:events', { websiteId, ...filterParams }], - queryFn: () => get(`/websites/${websiteId}/events`, { ...filterParams, pageSize: 20 }), + queryKey: ['websites:events', { websiteId, ...queryParams }], + queryFn: () => get(`/websites/${websiteId}/events`, { ...queryParams, pageSize: 20 }), enabled: !!websiteId, ...options, }); diff --git a/src/components/hooks/queries/useWebsiteMetricsQuery.ts b/src/components/hooks/queries/useWebsiteMetricsQuery.ts index 5952de44..2d6a6ef8 100644 --- a/src/components/hooks/queries/useWebsiteMetricsQuery.ts +++ b/src/components/hooks/queries/useWebsiteMetricsQuery.ts @@ -15,7 +15,7 @@ export function useWebsiteMetricsQuery( options?: ReactQueryOptions, ) { const { get, useQuery } = useApi(); - const filterParams = useFilterParams(websiteId); + const queryParams = useFilterParams(websiteId); const searchParams = useSearchParams(); return useQuery({ @@ -23,13 +23,13 @@ export function useWebsiteMetricsQuery( 'websites:metrics', { websiteId, - ...filterParams, + ...queryParams, ...params, }, ], queryFn: async () => get(`/websites/${websiteId}/metrics`, { - ...filterParams, + ...queryParams, [searchParams.get('view')]: undefined, ...params, }), diff --git a/src/components/hooks/queries/useWebsitePageviewsQuery.ts b/src/components/hooks/queries/useWebsitePageviewsQuery.ts index f815f41a..63ec88ea 100644 --- a/src/components/hooks/queries/useWebsitePageviewsQuery.ts +++ b/src/components/hooks/queries/useWebsitePageviewsQuery.ts @@ -12,11 +12,11 @@ export function useWebsitePageviewsQuery( options?: ReactQueryOptions, ) { const { get, useQuery } = useApi(); - const filterParams = useFilterParams(websiteId); + const queryParams = useFilterParams(websiteId); return useQuery({ - queryKey: ['websites:pageviews', { websiteId, compare, ...filterParams }], - queryFn: () => get(`/websites/${websiteId}/pageviews`, { compare, ...filterParams }), + queryKey: ['websites:pageviews', { websiteId, compare, ...queryParams }], + queryFn: () => get(`/websites/${websiteId}/pageviews`, { compare, ...queryParams }), enabled: !!websiteId, ...options, }); diff --git a/src/components/hooks/queries/useWebsiteQuery.ts b/src/components/hooks/queries/useWebsiteQuery.ts index 30d9fbcf..55fe4eba 100644 --- a/src/components/hooks/queries/useWebsiteQuery.ts +++ b/src/components/hooks/queries/useWebsiteQuery.ts @@ -1,6 +1,6 @@ import { useApi } from '../useApi'; -export function useWebsiteQuery(websiteId: string, options?: { [key: string]: any }) { +export function useWebsiteQuery(websiteId: string, options?: Record) { const { get, useQuery } = useApi(); return useQuery({ diff --git a/src/components/hooks/queries/useWebsiteSessionStatsQuery.ts b/src/components/hooks/queries/useWebsiteSessionStatsQuery.ts index 4fa8e666..d60b3c77 100644 --- a/src/components/hooks/queries/useWebsiteSessionStatsQuery.ts +++ b/src/components/hooks/queries/useWebsiteSessionStatsQuery.ts @@ -1,10 +1,7 @@ import { useApi } from '../useApi'; import { useFilterParams } from '../useFilterParams'; -export function useWebsiteSessionStatsQuery( - websiteId: string, - options?: { [key: string]: string }, -) { +export function useWebsiteSessionStatsQuery(websiteId: string, options?: Record) { const { get, useQuery } = useApi(); const params = useFilterParams(websiteId); diff --git a/src/components/hooks/queries/useWebsiteSessionsQuery.ts b/src/components/hooks/queries/useWebsiteSessionsQuery.ts index 0a24a1b5..38405377 100644 --- a/src/components/hooks/queries/useWebsiteSessionsQuery.ts +++ b/src/components/hooks/queries/useWebsiteSessionsQuery.ts @@ -5,7 +5,7 @@ import { useFilterParams } from '@/components/hooks/useFilterParams'; export function useWebsiteSessionsQuery( websiteId: string, - params?: { [key: string]: string | number }, + params?: Record, ) { const { get } = useApi(); const { modified } = useModified(`sessions`); diff --git a/src/components/hooks/queries/useWebsiteSessionsWeeklyQuery.ts b/src/components/hooks/queries/useWebsiteSessionsWeeklyQuery.ts index 4a07f38d..ecfbde84 100644 --- a/src/components/hooks/queries/useWebsiteSessionsWeeklyQuery.ts +++ b/src/components/hooks/queries/useWebsiteSessionsWeeklyQuery.ts @@ -4,7 +4,7 @@ import { useFilterParams } from '@/components/hooks/useFilterParams'; export function useWebsiteSessionsWeeklyQuery( websiteId: string, - params?: { [key: string]: string | number }, + params?: Record, ) { const { get, useQuery } = useApi(); const { modified } = useModified(`sessions`); diff --git a/src/components/hooks/queries/useWebsiteStatsQuery.ts b/src/components/hooks/queries/useWebsiteStatsQuery.ts index 2d5595e0..4bf5f2d3 100644 --- a/src/components/hooks/queries/useWebsiteStatsQuery.ts +++ b/src/components/hooks/queries/useWebsiteStatsQuery.ts @@ -19,15 +19,14 @@ export interface WebsiteStatsData { export function useWebsiteStatsQuery( websiteId: string, - compare?: string, options?: UseQueryOptions, ) { const { get, useQuery } = useApi(); - const params = useFilterParams(websiteId); + const filterParams = useFilterParams(websiteId); return useQuery({ - queryKey: ['websites:stats', { websiteId, ...params, compare }], - queryFn: () => get(`/websites/${websiteId}/stats`, { ...params, compare }), + queryKey: ['websites:stats', { websiteId, ...filterParams }], + queryFn: () => get(`/websites/${websiteId}/stats`, { ...filterParams }), enabled: !!websiteId, ...options, }); diff --git a/src/components/hooks/queries/useWebsites.ts b/src/components/hooks/queries/useWebsitesQuery.ts similarity index 73% rename from src/components/hooks/queries/useWebsites.ts rename to src/components/hooks/queries/useWebsitesQuery.ts index f9cd5110..fd168ef1 100644 --- a/src/components/hooks/queries/useWebsites.ts +++ b/src/components/hooks/queries/useWebsitesQuery.ts @@ -2,10 +2,12 @@ import { useApi } from '../useApi'; import { usePagedQuery } from '../usePagedQuery'; import { useLoginQuery } from './useLoginQuery'; import { useModified } from '../useModified'; +import { ReactQueryOptions } from '@/lib/types'; -export function useWebsites( +export function useWebsitesQuery( { userId, teamId }: { userId?: string; teamId?: string }, - params?: { [key: string]: string | number }, + params?: Record, + options?: ReactQueryOptions, ) { const { get } = useApi(); const { user } = useLoginQuery(); @@ -13,10 +15,12 @@ export function useWebsites( return usePagedQuery({ queryKey: ['websites', { userId, teamId, modified, ...params }], - queryFn: () => { + queryFn: pageParams => { return get(teamId ? `/teams/${teamId}/websites` : `/users/${userId || user.id}/websites`, { ...params, + ...pageParams, }); }, + ...options, }); } diff --git a/src/components/hooks/useFormat.ts b/src/components/hooks/useFormat.ts index 6f0b436f..039959cd 100644 --- a/src/components/hooks/useFormat.ts +++ b/src/components/hooks/useFormat.ts @@ -40,7 +40,7 @@ export function useFormat() { return languageNames[value?.split('-')[0]] || value; }; - const formatValue = (value: string, type: string, data?: { [key: string]: any }): string => { + const formatValue = (value: string, type: string, data?: Record): string => { switch (type) { case 'os': return formatOS(value); diff --git a/src/components/hooks/useMessages.ts b/src/components/hooks/useMessages.ts index f06f936b..e02b5951 100644 --- a/src/components/hooks/useMessages.ts +++ b/src/components/hooks/useMessages.ts @@ -15,7 +15,7 @@ export function useMessages(): any { id: string; defaultMessage: string; }, - values?: { [key: string]: string }, + values?: Record, opts?: any, ) => { return descriptor ? intl.formatMessage(descriptor, values, opts) : null; diff --git a/src/components/hooks/useNavigation.ts b/src/components/hooks/useNavigation.ts index 2d8644df..3d02a9a0 100644 --- a/src/components/hooks/useNavigation.ts +++ b/src/components/hooks/useNavigation.ts @@ -9,11 +9,11 @@ export function useNavigation() { const [, websiteId] = pathname.match(/\/websites\/([a-f0-9-]+)/) || []; const query = Object.fromEntries(searchParams); - const updateParams = (params?: { [key: string]: string | number }) => { + const updateParams = (params?: Record) => { return !params ? pathname : buildUrl(pathname, { ...query, ...params }); }; - const renderUrl = (path: string, params?: { [key: string]: string | number } | false) => { + const renderUrl = (path: string, params?: Record | false) => { return buildUrl( teamId ? `/teams/${teamId}${path}` : path, params === false ? {} : { ...query, ...params }, diff --git a/src/components/hooks/usePagedQuery.ts b/src/components/hooks/usePagedQuery.ts index 6b995ea5..4cc53476 100644 --- a/src/components/hooks/usePagedQuery.ts +++ b/src/components/hooks/usePagedQuery.ts @@ -1,30 +1,27 @@ import { UseQueryOptions } from '@tanstack/react-query'; import { useState } from 'react'; -import { PageResult, PageParams, PagedQueryResult } from '@/lib/types'; import { useApi } from './useApi'; import { useNavigation } from './useNavigation'; -export function usePagedQuery({ +export function usePagedQuery({ queryKey, queryFn, ...options -}: Omit & { queryFn: (params?: object) => any }): PagedQueryResult { +}: Omit & { queryFn: (params?: object) => any }) { const { query: queryParams } = useNavigation(); - const [params, setParams] = useState({ - search: '', - page: queryParams?.page || '1', + const [params, setParams] = useState({ + search: queryParams?.search ?? '', + page: queryParams?.page ?? '1', }); const { useQuery } = useApi(); - const { data, ...query } = useQuery({ - queryKey: [{ ...queryKey, ...params }], - queryFn: () => queryFn(params as any), - ...options, - }); return { - result: data as PageResult, - query, + ...useQuery({ + queryKey: [{ ...queryKey, ...params }], + queryFn: () => queryFn(params), + ...options, + }), params, setParams, }; diff --git a/src/components/input/WebsiteSelect.tsx b/src/components/input/WebsiteSelect.tsx index fac60755..b0b0f881 100644 --- a/src/components/input/WebsiteSelect.tsx +++ b/src/components/input/WebsiteSelect.tsx @@ -1,7 +1,6 @@ import { useState } from 'react'; -import { Select, ListItem } from '@umami/react-zen'; -import { useWebsites, useMessages } from '@/components/hooks'; -import type { SelectProps } from '@umami/react-zen/Select'; +import { Select, SelectProps, ListItem } from '@umami/react-zen'; +import { useWebsitesQuery, useMessages } from '@/components/hooks'; export function WebsiteSelect({ websiteId, @@ -12,14 +11,14 @@ export function WebsiteSelect({ }: { websiteId?: string; teamId?: string; - variant?: 'primary' | 'secondary' | 'outline' | 'quiet' | 'danger' | 'zero'; + variant?: 'primary' | 'outline' | 'quiet' | 'danger' | 'zero'; onSelect?: (key: any) => void; } & SelectProps) { const { formatMessage, labels } = useMessages(); const [search, setSearch] = useState(''); const [selectedId, setSelectedId] = useState(websiteId); - const queryResult = useWebsites({ teamId }, { search, pageSize: 5 }); + const { data, isLoading } = useWebsitesQuery({ teamId }, { search, pageSize: 5 }); const handleSelect = (value: any) => { setSelectedId(value); @@ -30,15 +29,17 @@ export function WebsiteSelect({ setSearch(value); }; - const items = queryResult?.result?.data as any[]; + if (!data) { + return null; + } return ( Date: Tue, 8 Jul 2025 18:40:47 -0700 Subject: [PATCH 120/399] New admin section. --- .../admin/teams/AdminTeamsDataTable.tsx | 19 +++++ src/app/(main)/admin/teams/AdminTeamsPage.tsx | 16 ++++ .../(main)/admin/teams/AdminTeamsTable.tsx | 78 +++++++++++++++++ .../admin/teams/[teamId]/AdminTeamPage.tsx | 10 +++ src/app/(main)/admin/teams/[teamId]/page.tsx | 17 ++++ src/app/(main)/admin/teams/page.tsx | 9 ++ src/app/(main)/admin/users/UsersDataTable.tsx | 2 +- .../{UsersSettingsPage.tsx => UsersPage.tsx} | 2 +- src/app/(main)/admin/users/UsersTable.tsx | 30 ++----- .../admin/users/[userId]/UserWebsites.tsx | 6 +- src/app/(main)/admin/users/[userId]/page.tsx | 2 +- src/app/(main)/admin/users/page.tsx | 4 +- .../admin/websites/AdminWebsitesDataTable.tsx | 13 +++ .../admin/websites/AdminWebsitesPage.tsx | 16 ++++ .../admin/websites/AdminWebsitesTable.tsx | 85 +++++++++++++++++++ src/app/(main)/admin/websites/page.tsx | 9 ++ .../(main)/settings/teams/TeamsDataTable.tsx | 6 +- .../settings/websites/WebsitesDataTable.tsx | 6 +- .../websites/[websiteId]/WebsiteData.tsx | 8 +- .../[websiteId]/WebsiteTransferForm.tsx | 4 +- .../settings/members/TeamMembersDataTable.tsx | 2 +- .../[teamId]/settings/team/TeamEditForm.tsx | 2 +- .../websites/TeamWebsitesDataTable.tsx | 2 +- .../[websiteId]/events/EventsDataTable.tsx | 2 +- .../sessions/SessionsDataTable.tsx | 2 +- src/app/api/admin/teams/route.ts | 54 ++++++++++++ src/app/api/admin/users/route.ts | 6 +- src/app/api/admin/websites/route.ts | 48 ++--------- src/components/common/DataGrid.tsx | 33 ++++--- src/components/common/LinkButton.tsx | 11 ++- src/components/common/Pager.tsx | 9 +- src/components/hooks/index.ts | 2 + src/components/hooks/queries/useTeamsQuery.ts | 19 +++-- .../hooks/queries/useUserTeamsQuery.ts | 15 ++++ .../hooks/queries/useUserWebsitesQuery.ts | 26 ++++++ src/components/hooks/queries/useUsersQuery.ts | 4 +- .../hooks/queries/useWebsitesQuery.ts | 14 +-- src/components/hooks/useNavigation.ts | 22 ++++- src/components/hooks/usePagedQuery.ts | 37 ++++---- src/components/input/TeamsButton.tsx | 4 +- src/components/input/WebsiteSelect.tsx | 4 +- src/lib/auth.ts | 4 + src/lib/clickhouse.ts | 4 +- src/lib/prisma.ts | 4 +- 44 files changed, 515 insertions(+), 157 deletions(-) create mode 100644 src/app/(main)/admin/teams/AdminTeamsDataTable.tsx create mode 100644 src/app/(main)/admin/teams/AdminTeamsPage.tsx create mode 100644 src/app/(main)/admin/teams/AdminTeamsTable.tsx create mode 100644 src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx create mode 100644 src/app/(main)/admin/teams/[teamId]/page.tsx create mode 100644 src/app/(main)/admin/teams/page.tsx rename src/app/(main)/admin/users/{UsersSettingsPage.tsx => UsersPage.tsx} (93%) create mode 100644 src/app/(main)/admin/websites/AdminWebsitesDataTable.tsx create mode 100644 src/app/(main)/admin/websites/AdminWebsitesPage.tsx create mode 100644 src/app/(main)/admin/websites/AdminWebsitesTable.tsx create mode 100644 src/app/(main)/admin/websites/page.tsx create mode 100644 src/app/api/admin/teams/route.ts create mode 100644 src/components/hooks/queries/useUserTeamsQuery.ts create mode 100644 src/components/hooks/queries/useUserWebsitesQuery.ts diff --git a/src/app/(main)/admin/teams/AdminTeamsDataTable.tsx b/src/app/(main)/admin/teams/AdminTeamsDataTable.tsx new file mode 100644 index 00000000..53e18248 --- /dev/null +++ b/src/app/(main)/admin/teams/AdminTeamsDataTable.tsx @@ -0,0 +1,19 @@ +import { DataGrid } from '@/components/common/DataGrid'; +import { useTeamsQuery } from '@/components/hooks'; +import { AdminTeamsTable } from './AdminTeamsTable'; +import { ReactNode } from 'react'; + +export function AdminTeamsDataTable({ + showActions, +}: { + showActions?: boolean; + children?: ReactNode; +}) { + const queryResult = useTeamsQuery(); + + return ( + + {({ data }) => } + + ); +} diff --git a/src/app/(main)/admin/teams/AdminTeamsPage.tsx b/src/app/(main)/admin/teams/AdminTeamsPage.tsx new file mode 100644 index 00000000..37f43c94 --- /dev/null +++ b/src/app/(main)/admin/teams/AdminTeamsPage.tsx @@ -0,0 +1,16 @@ +'use client'; +import { AdminTeamsDataTable } from './AdminTeamsDataTable'; +import { Column } from '@umami/react-zen'; +import { SectionHeader } from '@/components/common/SectionHeader'; +import { useMessages } from '@/components/hooks'; + +export function AdminTeamsPage() { + const { formatMessage, labels } = useMessages(); + + return ( + + + + + ); +} diff --git a/src/app/(main)/admin/teams/AdminTeamsTable.tsx b/src/app/(main)/admin/teams/AdminTeamsTable.tsx new file mode 100644 index 00000000..6582cf38 --- /dev/null +++ b/src/app/(main)/admin/teams/AdminTeamsTable.tsx @@ -0,0 +1,78 @@ +import { useState } from 'react'; +import { Row, Text, Icon, DataTable, DataColumn, MenuItem, Modal } from '@umami/react-zen'; +import Link from 'next/link'; +import { Trash } from '@/components/icons'; +import { useMessages } from '@/components/hooks'; +import { Edit } from '@/components/icons'; +import { MenuButton } from '@/components/input/MenuButton'; +import { DateDistance } from '@/components/common/DateDistance'; + +export function AdminTeamsTable({ + data = [], + showActions = true, +}: { + data: any[]; + showActions?: boolean; +}) { + const { formatMessage, labels } = useMessages(); + const [deleteUser, setDeleteUser] = useState(null); + + return ( + <> + + + {(row: any) => {row.name}} + + + {(row: any) => row?._count?.teamUser} + + + {(row: any) => row?._count?.website} + + + {(row: any) => ( + + {row?.teamUser?.[0]?.user?.username} + + )} + + + {(row: any) => } + + {showActions && ( + + {(row: any) => { + const { id } = row; + + return ( + + + + + + + {formatMessage(labels.edit)} + + + setDeleteUser(row)} + data-test="link-button-delete" + > + + + + + {formatMessage(labels.delete)} + + + + ); + }} + + )} + + + + ); +} diff --git a/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx b/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx new file mode 100644 index 00000000..3edd1ed1 --- /dev/null +++ b/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx @@ -0,0 +1,10 @@ +'use client'; +import { TeamDetails } from '@/app/(main)/teams/[teamId]/settings/team/TeamDetails'; + +export function AdminTeamPage({ teamId }: { teamId: string }) { + return ( + <> + + + ); +} diff --git a/src/app/(main)/admin/teams/[teamId]/page.tsx b/src/app/(main)/admin/teams/[teamId]/page.tsx new file mode 100644 index 00000000..0dc9d538 --- /dev/null +++ b/src/app/(main)/admin/teams/[teamId]/page.tsx @@ -0,0 +1,17 @@ +import { AdminTeamPage } from './AdminTeamPage'; +import { TeamProvider } from '@/app/(main)/teams/[teamId]/TeamProvider'; +import { Metadata } from 'next'; + +export default async function ({ params }: { params: Promise<{ teamId: string }> }) { + const { teamId } = await params; + + return ( + + + + ); +} + +export const metadata: Metadata = { + title: 'Team', +}; diff --git a/src/app/(main)/admin/teams/page.tsx b/src/app/(main)/admin/teams/page.tsx new file mode 100644 index 00000000..fb0fd342 --- /dev/null +++ b/src/app/(main)/admin/teams/page.tsx @@ -0,0 +1,9 @@ +import { Metadata } from 'next'; +import { AdminTeamsPage } from './AdminTeamsPage'; + +export default function () { + return ; +} +export const metadata: Metadata = { + title: 'Teams', +}; diff --git a/src/app/(main)/admin/users/UsersDataTable.tsx b/src/app/(main)/admin/users/UsersDataTable.tsx index d0cc5ec8..ae72cfed 100644 --- a/src/app/(main)/admin/users/UsersDataTable.tsx +++ b/src/app/(main)/admin/users/UsersDataTable.tsx @@ -7,7 +7,7 @@ export function UsersDataTable({ showActions }: { showActions?: boolean; childre const queryResult = useUsersQuery(); return ( - + {({ data }) => } ); diff --git a/src/app/(main)/admin/users/UsersSettingsPage.tsx b/src/app/(main)/admin/users/UsersPage.tsx similarity index 93% rename from src/app/(main)/admin/users/UsersSettingsPage.tsx rename to src/app/(main)/admin/users/UsersPage.tsx index b2e53dac..5c8a1ae3 100644 --- a/src/app/(main)/admin/users/UsersSettingsPage.tsx +++ b/src/app/(main)/admin/users/UsersPage.tsx @@ -5,7 +5,7 @@ import { SectionHeader } from '@/components/common/SectionHeader'; import { useMessages } from '@/components/hooks'; import { UserAddButton } from './UserAddButton'; -export function UsersSettingsPage() { +export function UsersPage() { const { formatMessage, labels } = useMessages(); const handleSave = () => {}; diff --git a/src/app/(main)/admin/users/UsersTable.tsx b/src/app/(main)/admin/users/UsersTable.tsx index ffa0ec33..a78e66f2 100644 --- a/src/app/(main)/admin/users/UsersTable.tsx +++ b/src/app/(main)/admin/users/UsersTable.tsx @@ -1,22 +1,13 @@ import { useState } from 'react'; -import { - Row, - Text, - Icon, - DataTable, - DataColumn, - MenuItem, - MenuSeparator, - Modal, -} from '@umami/react-zen'; +import { Row, Text, Icon, DataTable, DataColumn, MenuItem, Modal } from '@umami/react-zen'; import Link from 'next/link'; -import { formatDistance } from 'date-fns'; import { ROLES } from '@/lib/constants'; import { Trash } from '@/components/icons'; -import { useMessages, useLocale } from '@/components/hooks'; +import { useMessages } from '@/components/hooks'; import { Edit } from '@/components/icons'; import { MenuButton } from '@/components/input/MenuButton'; import { UserDeleteForm } from './UserDeleteForm'; +import { DateDistance } from '@/components/common/DateDistance'; export function UsersTable({ data = [], @@ -26,7 +17,6 @@ export function UsersTable({ showActions?: boolean; }) { const { formatMessage, labels } = useMessages(); - const { dateLocale } = useLocale(); const [deleteUser, setDeleteUser] = useState(null); return ( @@ -42,17 +32,12 @@ export function UsersTable({ ) } - - {(row: any) => - formatDistance(new Date(row.createdAt), new Date(), { - addSuffix: true, - locale: dateLocale, - }) - } - - + {(row: any) => row._count.websiteUser} + + {(row: any) => } + {showActions && ( {(row: any) => { @@ -68,7 +53,6 @@ export function UsersTable({ {formatMessage(labels.edit)} - setDeleteUser(row)} diff --git a/src/app/(main)/admin/users/[userId]/UserWebsites.tsx b/src/app/(main)/admin/users/[userId]/UserWebsites.tsx index 63a06867..c3e4960e 100644 --- a/src/app/(main)/admin/users/[userId]/UserWebsites.tsx +++ b/src/app/(main)/admin/users/[userId]/UserWebsites.tsx @@ -1,12 +1,12 @@ import { DataGrid } from '@/components/common/DataGrid'; -import { useWebsitesQuery } from '@/components/hooks'; +import { useUserWebsitesQuery } from '@/components/hooks'; import { WebsitesTable } from '@/app/(main)/settings/websites/WebsitesTable'; export function UserWebsites({ userId }) { - const queryResult = useWebsitesQuery({ userId }); + const queryResult = useUserWebsitesQuery({ userId }); return ( - + {({ data }) => ( )} diff --git a/src/app/(main)/admin/users/[userId]/page.tsx b/src/app/(main)/admin/users/[userId]/page.tsx index 47bd3531..5d0eea99 100644 --- a/src/app/(main)/admin/users/[userId]/page.tsx +++ b/src/app/(main)/admin/users/[userId]/page.tsx @@ -8,5 +8,5 @@ export default async function ({ params }: { params: Promise<{ userId: string }> } export const metadata: Metadata = { - title: 'User Settings', + title: 'Users', }; diff --git a/src/app/(main)/admin/users/page.tsx b/src/app/(main)/admin/users/page.tsx index 311e4cb2..7cfd4887 100644 --- a/src/app/(main)/admin/users/page.tsx +++ b/src/app/(main)/admin/users/page.tsx @@ -1,8 +1,8 @@ import { Metadata } from 'next'; -import { UsersSettingsPage } from './UsersSettingsPage'; +import { UsersPage } from './UsersPage'; export default function () { - return ; + return ; } export const metadata: Metadata = { title: 'Users', diff --git a/src/app/(main)/admin/websites/AdminWebsitesDataTable.tsx b/src/app/(main)/admin/websites/AdminWebsitesDataTable.tsx new file mode 100644 index 00000000..21059924 --- /dev/null +++ b/src/app/(main)/admin/websites/AdminWebsitesDataTable.tsx @@ -0,0 +1,13 @@ +import { DataGrid } from '@/components/common/DataGrid'; +import { useWebsitesQuery } from '@/components/hooks'; +import { AdminWebsitesTable } from './AdminWebsitesTable'; + +export function AdminWebsitesDataTable() { + const query = useWebsitesQuery(); + + return ( + + {props => } + + ); +} diff --git a/src/app/(main)/admin/websites/AdminWebsitesPage.tsx b/src/app/(main)/admin/websites/AdminWebsitesPage.tsx new file mode 100644 index 00000000..07a73a40 --- /dev/null +++ b/src/app/(main)/admin/websites/AdminWebsitesPage.tsx @@ -0,0 +1,16 @@ +'use client'; +import { AdminWebsitesDataTable } from './AdminWebsitesDataTable'; +import { Column } from '@umami/react-zen'; +import { SectionHeader } from '@/components/common/SectionHeader'; +import { useMessages } from '@/components/hooks'; + +export function AdminWebsitesPage() { + const { formatMessage, labels } = useMessages(); + + return ( + + + + + ); +} diff --git a/src/app/(main)/admin/websites/AdminWebsitesTable.tsx b/src/app/(main)/admin/websites/AdminWebsitesTable.tsx new file mode 100644 index 00000000..99105bc3 --- /dev/null +++ b/src/app/(main)/admin/websites/AdminWebsitesTable.tsx @@ -0,0 +1,85 @@ +import { useState } from 'react'; +import Link from 'next/link'; +import { Row, Text, Icon, DataTable, DataColumn, MenuItem, Modal } from '@umami/react-zen'; +import { Trash, Users } from '@/components/icons'; +import { useMessages } from '@/components/hooks'; +import { Edit } from '@/components/icons'; +import { MenuButton } from '@/components/input/MenuButton'; +import { DateDistance } from '@/components/common/DateDistance'; + +export function AdminWebsitesTable({ data = [] }: { data: any[] }) { + const { formatMessage, labels } = useMessages(); + const [deleteUser, setDeleteUser] = useState(null); + + return ( + <> + + + {(row: any) => ( + + {row.name} + + )} + + + {(row: any) => {row.domain}} + + + {(row: any) => { + if (row?.team) { + return ( + + + + + + {row?.team?.name} + + + ); + } + return ( + + {row?.user?.username} + + ); + }} + + + {(row: any) => } + + + {(row: any) => { + const { id } = row; + + return ( + + + + + + + {formatMessage(labels.edit)} + + + setDeleteUser(row)} + data-test="link-button-delete" + > + + + + + {formatMessage(labels.delete)} + + + + ); + }} + + + + + ); +} diff --git a/src/app/(main)/admin/websites/page.tsx b/src/app/(main)/admin/websites/page.tsx new file mode 100644 index 00000000..85eb029a --- /dev/null +++ b/src/app/(main)/admin/websites/page.tsx @@ -0,0 +1,9 @@ +import { Metadata } from 'next'; +import { AdminWebsitesPage } from './AdminWebsitesPage'; + +export default function () { + return ; +} +export const metadata: Metadata = { + title: 'Websites', +}; diff --git a/src/app/(main)/settings/teams/TeamsDataTable.tsx b/src/app/(main)/settings/teams/TeamsDataTable.tsx index 309faca6..093917a0 100644 --- a/src/app/(main)/settings/teams/TeamsDataTable.tsx +++ b/src/app/(main)/settings/teams/TeamsDataTable.tsx @@ -1,6 +1,6 @@ import { DataGrid } from '@/components/common/DataGrid'; import { TeamsTable } from '@/app/(main)/settings/teams/TeamsTable'; -import { useLoginQuery, useTeamsQuery } from '@/components/hooks'; +import { useLoginQuery, useUserTeamsQuery } from '@/components/hooks'; import { ReactNode } from 'react'; export function TeamsDataTable({ @@ -13,10 +13,10 @@ export function TeamsDataTable({ children?: ReactNode; }) { const { user } = useLoginQuery(); - const queryResult = useTeamsQuery(user.id); + const queryResult = useUserTeamsQuery(user.id); return ( - children}> + children}> {({ data }) => { return ; }} diff --git a/src/app/(main)/settings/websites/WebsitesDataTable.tsx b/src/app/(main)/settings/websites/WebsitesDataTable.tsx index 042c0923..5015264a 100644 --- a/src/app/(main)/settings/websites/WebsitesDataTable.tsx +++ b/src/app/(main)/settings/websites/WebsitesDataTable.tsx @@ -1,6 +1,6 @@ import { WebsitesTable } from './WebsitesTable'; import { DataGrid } from '@/components/common/DataGrid'; -import { useWebsitesQuery } from '@/components/hooks'; +import { useUserWebsitesQuery } from '@/components/hooks'; export function WebsitesDataTable({ teamId, @@ -13,10 +13,10 @@ export function WebsitesDataTable({ allowView?: boolean; showActions?: boolean; }) { - const queryResult = useWebsitesQuery({ teamId }); + const queryResult = useUserWebsitesQuery({ teamId }); return ( - + {({ data }) => ( + data.filter(({ teamUser }) => teamUser.find( ({ role, userId }) => [ROLES.teamOwner, ROLES.teamManager].includes(role) && userId === user.id, @@ -31,7 +31,7 @@ export function WebsiteData({ websiteId, onSave }: { websiteId: string; onSave?: ) ).length > 0 || (teamId && - !!result?.data + !!data ?.find(({ id }) => id === teamId) ?.teamUser.find(({ role, userId }) => role === ROLES.teamOwner && userId === user.id)); diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteTransferForm.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteTransferForm.tsx index 610f3268..c101d4ba 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteTransferForm.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteTransferForm.tsx @@ -10,7 +10,7 @@ import { ListItem, Text, } from '@umami/react-zen'; -import { useApi, useLoginQuery, useMessages, useTeamsQuery } from '@/components/hooks'; +import { useApi, useLoginQuery, useMessages, useUserTeamsQuery } from '@/components/hooks'; import { WebsiteContext } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; import { ROLES } from '@/lib/constants'; @@ -31,7 +31,7 @@ export function WebsiteTransferForm({ const { mutate, error } = useMutation({ mutationFn: (data: any) => post(`/websites/${websiteId}/transfer`, data), }); - const { result, query } = useTeamsQuery(user.id); + const { result, query } = useUserTeamsQuery(user.id); const isTeamWebsite = !!website?.teamId; const items = result.data.filter(({ teamUser }) => diff --git a/src/app/(main)/teams/[teamId]/settings/members/TeamMembersDataTable.tsx b/src/app/(main)/teams/[teamId]/settings/members/TeamMembersDataTable.tsx index 32dd6c4a..25ccbab3 100644 --- a/src/app/(main)/teams/[teamId]/settings/members/TeamMembersDataTable.tsx +++ b/src/app/(main)/teams/[teamId]/settings/members/TeamMembersDataTable.tsx @@ -12,7 +12,7 @@ export function TeamMembersDataTable({ const queryResult = useTeamMembersQuery(teamId); return ( - + {({ data }) => } ); diff --git a/src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx b/src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx index a902e159..8ea3ddb9 100644 --- a/src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx +++ b/src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx @@ -48,7 +48,7 @@ export function TeamEditForm({ teamId, allowEdit }: { teamId: string; allowEdit? rules={{ required: formatMessage(labels.required) }} > {allowEdit && } - {!allowEdit && team.name} + {!allowEdit && team?.name} {!cloudMode && allowEdit && ( diff --git a/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesDataTable.tsx b/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesDataTable.tsx index bc7623de..1cb65eac 100644 --- a/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesDataTable.tsx +++ b/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesDataTable.tsx @@ -12,7 +12,7 @@ export function TeamWebsitesDataTable({ const queryResult = useTeamWebsitesQuery(teamId); return ( - + {({ data }) => } ); diff --git a/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx b/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx index 70c0ca56..f73ec442 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx @@ -37,7 +37,7 @@ export function EventsDataTable({ return ( + {({ data }) => { return ; }} diff --git a/src/app/api/admin/teams/route.ts b/src/app/api/admin/teams/route.ts new file mode 100644 index 00000000..6b162050 --- /dev/null +++ b/src/app/api/admin/teams/route.ts @@ -0,0 +1,54 @@ +import { z } from 'zod'; +import { parseRequest } from '@/lib/request'; +import { json, unauthorized } from '@/lib/response'; +import { pagingParams, searchParams } from '@/lib/schema'; +import { canViewAllTeams } from '@/lib/auth'; +import { getTeams } from '@/queries/prisma/team'; + +export async function GET(request: Request) { + const schema = z.object({ + ...pagingParams, + ...searchParams, + }); + + const { auth, query, error } = await parseRequest(request, schema); + + if (error) { + return error(); + } + + if (!(await canViewAllTeams(auth))) { + return unauthorized(); + } + + const teams = await getTeams( + { + include: { + _count: { + select: { + teamUser: true, + website: true, + }, + }, + teamUser: { + select: { + user: { + omit: { + password: true, + }, + }, + }, + where: { + role: 'team-owner', + }, + }, + }, + orderBy: { + createdAt: 'desc', + }, + }, + query, + ); + + return json(teams); +} diff --git a/src/app/api/admin/users/route.ts b/src/app/api/admin/users/route.ts index 2185e03e..3cf116f7 100644 --- a/src/app/api/admin/users/route.ts +++ b/src/app/api/admin/users/route.ts @@ -1,13 +1,14 @@ import { z } from 'zod'; import { parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; -import { pagingParams } from '@/lib/schema'; +import { pagingParams, searchParams } from '@/lib/schema'; import { canViewUsers } from '@/lib/auth'; import { getUsers } from '@/queries/prisma/user'; export async function GET(request: Request) { const schema = z.object({ ...pagingParams, + ...searchParams, }); const { auth, query, error } = await parseRequest(request, schema); @@ -31,6 +32,9 @@ export async function GET(request: Request) { }, }, }, + orderBy: { + createdAt: 'desc', + }, }, query, ); diff --git a/src/app/api/admin/websites/route.ts b/src/app/api/admin/websites/route.ts index 3f35ea49..2b82fbe8 100644 --- a/src/app/api/admin/websites/route.ts +++ b/src/app/api/admin/websites/route.ts @@ -1,17 +1,15 @@ import { z } from 'zod'; import { parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; -import { pagingParams } from '@/lib/schema'; +import { pagingParams, searchParams } from '@/lib/schema'; import { canViewAllWebsites } from '@/lib/auth'; import { getWebsites } from '@/queries/prisma/website'; import { ROLES } from '@/lib/constants'; export async function GET(request: Request) { const schema = z.object({ - userId: z.string().uuid(), - includeOwnedTeams: z.string().optional(), - includeAllTeams: z.string().optional(), ...pagingParams, + ...searchParams, }); const { auth, query, error } = await parseRequest(request, schema); @@ -24,46 +22,13 @@ export async function GET(request: Request) { return unauthorized(); } - const { userId, includeOwnedTeams, includeAllTeams } = query; - const websites = await getWebsites( { - where: { - OR: [ - ...(userId && [{ userId }]), - ...(userId && includeOwnedTeams - ? [ - { - team: { - deletedAt: null, - teamUser: { - some: { - role: ROLES.teamOwner, - userId, - }, - }, - }, - }, - ] - : []), - ...(userId && includeAllTeams - ? [ - { - team: { - deletedAt: null, - teamUser: { - some: { - userId, - }, - }, - }, - }, - ] - : []), - ], - }, include: { user: { + where: { + deletedAt: null, + }, select: { username: true, id: true, @@ -82,6 +47,9 @@ export async function GET(request: Request) { }, }, }, + orderBy: { + createdAt: 'desc', + }, }, query, ); diff --git a/src/components/common/DataGrid.tsx b/src/components/common/DataGrid.tsx index 22344875..82c2bfdb 100644 --- a/src/components/common/DataGrid.tsx +++ b/src/components/common/DataGrid.tsx @@ -1,13 +1,15 @@ -import { ReactNode, useState } from 'react'; +import { ReactNode, useState, useCallback } from 'react'; import { SearchField, Row, Column } from '@umami/react-zen'; +import { UseQueryResult } from '@tanstack/react-query'; import { useMessages, useNavigation } from '@/components/hooks'; import { Pager } from '@/components/common/Pager'; import { LoadingPanel } from '@/components/common/LoadingPanel'; +import { PageResult } from '@/lib/types'; const DEFAULT_SEARCH_DELAY = 600; export interface DataGridProps { - queryResult: any; + query: UseQueryResult, any>; searchDelay?: number; allowSearch?: boolean; allowPaging?: boolean; @@ -17,7 +19,7 @@ export interface DataGridProps { } export function DataGrid({ - queryResult, + query, searchDelay = 600, allowSearch, allowPaging = true, @@ -26,20 +28,23 @@ export function DataGrid({ children, }: DataGridProps) { const { formatMessage, labels } = useMessages(); - const { data, error, isLoading, isFetching, setParams } = queryResult; - const { router, updateParams } = useNavigation(); - const [search, setSearch] = useState(''); + const { data, error, isLoading, isFetching } = query; + const { router, updateParams, query: queryParams } = useNavigation(); + const [search, setSearch] = useState(queryParams?.saerch || data?.search || ''); - const handleSearch = (search: string) => { - setSearch(search); - setParams(params => ({ ...params, search })); - router.push(updateParams({ search })); + const handleSearch = (value: string) => { + if (value !== search) { + setSearch(value); + router.push(updateParams({ search: value, page: 1 })); + } }; - const handlePageChange = (page: number) => { - setParams(params => ({ ...params, page })); - router.push(updateParams({ page })); - }; + const handlePageChange = useCallback( + (page: number) => { + router.push(updateParams({ search, page })); + }, + [search], + ); return ( diff --git a/src/components/common/LinkButton.tsx b/src/components/common/LinkButton.tsx index ca1baccb..69a025d1 100644 --- a/src/components/common/LinkButton.tsx +++ b/src/components/common/LinkButton.tsx @@ -17,13 +17,20 @@ export function LinkButton({ scroll = true, target, children, + isDisabled, ...props }: LinkButtonProps) { const { dir } = useLocale(); return ( - diff --git a/src/components/common/Pager.tsx b/src/components/common/Pager.tsx index 3f1802dd..31ff8aa5 100644 --- a/src/components/common/Pager.tsx +++ b/src/components/common/Pager.tsx @@ -34,9 +34,14 @@ export function Pager({ page, pageSize, count, onPageChange }: PagerProps) { return ( - {formatMessage(labels.numberOfRecords, { x: count })} + {formatMessage(labels.numberOfRecords, { x: count.toLocaleString() })} - {formatMessage(labels.pageOf, { current: page, total: maxPage })} + + {formatMessage(labels.pageOf, { + current: page.toLocaleString(), + total: maxPage.toLocaleString(), + })} + -
- ); - })} -
- ); -} diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx index 767ffba0..d304562f 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx @@ -19,19 +19,21 @@ export function WebsiteData({ websiteId, onSave }: { websiteId: string; onSave?: const { touch } = useModified(); const { teamId, renderUrl } = useNavigation(); const router = useRouter(); - const { data } = useUserTeamsQuery(user.id); + const { data: teams } = useUserTeamsQuery(user.id); + const canTransferWebsite = ( - !teamId && - data.filter(({ teamUser }) => - teamUser.find( - ({ role, userId }) => - [ROLES.teamOwner, ROLES.teamManager].includes(role) && userId === user.id, - ), - ) + (!teamId && + teams?.data?.filter(({ teamUser }) => + teamUser.find( + ({ role, userId }) => + [ROLES.teamOwner, ROLES.teamManager].includes(role) && userId === user.id, + ), + )) || + [] ).length > 0 || (teamId && - !!data + !!teams?.data ?.find(({ id }) => id === teamId) ?.teamUser.find(({ role, userId }) => role === ROLES.teamOwner && userId === user.id)); diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteShareForm.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteShareForm.tsx index 6a9bbbb7..dd3dcd26 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteShareForm.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteShareForm.tsx @@ -6,17 +6,13 @@ import { Switch, FormSubmitButton, Column, - Icon, - Grid, Label, useToast, - TooltipTrigger, - Tooltip, + Row, } from '@umami/react-zen'; import { useState } from 'react'; import { getRandomChars } from '@/lib/crypto'; import { useApi, useMessages, useModified } from '@/components/hooks'; -import { Refresh } from '@/components/icons'; const generateId = () => getRandomChars(16); @@ -70,24 +66,19 @@ export function WebsiteShareForm({ websiteId, shareId, onSave, onClose }: Websit {id && ( - - - - - {formatMessage(labels.regenerate)} - - + )} - - - - {formatMessage(labels.save)} - + + + {id && } + + + {onClose && } + + {formatMessage(labels.save)} + + diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteTransferForm.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteTransferForm.tsx index c101d4ba..1545f84d 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteTransferForm.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteTransferForm.tsx @@ -31,15 +31,16 @@ export function WebsiteTransferForm({ const { mutate, error } = useMutation({ mutationFn: (data: any) => post(`/websites/${websiteId}/transfer`, data), }); - const { result, query } = useUserTeamsQuery(user.id); + const { data: teams, isLoading } = useUserTeamsQuery(user.id); const isTeamWebsite = !!website?.teamId; - const items = result.data.filter(({ teamUser }) => - teamUser.find( - ({ role, userId }) => - [ROLES.teamOwner, ROLES.teamManager].includes(role) && userId === user.id, - ), - ); + const items = + teams?.data?.filter(({ teamUser }) => + teamUser.find( + ({ role, userId }) => + [ROLES.teamOwner, ROLES.teamManager].includes(role) && userId === user.id, + ), + ) || []; const handleSubmit = async () => { mutate( @@ -60,7 +61,7 @@ export function WebsiteTransferForm({ setTeamId(key as string); }; - if (query.isLoading) { + if (isLoading) { return ; } diff --git a/src/app/(main)/teams/[teamId]/settings/team/TeamDetails.tsx b/src/app/(main)/teams/[teamId]/settings/team/TeamDetails.tsx index e4500c96..d7782956 100644 --- a/src/app/(main)/teams/[teamId]/settings/team/TeamDetails.tsx +++ b/src/app/(main)/teams/[teamId]/settings/team/TeamDetails.tsx @@ -1,12 +1,15 @@ +import { useContext, useState } from 'react'; +import { Column, Tabs, TabList, Tab, TabPanel } from '@umami/react-zen'; import { TeamContext } from '@/app/(main)/teams/[teamId]/TeamProvider'; import { useLoginQuery, useMessages } from '@/components/hooks'; import { SectionHeader } from '@/components/common/SectionHeader'; import { ROLES } from '@/lib/constants'; -import { useContext, useState } from 'react'; -import { Column, Tabs, TabList, Tab, TabPanel } from '@umami/react-zen'; +import { Users } from '@/components/icons'; import { TeamLeaveButton } from '@/app/(main)/settings/teams/TeamLeaveButton'; import { TeamManage } from './TeamManage'; import { TeamEditForm } from './TeamEditForm'; +import { TeamWebsitesDataTable } from '@/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesDataTable'; +import { TeamMembersDataTable } from '@/app/(main)/teams/[teamId]/settings/members/TeamMembersDataTable'; export function TeamDetails({ teamId }: { teamId: string }) { const team = useContext(TeamContext); @@ -26,17 +29,25 @@ export function TeamDetails({ teamId }: { teamId: string }) { return ( - + }> {!isTeamOwner && } setTab(value)}> {formatMessage(labels.details)} + {formatMessage(labels.members)} + {formatMessage(labels.websites)} {isTeamOwner && {formatMessage(labels.manage)}} + + + + + + diff --git a/src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx b/src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx index 8ea3ddb9..fad603bb 100644 --- a/src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx +++ b/src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx @@ -6,6 +6,7 @@ import { TextField, Button, useToast, + Text, } from '@umami/react-zen'; import { getRandomChars } from '@/lib/crypto'; import { useContext } from 'react'; @@ -47,8 +48,7 @@ export function TeamEditForm({ teamId, allowEdit }: { teamId: string; allowEdit? label={formatMessage(labels.name)} rules={{ required: formatMessage(labels.required) }} > - {allowEdit && } - {!allowEdit && team?.name} + {allowEdit ? : {team?.name}} {!cloudMode && allowEdit && ( diff --git a/src/app/api/admin/users/route.ts b/src/app/api/admin/users/route.ts index 3cf116f7..d0d3fcbd 100644 --- a/src/app/api/admin/users/route.ts +++ b/src/app/api/admin/users/route.ts @@ -32,6 +32,9 @@ export async function GET(request: Request) { }, }, }, + omit: { + password: true, + }, orderBy: { createdAt: 'desc', }, diff --git a/src/components/common/SectionHeader.tsx b/src/components/common/SectionHeader.tsx index 752e0a5b..baaaa8b9 100644 --- a/src/components/common/SectionHeader.tsx +++ b/src/components/common/SectionHeader.tsx @@ -18,7 +18,7 @@ export function SectionHeader({ return ( - {icon && {icon}} + {icon && {icon}} {title && {title}} {description && {description}} diff --git a/src/components/hooks/queries/useTeamsQuery.ts b/src/components/hooks/queries/useTeamsQuery.ts index 205545ff..1e78db84 100644 --- a/src/components/hooks/queries/useTeamsQuery.ts +++ b/src/components/hooks/queries/useTeamsQuery.ts @@ -1,6 +1,6 @@ import { useApi } from '../useApi'; import { useModified } from '../useModified'; -import { usePagedQuery } from '@/components/hooks'; +import { usePagedQuery } from '../usePagedQuery'; import { ReactQueryOptions } from '@/lib/types'; export function useTeamsQuery(params?: Record, options?: ReactQueryOptions) { @@ -8,7 +8,7 @@ export function useTeamsQuery(params?: Record, options?: ReactQuery const { modified } = useModified(`teams`); return usePagedQuery({ - queryKey: ['websites', { modified, ...params }], + queryKey: ['teams:admin', { modified, ...params }], queryFn: pageParams => { return get(`/admin/teams`, { ...params, diff --git a/src/components/hooks/queries/useUsersQuery.ts b/src/components/hooks/queries/useUsersQuery.ts index 2723c6b1..03e66ce0 100644 --- a/src/components/hooks/queries/useUsersQuery.ts +++ b/src/components/hooks/queries/useUsersQuery.ts @@ -7,7 +7,7 @@ export function useUsersQuery() { const { modified } = useModified(`users`); return usePagedQuery({ - queryKey: ['users', { modified }], + queryKey: ['users:admin', { modified }], queryFn: (pageParams: any) => { return get('/admin/users', { ...pageParams, diff --git a/src/components/hooks/queries/useWebsitesQuery.ts b/src/components/hooks/queries/useWebsitesQuery.ts index d33ab77c..819b42a9 100644 --- a/src/components/hooks/queries/useWebsitesQuery.ts +++ b/src/components/hooks/queries/useWebsitesQuery.ts @@ -8,7 +8,7 @@ export function useWebsitesQuery(params?: Record, options?: ReactQu const { modified } = useModified(`websites`); return usePagedQuery({ - queryKey: ['websites', { modified, ...params }], + queryKey: ['websites:admin', { modified, ...params }], queryFn: pageParams => { return get(`/admin/websites`, { ...pageParams, diff --git a/src/index.ts b/src/index.ts index 2a077a12..b3d2de2a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,7 +24,6 @@ export * from '@/app/(main)/settings/teams/TeamsDataTable'; export * from '@/app/(main)/settings/teams/TeamsHeader'; export * from '@/app/(main)/settings/teams/TeamsJoinButton'; export * from '@/app/(main)/settings/teams/TeamsTable'; -export * from '@/app/(main)/settings/teams/WebsiteTags'; export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteShareForm'; export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteTrackingCode'; From c98f324c22858e1cdd13d450e877b5927eb0581a Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 11 Jul 2025 22:55:30 -0700 Subject: [PATCH 122/399] Settings refactor. --- db/postgresql/schema.prisma | 36 +- next.config.ts | 13 +- package.json | 2 +- pnpm-lock.yaml | 430 +++++++++++++++++- .../admin/teams/[teamId]/AdminTeamPage.tsx | 2 +- .../admin/users/[userId]/UserProvider.tsx | 19 +- src/app/(main)/settings/SettingsLayout.tsx | 5 + .../DateRangeSetting.tsx | 0 .../LanguageSetting.tsx | 0 .../preferences/PreferenceSettings.tsx | 39 ++ .../settings/preferences/PreferencesPage.tsx | 16 + .../{profile => preferences}/ThemeSetting.tsx | 7 +- .../TimezoneSetting.tsx | 0 src/app/(main)/settings/preferences/page.tsx | 10 + .../settings/profile/PasswordChangeButton.tsx | 17 +- .../settings/profile/ProfileSettings.tsx | 24 - src/app/(main)/settings/teams/TeamAddForm.tsx | 2 +- .../(main)/settings/teams/TeamJoinForm.tsx | 2 +- .../(main)/settings/teams/TeamsDataTable.tsx | 5 +- src/app/(main)/settings/teams/TeamsTable.tsx | 11 +- .../teams/[teamId]}/TeamDeleteForm.tsx | 0 .../teams/[teamId]}/TeamDetails.tsx | 10 +- .../teams/[teamId]}/TeamEditForm.tsx | 41 +- .../teams/[teamId]}/TeamManage.tsx | 0 .../teams/[teamId]}/TeamMemberEditButton.tsx | 18 +- .../teams/[teamId]}/TeamMemberEditForm.tsx | 8 +- .../[teamId]}/TeamMemberRemoveButton.tsx | 10 +- .../teams/[teamId]}/TeamMembersDataTable.tsx | 2 +- .../teams/[teamId]}/TeamMembersPage.tsx | 0 .../teams/[teamId]}/TeamMembersTable.tsx | 44 +- .../teams/[teamId]/TeamSettingsPage.tsx | 11 + .../[teamId]}/TeamWebsiteRemoveButton.tsx | 0 .../teams/[teamId]}/TeamWebsitesDataTable.tsx | 2 +- .../teams/[teamId]}/TeamWebsitesTable.tsx | 9 +- .../team => settings/teams/[teamId]}/page.tsx | 6 +- .../settings/websites/WebsiteAddButton.tsx | 17 +- .../settings/websites/WebsitesTable.tsx | 15 +- .../websites/[websiteId]/WebsiteEditForm.tsx | 2 +- .../websites/[websiteId]/WebsiteSettings.tsx | 10 +- .../(main)/teams/[teamId]/TeamProvider.tsx | 15 +- src/app/(main)/teams/[teamId]/layout.tsx | 7 +- .../[teamId]/settings/TeamSettingsLayout.tsx | 49 -- .../teams/[teamId]/settings/members/page.tsx | 12 - .../teams/[teamId]/settings/team/TeamPage.tsx | 6 - .../settings/websites/TeamWebsitesPage.tsx | 29 -- .../settings/websites/[websiteId]/page.tsx | 5 - .../teams/[teamId]/settings/websites/page.tsx | 12 - .../websites/[websiteId]/WebsiteProvider.tsx | 17 +- src/app/api/teams/[teamId]/users/route.ts | 9 +- src/components/common/ConfirmationForm.tsx | 11 +- src/components/hooks/queries/useTeamQuery.ts | 11 +- src/components/hooks/queries/useUserQuery.ts | 10 +- .../hooks/queries/useWebsiteQuery.ts | 9 +- src/components/input/FilterBar.tsx | 2 +- src/components/input/MenuButton.tsx | 4 +- src/components/messages.ts | 1 + 56 files changed, 706 insertions(+), 348 deletions(-) rename src/app/(main)/settings/{profile => preferences}/DateRangeSetting.tsx (100%) rename src/app/(main)/settings/{profile => preferences}/LanguageSetting.tsx (100%) create mode 100644 src/app/(main)/settings/preferences/PreferenceSettings.tsx create mode 100644 src/app/(main)/settings/preferences/PreferencesPage.tsx rename src/app/(main)/settings/{profile => preferences}/ThemeSetting.tsx (61%) rename src/app/(main)/settings/{profile => preferences}/TimezoneSetting.tsx (100%) create mode 100644 src/app/(main)/settings/preferences/page.tsx rename src/app/(main)/{teams/[teamId]/settings/team => settings/teams/[teamId]}/TeamDeleteForm.tsx (100%) rename src/app/(main)/{teams/[teamId]/settings/team => settings/teams/[teamId]}/TeamDetails.tsx (88%) rename src/app/(main)/{teams/[teamId]/settings/team => settings/teams/[teamId]}/TeamEditForm.tsx (69%) rename src/app/(main)/{teams/[teamId]/settings/team => settings/teams/[teamId]}/TeamManage.tsx (100%) rename src/app/(main)/{teams/[teamId]/settings/members => settings/teams/[teamId]}/TeamMemberEditButton.tsx (83%) rename src/app/(main)/{teams/[teamId]/settings/members => settings/teams/[teamId]}/TeamMemberEditForm.tsx (94%) rename src/app/(main)/{teams/[teamId]/settings/members => settings/teams/[teamId]}/TeamMemberRemoveButton.tsx (87%) rename src/app/(main)/{teams/[teamId]/settings/members => settings/teams/[teamId]}/TeamMembersDataTable.tsx (90%) rename src/app/(main)/{teams/[teamId]/settings/members => settings/teams/[teamId]}/TeamMembersPage.tsx (100%) rename src/app/(main)/{teams/[teamId]/settings/members => settings/teams/[teamId]}/TeamMembersTable.tsx (50%) create mode 100644 src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx rename src/app/(main)/{teams/[teamId]/settings/websites => settings/teams/[teamId]}/TeamWebsiteRemoveButton.tsx (100%) rename src/app/(main)/{teams/[teamId]/settings/websites => settings/teams/[teamId]}/TeamWebsitesDataTable.tsx (91%) rename src/app/(main)/{teams/[teamId]/settings/websites => settings/teams/[teamId]}/TeamWebsitesTable.tsx (85%) rename src/app/(main)/{teams/[teamId]/settings/team => settings/teams/[teamId]}/page.tsx (62%) delete mode 100644 src/app/(main)/teams/[teamId]/settings/TeamSettingsLayout.tsx delete mode 100644 src/app/(main)/teams/[teamId]/settings/members/page.tsx delete mode 100644 src/app/(main)/teams/[teamId]/settings/team/TeamPage.tsx delete mode 100644 src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesPage.tsx delete mode 100644 src/app/(main)/teams/[teamId]/settings/websites/[websiteId]/page.tsx delete mode 100644 src/app/(main)/teams/[teamId]/settings/websites/page.tsx diff --git a/db/postgresql/schema.prisma b/db/postgresql/schema.prisma index 39dac240..cfcbf0ef 100644 --- a/db/postgresql/schema.prisma +++ b/db/postgresql/schema.prisma @@ -1,5 +1,5 @@ generator client { - provider = "prisma-client" + provider = "prisma-client-js" previewFeatures = ["queryCompiler", "driverAdapters"] output = "../src/generated/prisma" moduleFormat = "esm" @@ -46,7 +46,7 @@ model Session { websiteEvent WebsiteEvent[] sessionData SessionData[] - revenue Revenue[] + revenue Revenue[] @@index([createdAt]) @@index([websiteId]) @@ -224,7 +224,7 @@ model Report { type String @db.VarChar(200) name String @db.VarChar(200) description String @db.VarChar(500) - parameters Json + parameters Json createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6) @@ -239,13 +239,13 @@ model Report { } model Segment { - id String @id() @unique() @map("segment_id") @db.Uuid - websiteId String @map("website_id") @db.Uuid - type String @db.VarChar(200) - name String @db.VarChar(200) - parameters Json - createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) - updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6) + id String @id() @unique() @map("segment_id") @db.Uuid + websiteId String @map("website_id") @db.Uuid + type String @db.VarChar(200) + name String @db.VarChar(200) + parameters Json + createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) + updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6) website Website @relation(fields: [websiteId], references: [id]) @@ -254,14 +254,14 @@ model Segment { } model Revenue { - id String @id() @unique() @map("revenue_id") @db.Uuid - websiteId String @map("website_id") @db.Uuid - sessionId String @map("session_id") @db.Uuid - eventId String @map("event_id") @db.Uuid - eventName String @map("event_name") @db.VarChar(50) - currency String @db.VarChar(100) - revenue Decimal? @db.Decimal(19, 4) - createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) + id String @id() @unique() @map("revenue_id") @db.Uuid + websiteId String @map("website_id") @db.Uuid + sessionId String @map("session_id") @db.Uuid + eventId String @map("event_id") @db.Uuid + eventName String @map("event_name") @db.VarChar(50) + currency String @db.VarChar(100) + revenue Decimal? @db.Decimal(19, 4) + createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) website Website @relation(fields: [websiteId], references: [id]) session Session @relation(fields: [sessionId], references: [id]) diff --git a/next.config.ts b/next.config.ts index 4e0561b7..f2c07aff 100644 --- a/next.config.ts +++ b/next.config.ts @@ -125,7 +125,7 @@ if (collectApiEndpoint) { const redirects = [ { source: '/settings', - destination: '/settings/profile', + destination: '/settings/preferences', permanent: true, }, { @@ -133,11 +133,6 @@ const redirects = [ destination: '/teams/:id/websites', permanent: true, }, - { - source: '/teams/:id/settings', - destination: '/teams/:id/settings/team', - permanent: true, - }, { source: '/admin', destination: '/admin/users', @@ -173,12 +168,6 @@ if (cloudMode && cloudUrl) { permanent: false, }); - redirects.push({ - source: '/teams/:id/settings/:path*', - destination: `${cloudUrl}/teams/:id/settings/:path*`, - permanent: false, - }); - if (disableLogin) { redirects.push({ source: '/login', diff --git a/package.json b/package.json index 02d0d23f..878176db 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "@react-spring/web": "^9.7.3", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.80.10", - "@umami/react-zen": "^0.144.0", + "@umami/react-zen": "^0.145.0", "@umami/redis-client": "^0.27.0", "bcryptjs": "^2.4.3", "chalk": "^4.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6929ce71..9443ea0c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^5.80.10 version: 5.80.10(react@19.1.0) '@umami/react-zen': - specifier: ^0.144.0 - version: 0.144.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) + specifier: ^0.145.0 + version: 0.145.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) '@umami/redis-client': specifier: ^0.27.0 version: 0.27.0 @@ -355,6 +355,45 @@ importers: specifier: ^5.5.3 version: 5.8.3 + dist: + dependencies: + '@tanstack/react-query': + specifier: ^4.33.0 + version: 4.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + classnames: + specifier: ^2.3.1 + version: 2.5.1 + colord: + specifier: ^2.9.2 + version: 2.9.3 + date-fns-tz: + specifier: ^1.1.4 + version: 1.3.8(date-fns@2.30.0) + immer: + specifier: ^9.0.12 + version: 9.0.21 + moment-timezone: + specifier: ^0.5.35 + version: 0.5.48 + next: + specifier: ^13.4.0 + version: 13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-basics: + specifier: ^0.36.0 + version: 0.36.0(next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + react-intl: + specifier: ^5.24.7 + version: 5.25.1(react@18.3.1)(typescript@4.9.5) + zustand: + specifier: ^4.3.8 + version: 4.5.7(@types/react@19.1.8)(immer@9.0.21)(react@18.3.1) + packages: '@ampproject/remapping@2.3.0': @@ -1056,6 +1095,9 @@ packages: '@formatjs/ecma402-abstract@2.3.4': resolution: {integrity: sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==} + '@formatjs/fast-memoize@1.2.1': + resolution: {integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==} + '@formatjs/fast-memoize@2.2.3': resolution: {integrity: sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==} @@ -1080,9 +1122,15 @@ packages: '@formatjs/icu-skeleton-parser@1.8.8': resolution: {integrity: sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==} + '@formatjs/intl-displaynames@5.4.3': + resolution: {integrity: sha512-4r12A3mS5dp5hnSaQCWBuBNfi9Amgx2dzhU4lTFfhSxgb5DOAiAbMpg6+7gpWZgl4ahsj3l2r/iHIjdmdXOE2Q==} + '@formatjs/intl-displaynames@6.8.5': resolution: {integrity: sha512-85b+GdAKCsleS6cqVxf/Aw/uBd+20EM0wDpgaxzHo3RIR3bxF4xCJqH/Grbzx8CXurTgDDZHPdPdwJC+May41w==} + '@formatjs/intl-listformat@6.5.3': + resolution: {integrity: sha512-ozpz515F/+3CU+HnLi5DYPsLa6JoCfBggBSSg/8nOB5LYSFW9+ZgNQJxJ8tdhKYeODT+4qVHX27EeJLoxLGLNg==} + '@formatjs/intl-listformat@7.7.5': resolution: {integrity: sha512-Wzes10SMNeYgnxYiKsda4rnHP3Q3II4XT2tZyOgnH5fWuHDtIkceuWlRQNsvrI3uiwP4hLqp2XdQTCsfkhXulg==} @@ -1106,6 +1154,14 @@ packages: typescript: optional: true + '@formatjs/intl@2.2.1': + resolution: {integrity: sha512-vgvyUOOrzqVaOFYzTf2d3+ToSkH2JpR7x/4U1RyoHQLmvEaTQvXJ7A2qm1Iy3brGNXC/+/7bUlc3lpH+h/LOJA==} + peerDependencies: + typescript: ^4.5 + peerDependenciesMeta: + typescript: + optional: true + '@formatjs/ts-transformer@2.13.0': resolution: {integrity: sha512-mu7sHXZk1NWZrQ3eUqugpSYo8x5/tXkrI4uIbFqCEC0eNgQaIcoKgVeDFgDAcgG+cEme2atAUYSFF+DFWC4org==} peerDependencies: @@ -1381,54 +1437,111 @@ packages: resolution: {integrity: sha512-SCF2UPT+mDrfO3DDeUb7eTRqHycBEx4aJ8vACm17Nyn2b2ueaLlS5u/2V42SSZF/F6LydI7R78fv3xPW7HHdWw==} engines: {node: '>=18.0.0'} + '@next/env@13.5.11': + resolution: {integrity: sha512-fbb2C7HChgM7CemdCY+y3N1n8pcTKdqtQLbC7/EQtPdLvlMUT9JX/dBYl8MMZAtYG4uVMyPFHXckb68q/NRwqg==} + '@next/env@15.3.4': resolution: {integrity: sha512-ZkdYzBseS6UjYzz6ylVKPOK+//zLWvD6Ta+vpoye8cW11AjiQjGYVibF0xuvT4L0iJfAPfZLFidaEzAOywyOAQ==} '@next/eslint-plugin-next@14.2.30': resolution: {integrity: sha512-mvVsMIutMxQ4NGZEMZ1kiBNc+la8Xmlk30bKUmCPQz2eFkmsLv54Mha8QZarMaCtSPkkFA1TMD+FIZk0l/PpzA==} + '@next/swc-darwin-arm64@13.5.9': + resolution: {integrity: sha512-pVyd8/1y1l5atQRvOaLOvfbmRwefxLhqQOzYo/M7FQ5eaRwA1+wuCn7t39VwEgDd7Aw1+AIWwd+MURXUeXhwDw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + '@next/swc-darwin-arm64@15.3.4': resolution: {integrity: sha512-z0qIYTONmPRbwHWvpyrFXJd5F9YWLCsw3Sjrzj2ZvMYy9NPQMPZ1NjOJh4ojr4oQzcGYwgJKfidzehaNa1BpEg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] + '@next/swc-darwin-x64@13.5.9': + resolution: {integrity: sha512-DwdeJqP7v8wmoyTWPbPVodTwCybBZa02xjSJ6YQFIFZFZ7dFgrieKW4Eo0GoIcOJq5+JxkQyejmI+8zwDp3pwA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + '@next/swc-darwin-x64@15.3.4': resolution: {integrity: sha512-Z0FYJM8lritw5Wq+vpHYuCIzIlEMjewG2aRkc3Hi2rcbULknYL/xqfpBL23jQnCSrDUGAo/AEv0Z+s2bff9Zkw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] + '@next/swc-linux-arm64-gnu@13.5.9': + resolution: {integrity: sha512-wdQsKsIsGSNdFojvjW3Ozrh8Q00+GqL3wTaMjDkQxVtRbAqfFBtrLPO0IuWChVUP2UeuQcHpVeUvu0YgOP00+g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + '@next/swc-linux-arm64-gnu@15.3.4': resolution: {integrity: sha512-l8ZQOCCg7adwmsnFm8m5q9eIPAHdaB2F3cxhufYtVo84pymwKuWfpYTKcUiFcutJdp9xGHC+F1Uq3xnFU1B/7g==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + '@next/swc-linux-arm64-musl@13.5.9': + resolution: {integrity: sha512-6VpS+bodQqzOeCwGxoimlRoosiWlSc0C224I7SQWJZoyJuT1ChNCo+45QQH+/GtbR/s7nhaUqmiHdzZC9TXnXA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + '@next/swc-linux-arm64-musl@15.3.4': resolution: {integrity: sha512-wFyZ7X470YJQtpKot4xCY3gpdn8lE9nTlldG07/kJYexCUpX1piX+MBfZdvulo+t1yADFVEuzFfVHfklfEx8kw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + '@next/swc-linux-x64-gnu@13.5.9': + resolution: {integrity: sha512-XxG3yj61WDd28NA8gFASIR+2viQaYZEFQagEodhI/R49gXWnYhiflTeeEmCn7Vgnxa/OfK81h1gvhUZ66lozpw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + '@next/swc-linux-x64-gnu@15.3.4': resolution: {integrity: sha512-gEbH9rv9o7I12qPyvZNVTyP/PWKqOp8clvnoYZQiX800KkqsaJZuOXkWgMa7ANCCh/oEN2ZQheh3yH8/kWPSEg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + '@next/swc-linux-x64-musl@13.5.9': + resolution: {integrity: sha512-/dnscWqfO3+U8asd+Fc6dwL2l9AZDl7eKtPNKW8mKLh4Y4wOpjJiamhe8Dx+D+Oq0GYVjuW0WwjIxYWVozt2bA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + '@next/swc-linux-x64-musl@15.3.4': resolution: {integrity: sha512-Cf8sr0ufuC/nu/yQ76AnarbSAXcwG/wj+1xFPNbyNo8ltA6kw5d5YqO8kQuwVIxk13SBdtgXrNyom3ZosHAy4A==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + '@next/swc-win32-arm64-msvc@13.5.9': + resolution: {integrity: sha512-T/iPnyurOK5a4HRUcxAlss8uzoEf5h9tkd+W2dSWAfzxv8WLKlUgbfk+DH43JY3Gc2xK5URLuXrxDZ2mGfk/jw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + '@next/swc-win32-arm64-msvc@15.3.4': resolution: {integrity: sha512-ay5+qADDN3rwRbRpEhTOreOn1OyJIXS60tg9WMYTWCy3fB6rGoyjLVxc4dR9PYjEdR2iDYsaF5h03NA+XuYPQQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] + '@next/swc-win32-ia32-msvc@13.5.9': + resolution: {integrity: sha512-BLiPKJomaPrTAb7ykjA0LPcuuNMLDVK177Z1xe0nAem33+9FIayU4k/OWrtSn9SAJW/U60+1hoey5z+KCHdRLQ==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@next/swc-win32-x64-msvc@13.5.9': + resolution: {integrity: sha512-/72/dZfjXXNY/u+n8gqZDjI6rxKMpYsgBBYNZKWOQw0BpBF7WCnPflRy3ZtvQ2+IYI3ZH2bPyj7K+6a6wNk90Q==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + '@next/swc-win32-x64-msvc@15.3.4': resolution: {integrity: sha512-4kDt31Bc9DGyYs41FTL1/kNpDeHyha2TC0j5sRRoKCyrhNcfZ/nRQkAUlF27mETwm8QyHqIjHJitfcza2Iykfg==} engines: {node: '>= 10'} @@ -2316,9 +2429,27 @@ packages: '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} + '@swc/helpers@0.5.2': + resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} + + '@tanstack/query-core@4.40.0': + resolution: {integrity: sha512-7MJTtZkCSuehMC7IxMOCGsLvHS3jHx4WjveSrGsG1Nc1UQLjaFwwkpLA2LmPfvOAxnH4mszMOBFD6LlZE+aB+Q==} + '@tanstack/query-core@5.80.10': resolution: {integrity: sha512-mUNQOtzxkjL6jLbyChZoSBP6A5gQDVRUiPvW+/zw/9ftOAz+H754zCj3D8PwnzPKyHzGkQ9JbH48ukhym9LK1Q==} + '@tanstack/react-query@4.40.1': + resolution: {integrity: sha512-mgD07S5N8e5v81CArKDWrHE4LM7HxZ9k/KLeD3+NUD9WimGZgKIqojUZf/rXkfAMYZU9p0Chzj2jOXm7xpgHHQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + '@tanstack/react-query@5.80.10': resolution: {integrity: sha512-6zM098J8sLy9oU60XAdzUlAH4wVzoMVsWUWiiE/Iz4fd67PplxeyL4sw/MPcVJJVhbwGGXCsHn9GrQt2mlAzig==} peerDependencies: @@ -2547,8 +2678,8 @@ packages: resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@umami/react-zen@0.144.0': - resolution: {integrity: sha512-RpPid2hdXAzbWKlbQWdSCwm6GZMHVs1f6VsVumq7Who/B8wxX0RVBwehHn3/ERwDw+c6ThRzlAZvOO6QLv+tQw==} + '@umami/react-zen@0.145.0': + resolution: {integrity: sha512-bbbdgWDwW0MIXfSc3JJPDOcmATZpwDsbrDdj37LEvP6rdtUgwAarnATjJa9l3133LGhhEAdYitZqwrDfHHPI5g==} '@umami/redis-client@0.27.0': resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==} @@ -2988,12 +3119,12 @@ packages: caniuse-lite@1.0.30001718: resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==} - caniuse-lite@1.0.30001722: - resolution: {integrity: sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==} - caniuse-lite@1.0.30001726: resolution: {integrity: sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==} + caniuse-lite@1.0.30001727: + resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==} + caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -3424,8 +3555,8 @@ packages: resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==} engines: {node: '>=10'} - decimal.js@10.5.0: - resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} dedent@1.6.0: resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==} @@ -4055,6 +4186,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + glob@10.3.10: resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} engines: {node: '>=16 || 14 >=14.17'} @@ -4291,6 +4425,9 @@ packages: intl-messageformat@10.7.7: resolution: {integrity: sha512-F134jIoeYMro/3I0h08D0Yt4N9o9pjddU/4IIxMMURqbAtI2wu70X8hvG1V48W49zXHXv3RKSF/po+0fDfsGjA==} + intl-messageformat@9.13.0: + resolution: {integrity: sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==} + ipaddr.js@2.2.0: resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} engines: {node: '>= 10'} @@ -5082,6 +5219,12 @@ packages: resolution: {integrity: sha512-DXO4L9W+08T+A7h5+xdT32l7IMot8z7WOH+7C1Maol571PnktQ8un7Ni4CyPFp4H+vht/FDA5/tpjRvWMFQDMw==} engines: {node: '>=10', npm: '>=6'} + moment-timezone@0.5.48: + resolution: {integrity: sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==} + + moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -5101,6 +5244,28 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + next-basics@0.36.0: + resolution: {integrity: sha512-Nwou8pCjFuoD/ZxUw9iKC7hhZeWbo/ng0ze74yck3W89MNc/CepwCDziflAHY5XcmIVNmpXOCu9OfmzTdVRPWQ==} + peerDependencies: + next: ^13.4.0 + react: ^18.2.0 + react-dom: ^18.2.0 + + next@13.5.11: + resolution: {integrity: sha512-WUPJ6WbAX9tdC86kGTu92qkrRdgRqVrY++nwM+shmWQwmyxt4zhZfR59moXSI4N8GDYCBY3lIAqhzjDd4rTC8Q==} + engines: {node: '>=16.14.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + sass: + optional: true + next@15.3.4: resolution: {integrity: sha512-mHKd50C+mCjam/gcnwqL1T1vPx/XQNFlXqFIVdgQdVAFY9iIQtY0IfaVflEYzKiqjeA7B0cYYMaCrmAYFjs4rA==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} @@ -5936,6 +6101,11 @@ packages: react: ^18.2.0 react-dom: ^18.2.0 + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + peerDependencies: + react: ^18.3.1 + react-dom@19.1.0: resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} peerDependencies: @@ -5952,8 +6122,8 @@ packages: peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-hook-form@7.58.1: - resolution: {integrity: sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==} + react-hook-form@7.60.0: + resolution: {integrity: sha512-SBrYOvMbDB7cV8ZfNpaiLcgjH/a1c7aK0lK+aNigpf4xWLO8q+o4tcvVurv3c4EOyzn/3dCsYt4GKD42VvJ/+A==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -5963,6 +6133,15 @@ packages: peerDependencies: react: '*' + react-intl@5.25.1: + resolution: {integrity: sha512-pkjdQDvpJROoXLMltkP/5mZb0/XqrqLoPGKUCfbdkP8m6U9xbK40K51Wu+a4aQqTEvEK5lHBk0fWzUV72SJ3Hg==} + peerDependencies: + react: ^16.3.0 || 17 || 18 + typescript: ^4.5 + peerDependenciesMeta: + typescript: + optional: true + react-intl@6.8.9: resolution: {integrity: sha512-TUfj5E7lyUDvz/GtovC9OMh441kBr08rtIbgh3p0R8iF3hVY+V2W9Am7rb8BpJ/29BH1utJOqOOhmvEVh3GfZg==} peerDependencies: @@ -6018,6 +6197,10 @@ packages: react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + react@19.1.0: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} @@ -6204,6 +6387,9 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} @@ -6463,6 +6649,19 @@ packages: style-search@0.1.0: resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} + styled-jsx@5.1.1: + resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + styled-jsx@5.1.6: resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} engines: {node: '>= 12.0.0'} @@ -6839,6 +7038,10 @@ packages: walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + watchpack@2.4.0: + resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} + engines: {node: '>=10.13.0'} + web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -6954,6 +7157,21 @@ packages: zod@3.25.67: resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} + zustand@4.5.7: + resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==} + engines: {node: '>=12.7.0'} + peerDependencies: + '@types/react': '>=16.8' + immer: '>=9.0.6' + react: '>=16.8' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + zustand@5.0.5: resolution: {integrity: sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==} engines: {node: '>=12.20.0'} @@ -7624,7 +7842,11 @@ snapshots: dependencies: '@formatjs/fast-memoize': 2.2.7 '@formatjs/intl-localematcher': 0.6.1 - decimal.js: 10.5.0 + decimal.js: 10.6.0 + tslib: 2.8.1 + + '@formatjs/fast-memoize@1.2.1': + dependencies: tslib: 2.8.1 '@formatjs/fast-memoize@2.2.3': @@ -7668,12 +7890,24 @@ snapshots: '@formatjs/ecma402-abstract': 2.2.4 tslib: 2.8.1 + '@formatjs/intl-displaynames@5.4.3': + dependencies: + '@formatjs/ecma402-abstract': 1.11.4 + '@formatjs/intl-localematcher': 0.2.25 + tslib: 2.8.1 + '@formatjs/intl-displaynames@6.8.5': dependencies: '@formatjs/ecma402-abstract': 2.2.4 '@formatjs/intl-localematcher': 0.5.8 tslib: 2.8.1 + '@formatjs/intl-listformat@6.5.3': + dependencies: + '@formatjs/ecma402-abstract': 1.11.4 + '@formatjs/intl-localematcher': 0.2.25 + tslib: 2.8.1 + '@formatjs/intl-listformat@7.7.5': dependencies: '@formatjs/ecma402-abstract': 2.2.4 @@ -7709,6 +7943,18 @@ snapshots: optionalDependencies: typescript: 5.8.3 + '@formatjs/intl@2.2.1(typescript@4.9.5)': + dependencies: + '@formatjs/ecma402-abstract': 1.11.4 + '@formatjs/fast-memoize': 1.2.1 + '@formatjs/icu-messageformat-parser': 2.1.0 + '@formatjs/intl-displaynames': 5.4.3 + '@formatjs/intl-listformat': 6.5.3 + intl-messageformat: 9.13.0 + tslib: 2.8.1 + optionalDependencies: + typescript: 4.9.5 + '@formatjs/ts-transformer@2.13.0(ts-jest@29.4.0(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.5)(jest-util@29.7.0)(jest@29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@types/node@22.15.32)(typescript@5.8.3)))(typescript@5.8.3))': dependencies: intl-messageformat-parser: 6.1.2 @@ -8070,33 +8316,62 @@ snapshots: '@netlify/plugin-nextjs@5.11.3': {} + '@next/env@13.5.11': {} + '@next/env@15.3.4': {} '@next/eslint-plugin-next@14.2.30': dependencies: glob: 10.3.10 + '@next/swc-darwin-arm64@13.5.9': + optional: true + '@next/swc-darwin-arm64@15.3.4': optional: true + '@next/swc-darwin-x64@13.5.9': + optional: true + '@next/swc-darwin-x64@15.3.4': optional: true + '@next/swc-linux-arm64-gnu@13.5.9': + optional: true + '@next/swc-linux-arm64-gnu@15.3.4': optional: true + '@next/swc-linux-arm64-musl@13.5.9': + optional: true + '@next/swc-linux-arm64-musl@15.3.4': optional: true + '@next/swc-linux-x64-gnu@13.5.9': + optional: true + '@next/swc-linux-x64-gnu@15.3.4': optional: true + '@next/swc-linux-x64-musl@13.5.9': + optional: true + '@next/swc-linux-x64-musl@15.3.4': optional: true + '@next/swc-win32-arm64-msvc@13.5.9': + optional: true + '@next/swc-win32-arm64-msvc@15.3.4': optional: true + '@next/swc-win32-ia32-msvc@13.5.9': + optional: true + + '@next/swc-win32-x64-msvc@13.5.9': + optional: true + '@next/swc-win32-x64-msvc@15.3.4': optional: true @@ -9453,8 +9728,22 @@ snapshots: dependencies: tslib: 2.8.1 + '@swc/helpers@0.5.2': + dependencies: + tslib: 2.8.1 + + '@tanstack/query-core@4.40.0': {} + '@tanstack/query-core@5.80.10': {} + '@tanstack/react-query@4.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@tanstack/query-core': 4.40.0 + react: 18.3.1 + use-sync-external-store: 1.5.0(react@18.3.1) + optionalDependencies: + react-dom: 18.3.1(react@18.3.1) + '@tanstack/react-query@5.80.10(react@19.1.0)': dependencies: '@tanstack/query-core': 5.80.10 @@ -9736,7 +10025,7 @@ snapshots: '@typescript-eslint/types': 8.34.1 eslint-visitor-keys: 4.2.1 - '@umami/react-zen@0.144.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': + '@umami/react-zen@0.145.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': dependencies: '@fontsource/jetbrains-mono': 5.2.6 '@internationalized/date': 3.8.2 @@ -9750,7 +10039,7 @@ snapshots: react: 19.1.0 react-aria-components: 1.9.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-dom: 19.1.0(react@19.1.0) - react-hook-form: 7.58.1(react@19.1.0) + react-hook-form: 7.60.0(react@19.1.0) react-icons: 5.5.0(react@19.1.0) thenby: 1.3.4 zustand: 5.0.5(@types/react@19.1.8)(immer@9.0.21)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)) @@ -10245,16 +10534,16 @@ snapshots: caniuse-api@3.0.0: dependencies: browserslist: 4.24.5 - caniuse-lite: 1.0.30001722 + caniuse-lite: 1.0.30001727 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 caniuse-lite@1.0.30001718: {} - caniuse-lite@1.0.30001722: {} - caniuse-lite@1.0.30001726: {} + caniuse-lite@1.0.30001727: {} + caseless@0.12.0: {} chalk@2.4.2: @@ -10726,7 +11015,7 @@ snapshots: decamelize@5.0.1: {} - decimal.js@10.5.0: {} + decimal.js@10.6.0: {} dedent@1.6.0: {} @@ -11559,6 +11848,8 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regexp@0.4.1: {} + glob@10.3.10: dependencies: foreground-child: 3.3.1 @@ -11788,6 +12079,13 @@ snapshots: '@formatjs/icu-messageformat-parser': 2.9.4 tslib: 2.8.1 + intl-messageformat@9.13.0: + dependencies: + '@formatjs/ecma402-abstract': 1.11.4 + '@formatjs/fast-memoize': 1.2.1 + '@formatjs/icu-messageformat-parser': 2.1.0 + tslib: 2.8.1 + ipaddr.js@2.2.0: {} is-array-buffer@3.0.5: @@ -12764,6 +13062,12 @@ snapshots: mmdb-lib@2.2.1: {} + moment-timezone@0.5.48: + dependencies: + moment: 2.30.1 + + moment@2.30.1: {} + ms@2.1.2: {} ms@2.1.3: {} @@ -12774,6 +13078,40 @@ snapshots: natural-compare@1.4.0: {} + next-basics@0.36.0(next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + bcryptjs: 2.4.3 + jsonwebtoken: 9.0.2 + next: 13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + pure-rand: 6.1.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@next/env': 13.5.11 + '@swc/helpers': 0.5.2 + busboy: 1.6.0 + caniuse-lite: 1.0.30001727 + postcss: 8.4.31 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-jsx: 5.1.1(@babel/core@7.27.1)(react@18.3.1) + watchpack: 2.4.0 + optionalDependencies: + '@next/swc-darwin-arm64': 13.5.9 + '@next/swc-darwin-x64': 13.5.9 + '@next/swc-linux-arm64-gnu': 13.5.9 + '@next/swc-linux-arm64-musl': 13.5.9 + '@next/swc-linux-x64-gnu': 13.5.9 + '@next/swc-linux-x64-musl': 13.5.9 + '@next/swc-win32-arm64-msvc': 13.5.9 + '@next/swc-win32-ia32-msvc': 13.5.9 + '@next/swc-win32-x64-msvc': 13.5.9 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + next@15.3.4(@babel/core@7.27.1)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@next/env': 15.3.4 @@ -13659,6 +13997,12 @@ snapshots: react-hook-form: 7.56.4(react@19.1.0) react-window: 1.8.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react-dom@18.3.1(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + react-dom@19.1.0(react@19.1.0): dependencies: react: 19.1.0 @@ -13673,7 +14017,7 @@ snapshots: dependencies: react: 19.1.0 - react-hook-form@7.58.1(react@19.1.0): + react-hook-form@7.60.0(react@19.1.0): dependencies: react: 19.1.0 @@ -13681,6 +14025,22 @@ snapshots: dependencies: react: 19.1.0 + react-intl@5.25.1(react@18.3.1)(typescript@4.9.5): + dependencies: + '@formatjs/ecma402-abstract': 1.11.4 + '@formatjs/icu-messageformat-parser': 2.1.0 + '@formatjs/intl': 2.2.1(typescript@4.9.5) + '@formatjs/intl-displaynames': 5.4.3 + '@formatjs/intl-listformat': 6.5.3 + '@types/hoist-non-react-statics': 3.3.6 + '@types/react': 18.3.23 + hoist-non-react-statics: 3.3.2 + intl-messageformat: 9.13.0 + react: 18.3.1 + tslib: 2.8.1 + optionalDependencies: + typescript: 4.9.5 + react-intl@6.8.9(react@19.1.0)(typescript@5.8.3): dependencies: '@formatjs/ecma402-abstract': 2.2.4 @@ -13763,6 +14123,10 @@ snapshots: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + react@19.1.0: {} read-babelrc-up@1.1.0: @@ -13996,6 +14360,10 @@ snapshots: safer-buffer@2.1.2: {} + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + scheduler@0.26.0: {} schema-utils@2.7.1: @@ -14314,6 +14682,13 @@ snapshots: style-search@0.1.0: {} + styled-jsx@5.1.1(@babel/core@7.27.1)(react@18.3.1): + dependencies: + client-only: 0.0.1 + react: 18.3.1 + optionalDependencies: + '@babel/core': 7.27.1 + styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.1.0): dependencies: client-only: 0.0.1 @@ -14695,6 +15070,10 @@ snapshots: dependencies: react: 19.1.0 + use-sync-external-store@1.5.0(react@18.3.1): + dependencies: + react: 18.3.1 + use-sync-external-store@1.5.0(react@19.1.0): dependencies: react: 19.1.0 @@ -14740,6 +15119,11 @@ snapshots: dependencies: makeerror: 1.0.12 + watchpack@2.4.0: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + web-streams-polyfill@3.3.3: {} which-boxed-primitive@1.1.1: @@ -14881,6 +15265,14 @@ snapshots: zod@3.25.67: {} + zustand@4.5.7(@types/react@19.1.8)(immer@9.0.21)(react@18.3.1): + dependencies: + use-sync-external-store: 1.5.0(react@18.3.1) + optionalDependencies: + '@types/react': 19.1.8 + immer: 9.0.21 + react: 18.3.1 + zustand@5.0.5(@types/react@19.1.8)(immer@9.0.21)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)): optionalDependencies: '@types/react': 19.1.8 diff --git a/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx b/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx index 31134388..7f680a91 100644 --- a/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx +++ b/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx @@ -1,5 +1,5 @@ 'use client'; -import { TeamDetails } from '@/app/(main)/teams/[teamId]/settings/team/TeamDetails'; +import { TeamDetails } from '@/app/(main)/settings/teams/[teamId]/TeamDetails'; import { TeamProvider } from '@/app/(main)/teams/[teamId]/TeamProvider'; export function AdminTeamPage({ teamId }: { teamId: string }) { diff --git a/src/app/(main)/admin/users/[userId]/UserProvider.tsx b/src/app/(main)/admin/users/[userId]/UserProvider.tsx index 22b1b955..39df7cfc 100644 --- a/src/app/(main)/admin/users/[userId]/UserProvider.tsx +++ b/src/app/(main)/admin/users/[userId]/UserProvider.tsx @@ -1,22 +1,19 @@ -import { createContext, ReactNode, useEffect } from 'react'; +import { createContext, ReactNode } from 'react'; import { Loading } from '@umami/react-zen'; -import { useModified, useUserQuery } from '@/components/hooks'; +import { useUserQuery } from '@/components/hooks'; export const UserContext = createContext(null); export function UserProvider({ userId, children }: { userId: string; children: ReactNode }) { - const { modified } = useModified(`user:${userId}`); - const { data: user, isFetching, isLoading, refetch } = useUserQuery(userId); - - useEffect(() => { - if (modified) { - refetch(); - } - }, [modified]); + const { data: user, isFetching, isLoading } = useUserQuery(userId); if (isFetching && isLoading) { return ; } - return {children}; + if (!user) { + return null; + } + + return {children}; } diff --git a/src/app/(main)/settings/SettingsLayout.tsx b/src/app/(main)/settings/SettingsLayout.tsx index 4110820e..cfc901d4 100644 --- a/src/app/(main)/settings/SettingsLayout.tsx +++ b/src/app/(main)/settings/SettingsLayout.tsx @@ -13,6 +13,11 @@ export function SettingsLayout({ children }: { children: ReactNode }) { const { pathname } = useNavigation(); const items = [ + { + id: 'preferences', + label: formatMessage(labels.preferences), + url: '/settings/preferences', + }, { id: 'profile', label: formatMessage(labels.profile), diff --git a/src/app/(main)/settings/profile/DateRangeSetting.tsx b/src/app/(main)/settings/preferences/DateRangeSetting.tsx similarity index 100% rename from src/app/(main)/settings/profile/DateRangeSetting.tsx rename to src/app/(main)/settings/preferences/DateRangeSetting.tsx diff --git a/src/app/(main)/settings/profile/LanguageSetting.tsx b/src/app/(main)/settings/preferences/LanguageSetting.tsx similarity index 100% rename from src/app/(main)/settings/profile/LanguageSetting.tsx rename to src/app/(main)/settings/preferences/LanguageSetting.tsx diff --git a/src/app/(main)/settings/preferences/PreferenceSettings.tsx b/src/app/(main)/settings/preferences/PreferenceSettings.tsx new file mode 100644 index 00000000..c956ebad --- /dev/null +++ b/src/app/(main)/settings/preferences/PreferenceSettings.tsx @@ -0,0 +1,39 @@ +import { Column, Label } from '@umami/react-zen'; +import { useLoginQuery, useMessages } from '@/components/hooks'; +import { TimezoneSetting } from './TimezoneSetting'; +import { DateRangeSetting } from './DateRangeSetting'; +import { LanguageSetting } from './LanguageSetting'; +import { ThemeSetting } from './ThemeSetting'; + +export function PreferenceSettings() { + const { user } = useLoginQuery(); + const { formatMessage, labels } = useMessages(); + + if (!user) { + return null; + } + + return ( + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/app/(main)/settings/preferences/PreferencesPage.tsx b/src/app/(main)/settings/preferences/PreferencesPage.tsx new file mode 100644 index 00000000..62d7f882 --- /dev/null +++ b/src/app/(main)/settings/preferences/PreferencesPage.tsx @@ -0,0 +1,16 @@ +'use client'; +import { Column } from '@umami/react-zen'; +import { useMessages } from '@/components/hooks'; +import { SectionHeader } from '@/components/common/SectionHeader'; +import { PreferenceSettings } from './PreferenceSettings'; + +export function PreferencesPage() { + const { formatMessage, labels } = useMessages(); + + return ( + + + + + ); +} diff --git a/src/app/(main)/settings/profile/ThemeSetting.tsx b/src/app/(main)/settings/preferences/ThemeSetting.tsx similarity index 61% rename from src/app/(main)/settings/profile/ThemeSetting.tsx rename to src/app/(main)/settings/preferences/ThemeSetting.tsx index bc9b90b6..d0c4fb28 100644 --- a/src/app/(main)/settings/profile/ThemeSetting.tsx +++ b/src/app/(main)/settings/preferences/ThemeSetting.tsx @@ -6,15 +6,12 @@ export function ThemeSetting() { return ( - - - {({ close }) => } + {({ close }) => ( + + + + )} diff --git a/src/app/(main)/settings/profile/ProfileSettings.tsx b/src/app/(main)/settings/profile/ProfileSettings.tsx index 40471c75..72ae7d91 100644 --- a/src/app/(main)/settings/profile/ProfileSettings.tsx +++ b/src/app/(main)/settings/profile/ProfileSettings.tsx @@ -1,10 +1,6 @@ import { Row, Column, Label } from '@umami/react-zen'; import { useLoginQuery, useMessages } from '@/components/hooks'; import { ROLES } from '@/lib/constants'; -import { TimezoneSetting } from './TimezoneSetting'; -import { DateRangeSetting } from './DateRangeSetting'; -import { LanguageSetting } from './LanguageSetting'; -import { ThemeSetting } from './ThemeSetting'; import { PasswordChangeButton } from './PasswordChangeButton'; export function ProfileSettings() { @@ -52,26 +48,6 @@ export function ProfileSettings() { )} - - - - - - - - - - - - - - - - - - - - ); } diff --git a/src/app/(main)/settings/teams/TeamAddForm.tsx b/src/app/(main)/settings/teams/TeamAddForm.tsx index 80fd0c62..2c1746f7 100644 --- a/src/app/(main)/settings/teams/TeamAddForm.tsx +++ b/src/app/(main)/settings/teams/TeamAddForm.tsx @@ -25,7 +25,7 @@ export function TeamAddForm({ onSave, onClose }: { onSave: () => void; onClose: }; return ( -
+ diff --git a/src/app/(main)/settings/teams/TeamJoinForm.tsx b/src/app/(main)/settings/teams/TeamJoinForm.tsx index 91ec5aaf..047b28ad 100644 --- a/src/app/(main)/settings/teams/TeamJoinForm.tsx +++ b/src/app/(main)/settings/teams/TeamJoinForm.tsx @@ -25,7 +25,7 @@ export function TeamJoinForm({ onSave, onClose }: { onSave: () => void; onClose: }; return ( - + children}> + {({ data }) => { return ; }} diff --git a/src/app/(main)/settings/teams/TeamsTable.tsx b/src/app/(main)/settings/teams/TeamsTable.tsx index 39870ec8..bfe6b332 100644 --- a/src/app/(main)/settings/teams/TeamsTable.tsx +++ b/src/app/(main)/settings/teams/TeamsTable.tsx @@ -1,8 +1,9 @@ import { DataColumn, DataTable, Icon, MenuItem, Text, Row } from '@umami/react-zen'; import { useMessages } from '@/components/hooks'; -import { Arrow, Edit } from '@/components/icons'; +import { Eye, Edit } from '@/components/icons'; import { ROLES } from '@/lib/constants'; import { MenuButton } from '@/components/input/MenuButton'; +import Link from 'next/link'; export function TeamsTable({ data = [], @@ -16,7 +17,9 @@ export function TeamsTable({ return ( - + + {(row: any) => {row.name}} + {(row: any) => row.teamUser.find(({ role }) => role === ROLES.teamOwner)?.user?.username} @@ -36,12 +39,12 @@ export function TeamsTable({ - + {formatMessage(labels.view)} - + diff --git a/src/app/(main)/teams/[teamId]/settings/team/TeamDeleteForm.tsx b/src/app/(main)/settings/teams/[teamId]/TeamDeleteForm.tsx similarity index 100% rename from src/app/(main)/teams/[teamId]/settings/team/TeamDeleteForm.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamDeleteForm.tsx diff --git a/src/app/(main)/teams/[teamId]/settings/team/TeamDetails.tsx b/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx similarity index 88% rename from src/app/(main)/teams/[teamId]/settings/team/TeamDetails.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx index d7782956..635aba55 100644 --- a/src/app/(main)/teams/[teamId]/settings/team/TeamDetails.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx @@ -8,8 +8,8 @@ import { Users } from '@/components/icons'; import { TeamLeaveButton } from '@/app/(main)/settings/teams/TeamLeaveButton'; import { TeamManage } from './TeamManage'; import { TeamEditForm } from './TeamEditForm'; -import { TeamWebsitesDataTable } from '@/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesDataTable'; -import { TeamMembersDataTable } from '@/app/(main)/teams/[teamId]/settings/members/TeamMembersDataTable'; +import { TeamWebsitesDataTable } from './TeamWebsitesDataTable'; +import { TeamMembersDataTable } from './TeamMembersDataTable'; export function TeamDetails({ teamId }: { teamId: string }) { const team = useContext(TeamContext); @@ -22,10 +22,12 @@ export function TeamDetails({ teamId }: { teamId: string }) { user.role !== ROLES.viewOnly; const canEdit = - !!team?.teamUser?.find( + user.isAdmin || + (!!team?.teamUser?.find( ({ userId, role }) => (role === ROLES.teamOwner || role === ROLES.teamManager) && userId === user.id, - ) && user.role !== ROLES.viewOnly; + ) && + user.role !== ROLES.viewOnly); return ( diff --git a/src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx b/src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx similarity index 69% rename from src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx index fad603bb..4fde3fd3 100644 --- a/src/app/(main)/teams/[teamId]/settings/team/TeamEditForm.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx @@ -6,7 +6,6 @@ import { TextField, Button, useToast, - Text, } from '@umami/react-zen'; import { getRandomChars } from '@/lib/crypto'; import { useContext } from 'react'; @@ -15,28 +14,38 @@ import { TeamContext } from '@/app/(main)/teams/[teamId]/TeamProvider'; const generateId = () => `team_${getRandomChars(16)}`; -export function TeamEditForm({ teamId, allowEdit }: { teamId: string; allowEdit?: boolean }) { +export function TeamEditForm({ + teamId, + allowEdit, + onSave, +}: { + teamId: string; + allowEdit?: boolean; + onSave?: () => void; +}) { const team = useContext(TeamContext); const { formatMessage, labels, messages } = useMessages(); const { post, useMutation } = useApi(); + const { toast } = useToast(); + const { touch } = useModified(); + const { mutate, error } = useMutation({ mutationFn: (data: any) => post(`/teams/${teamId}`, data), }); - const { toast } = useToast(); - const { touch } = useModified(); - const cloudMode = !!process.env.cloudMode; const handleSubmit = async (data: any) => { mutate(data, { onSuccess: async () => { touch('teams'); + touch(`teams:${teamId}`); toast(formatMessage(messages.saved)); + onSave?.(); }, }); }; return ( - + {({ setValue }) => { return ( <> @@ -48,22 +57,16 @@ export function TeamEditForm({ teamId, allowEdit }: { teamId: string; allowEdit? label={formatMessage(labels.name)} rules={{ required: formatMessage(labels.required) }} > - {allowEdit ? : {team?.name}} + + + + - {!cloudMode && allowEdit && ( - - - - )} {allowEdit && ( - {allowEdit && ( - - )} + {formatMessage(labels.save)} )} diff --git a/src/app/(main)/teams/[teamId]/settings/team/TeamManage.tsx b/src/app/(main)/settings/teams/[teamId]/TeamManage.tsx similarity index 100% rename from src/app/(main)/teams/[teamId]/settings/team/TeamManage.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamManage.tsx diff --git a/src/app/(main)/teams/[teamId]/settings/members/TeamMemberEditButton.tsx b/src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx similarity index 83% rename from src/app/(main)/teams/[teamId]/settings/members/TeamMemberEditButton.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx index 62279bdd..308e3439 100644 --- a/src/app/(main)/teams/[teamId]/settings/members/TeamMemberEditButton.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx @@ -1,14 +1,5 @@ import { useMessages, useModified } from '@/components/hooks'; -import { - Row, - Pressable, - Icon, - Modal, - DialogTrigger, - Dialog, - Text, - useToast, -} from '@umami/react-zen'; +import { Row, Button, Icon, Modal, DialogTrigger, Dialog, useToast } from '@umami/react-zen'; import { TeamMemberEditForm } from './TeamMemberEditForm'; import { Edit } from '@/components/icons'; @@ -28,21 +19,20 @@ export function TeamMemberEditButton({ const { touch } = useModified(); const handleSave = () => { - toast(formatMessage(messages.saved)); touch('teams:members'); + toast(formatMessage(messages.saved)); onSave?.(); }; return ( - + {({ close }) => ( diff --git a/src/app/(main)/teams/[teamId]/settings/members/TeamMemberEditForm.tsx b/src/app/(main)/settings/teams/[teamId]/TeamMemberEditForm.tsx similarity index 94% rename from src/app/(main)/teams/[teamId]/settings/members/TeamMemberEditForm.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamMemberEditForm.tsx index c5501221..72618f83 100644 --- a/src/app/(main)/teams/[teamId]/settings/members/TeamMemberEditForm.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamMemberEditForm.tsx @@ -39,7 +39,7 @@ export function TeamMemberEditForm({ }; return ( - + - - {formatMessage(labels.save)} - + + {formatMessage(labels.save)} + ); diff --git a/src/app/(main)/teams/[teamId]/settings/members/TeamMemberRemoveButton.tsx b/src/app/(main)/settings/teams/[teamId]/TeamMemberRemoveButton.tsx similarity index 87% rename from src/app/(main)/teams/[teamId]/settings/members/TeamMemberRemoveButton.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamMemberRemoveButton.tsx index 508ddc6e..ae25c8be 100644 --- a/src/app/(main)/teams/[teamId]/settings/members/TeamMemberRemoveButton.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamMemberRemoveButton.tsx @@ -1,8 +1,8 @@ import { ConfirmationForm } from '@/components/common/ConfirmationForm'; import { useApi, useMessages, useModified } from '@/components/hooks'; import { messages } from '@/components/messages'; -import { Close } from '@/components/icons'; -import { Button, Icon, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen'; +import { Trash } from '@/components/icons'; +import { Button, Icon, Modal, DialogTrigger, Dialog } from '@umami/react-zen'; export function TeamMemberRemoveButton({ teamId, @@ -35,11 +35,10 @@ export function TeamMemberRemoveButton({ return ( - @@ -53,6 +52,7 @@ export function TeamMemberRemoveButton({ onConfirm={handleConfirm.bind(null, close)} onClose={close} buttonLabel={formatMessage(labels.remove)} + buttonVariant="danger" /> )} diff --git a/src/app/(main)/teams/[teamId]/settings/members/TeamMembersDataTable.tsx b/src/app/(main)/settings/teams/[teamId]/TeamMembersDataTable.tsx similarity index 90% rename from src/app/(main)/teams/[teamId]/settings/members/TeamMembersDataTable.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamMembersDataTable.tsx index 25ccbab3..d5f99310 100644 --- a/src/app/(main)/teams/[teamId]/settings/members/TeamMembersDataTable.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamMembersDataTable.tsx @@ -12,7 +12,7 @@ export function TeamMembersDataTable({ const queryResult = useTeamMembersQuery(teamId); return ( - + {({ data }) => } ); diff --git a/src/app/(main)/teams/[teamId]/settings/members/TeamMembersPage.tsx b/src/app/(main)/settings/teams/[teamId]/TeamMembersPage.tsx similarity index 100% rename from src/app/(main)/teams/[teamId]/settings/members/TeamMembersPage.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamMembersPage.tsx diff --git a/src/app/(main)/teams/[teamId]/settings/members/TeamMembersTable.tsx b/src/app/(main)/settings/teams/[teamId]/TeamMembersTable.tsx similarity index 50% rename from src/app/(main)/teams/[teamId]/settings/members/TeamMembersTable.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamMembersTable.tsx index 34f3ac3b..f84f58a9 100644 --- a/src/app/(main)/teams/[teamId]/settings/members/TeamMembersTable.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamMembersTable.tsx @@ -1,9 +1,8 @@ -import { DataColumn, DataTable, MenuItem } from '@umami/react-zen'; -import { useMessages, useLoginQuery } from '@/components/hooks'; +import { DataColumn, DataTable, Row } from '@umami/react-zen'; +import { useMessages } from '@/components/hooks'; import { ROLES } from '@/lib/constants'; import { TeamMemberRemoveButton } from './TeamMemberRemoveButton'; import { TeamMemberEditButton } from './TeamMemberEditButton'; -import { MenuButton } from '@/components/input/MenuButton'; export function TeamMembersTable({ data = [], @@ -15,7 +14,6 @@ export function TeamMembersTable({ allowEdit: boolean; }) { const { formatMessage, labels } = useMessages(); - const { user } = useLoginQuery(); const roles = { [ROLES.teamOwner]: formatMessage(labels.teamOwner), @@ -32,28 +30,22 @@ export function TeamMembersTable({ {(row: any) => roles[row?.role]} - - {(row: any) => { - return ( - allowEdit && - row?.role !== ROLES.teamOwner && - user?.id !== row?.user?.id && ( - - - - - - - - - ) - ); - }} - + {allowEdit && ( + + {(row: any) => { + return ( + + + + + ); + }} + + )} ); } diff --git a/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx b/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx new file mode 100644 index 00000000..88ec9b40 --- /dev/null +++ b/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx @@ -0,0 +1,11 @@ +'use client'; +import { TeamProvider } from '@/app/(main)/teams/[teamId]/TeamProvider'; +import { TeamDetails } from '@/app/(main)/settings/teams/[teamId]/TeamDetails'; + +export function TeamSettingsPage({ teamId }: { teamId: string }) { + return ( + + + + ); +} diff --git a/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsiteRemoveButton.tsx b/src/app/(main)/settings/teams/[teamId]/TeamWebsiteRemoveButton.tsx similarity index 100% rename from src/app/(main)/teams/[teamId]/settings/websites/TeamWebsiteRemoveButton.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamWebsiteRemoveButton.tsx diff --git a/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesDataTable.tsx b/src/app/(main)/settings/teams/[teamId]/TeamWebsitesDataTable.tsx similarity index 91% rename from src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesDataTable.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamWebsitesDataTable.tsx index 1cb65eac..6a2e4f45 100644 --- a/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesDataTable.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamWebsitesDataTable.tsx @@ -12,7 +12,7 @@ export function TeamWebsitesDataTable({ const queryResult = useTeamWebsitesQuery(teamId); return ( - + {({ data }) => } ); diff --git a/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesTable.tsx b/src/app/(main)/settings/teams/[teamId]/TeamWebsitesTable.tsx similarity index 85% rename from src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesTable.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamWebsitesTable.tsx index 59926335..f04f1f85 100644 --- a/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesTable.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamWebsitesTable.tsx @@ -1,7 +1,8 @@ import { DataColumn, DataTable, Icon, MenuItem, Text, Row } from '@umami/react-zen'; import { useLoginQuery, useMessages } from '@/components/hooks'; -import { Arrow, Edit } from '@/components/icons'; +import { Eye, Edit } from '@/components/icons'; import { MenuButton } from '@/components/input/MenuButton'; +import Link from 'next/link'; export function TeamWebsitesTable({ teamId, @@ -17,7 +18,9 @@ export function TeamWebsitesTable({ return ( - + + {(row: any) => {row.name}} + {(row: any) => row?.createUser?.username} @@ -31,7 +34,7 @@ export function TeamWebsitesTable({ - + {formatMessage(labels.view)} diff --git a/src/app/(main)/teams/[teamId]/settings/team/page.tsx b/src/app/(main)/settings/teams/[teamId]/page.tsx similarity index 62% rename from src/app/(main)/teams/[teamId]/settings/team/page.tsx rename to src/app/(main)/settings/teams/[teamId]/page.tsx index 4767b1c4..5a9aaacb 100644 --- a/src/app/(main)/teams/[teamId]/settings/team/page.tsx +++ b/src/app/(main)/settings/teams/[teamId]/page.tsx @@ -1,12 +1,12 @@ import { Metadata } from 'next'; -import { TeamPage } from './TeamPage'; +import { TeamSettingsPage } from './TeamSettingsPage'; export default async function ({ params }: { params: Promise<{ teamId: string }> }) { const { teamId } = await params; - return ; + return ; } export const metadata: Metadata = { - title: 'Teams Details', + title: 'Teams', }; diff --git a/src/app/(main)/settings/websites/WebsiteAddButton.tsx b/src/app/(main)/settings/websites/WebsiteAddButton.tsx index 8996c5b9..74852a14 100644 --- a/src/app/(main)/settings/websites/WebsiteAddButton.tsx +++ b/src/app/(main)/settings/websites/WebsiteAddButton.tsx @@ -1,5 +1,14 @@ import { useMessages, useModified } from '@/components/hooks'; -import { Button, Icon, Modal, Dialog, DialogTrigger, Text, useToast } from '@umami/react-zen'; +import { + Button, + Icon, + Modal, + Dialog, + DialogTrigger, + Text, + Column, + useToast, +} from '@umami/react-zen'; import { Plus } from '@/components/icons'; import { WebsiteAddForm } from './WebsiteAddForm'; @@ -24,7 +33,11 @@ export function WebsiteAddButton({ teamId, onSave }: { teamId: string; onSave?: - {({ close }) => } + {({ close }) => ( + + + + )} diff --git a/src/app/(main)/settings/websites/WebsitesTable.tsx b/src/app/(main)/settings/websites/WebsitesTable.tsx index f4cc7ebf..2d285c75 100644 --- a/src/app/(main)/settings/websites/WebsitesTable.tsx +++ b/src/app/(main)/settings/websites/WebsitesTable.tsx @@ -6,7 +6,7 @@ import { Eye, SquarePen } from '@/components/icons'; import Link from 'next/link'; export interface WebsitesTableProps { - data: any[]; + data: Record[]; showActions?: boolean; allowEdit?: boolean; allowView?: boolean; @@ -22,7 +22,8 @@ export function WebsitesTable({ children, }: WebsitesTableProps) { const { formatMessage, labels } = useMessages(); - const { renderUrl } = useNavigation(); + const { renderUrl, pathname } = useNavigation(); + const isSettings = pathname.includes('/settings'); if (!data?.length) { return children; @@ -31,7 +32,11 @@ export function WebsitesTable({ return ( - {(row: any) => {row.name}} + {(row: any) => ( + + {row.name} + + )} {showActions && ( @@ -41,7 +46,7 @@ export function WebsitesTable({ return ( - {allowEdit && ( + {allowView && ( @@ -51,7 +56,7 @@ export function WebsitesTable({ )} - {allowView && ( + {allowEdit && ( diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteEditForm.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteEditForm.tsx index 8e9c6d7c..94197748 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteEditForm.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteEditForm.tsx @@ -33,7 +33,7 @@ export function WebsiteEditForm({ websiteId, onSave }: { websiteId: string; onSa }; return ( -
+ diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteSettings.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteSettings.tsx index a7d19745..e36cf0ae 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteSettings.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteSettings.tsx @@ -2,7 +2,7 @@ import { useContext } from 'react'; import { Icon, Tabs, TabList, Tab, TabPanel, Text } from '@umami/react-zen'; import { WebsiteContext } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; import { useMessages } from '@/components/hooks'; -import { Globe, Arrow } from '@/components/icons'; +import { Globe, Eye } from '@/components/icons'; import { SectionHeader } from '@/components/common/SectionHeader'; import { WebsiteShareForm } from './WebsiteShareForm'; import { WebsiteTrackingCode } from './WebsiteTrackingCode'; @@ -25,7 +25,7 @@ export function WebsiteSettings({ }> - + {formatMessage(labels.view)} @@ -35,7 +35,7 @@ export function WebsiteSettings({ {formatMessage(labels.details)} {formatMessage(labels.trackingCode)} {formatMessage(labels.shareUrl)} - {formatMessage(labels.data)} + {formatMessage(labels.manage)} @@ -44,9 +44,9 @@ export function WebsiteSettings({ - + - + diff --git a/src/app/(main)/teams/[teamId]/TeamProvider.tsx b/src/app/(main)/teams/[teamId]/TeamProvider.tsx index 178b73d6..a0161ff0 100644 --- a/src/app/(main)/teams/[teamId]/TeamProvider.tsx +++ b/src/app/(main)/teams/[teamId]/TeamProvider.tsx @@ -1,25 +1,18 @@ 'use client'; -import { createContext, ReactNode, useEffect } from 'react'; -import { useTeamQuery, useModified } from '@/components/hooks'; +import { createContext, ReactNode } from 'react'; +import { useTeamQuery } from '@/components/hooks'; import { Loading } from '@umami/react-zen'; export const TeamContext = createContext(null); export function TeamProvider({ teamId, children }: { teamId?: string; children: ReactNode }) { - const { modified } = useModified(`teams`); - const { data: team, isLoading, isFetching, refetch } = useTeamQuery(teamId); - - useEffect(() => { - if (teamId && modified) { - refetch(); - } - }, [teamId, modified]); + const { data: team, isLoading, isFetching } = useTeamQuery(teamId); if (isFetching && isLoading) { return ; } - if (teamId && !team) { + if (!team) { return null; } diff --git a/src/app/(main)/teams/[teamId]/layout.tsx b/src/app/(main)/teams/[teamId]/layout.tsx index 11814eca..1dfdd243 100644 --- a/src/app/(main)/teams/[teamId]/layout.tsx +++ b/src/app/(main)/teams/[teamId]/layout.tsx @@ -1,6 +1,5 @@ import { TeamProvider } from './TeamProvider'; import { Metadata } from 'next'; -import { TeamSettingsLayout } from './settings/TeamSettingsLayout'; export default async function ({ children, @@ -11,11 +10,7 @@ export default async function ({ }) { const { teamId } = await params; - return ( - - {children} - - ); + return {children}; } export const metadata: Metadata = { diff --git a/src/app/(main)/teams/[teamId]/settings/TeamSettingsLayout.tsx b/src/app/(main)/teams/[teamId]/settings/TeamSettingsLayout.tsx deleted file mode 100644 index 6e4c33cc..00000000 --- a/src/app/(main)/teams/[teamId]/settings/TeamSettingsLayout.tsx +++ /dev/null @@ -1,49 +0,0 @@ -'use client'; -import { ReactNode } from 'react'; -import { useMessages, useNavigation } from '@/components/hooks'; -import { Grid, Column } from '@umami/react-zen'; -import { SideMenu } from '@/components/common/SideMenu'; -import { Panel } from '@/components/common/Panel'; -import { PageHeader } from '@/components/common/PageHeader'; -import { PageBody } from '@/components/common/PageBody'; - -export function TeamSettingsLayout({ children }: { children: ReactNode }) { - const { formatMessage, labels } = useMessages(); - const { pathname, teamId } = useNavigation(); - - const items = [ - { - id: 'team', - label: formatMessage(labels.team), - url: `/teams/${teamId}/settings/team`, - }, - { - id: 'websites', - label: formatMessage(labels.websites), - url: `/teams/${teamId}/settings/websites`, - }, - { - id: 'members', - label: formatMessage(labels.members), - url: `/teams/${teamId}/settings/members`, - }, - ].filter(n => n); - - const value = items.find(({ url }) => pathname.includes(url))?.id; - - return ( - - - - - - - - - {children} - - - - - ); -} diff --git a/src/app/(main)/teams/[teamId]/settings/members/page.tsx b/src/app/(main)/teams/[teamId]/settings/members/page.tsx deleted file mode 100644 index f6957843..00000000 --- a/src/app/(main)/teams/[teamId]/settings/members/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Metadata } from 'next'; -import { TeamMembersPage } from './TeamMembersPage'; - -export default async function ({ params }: { params: Promise<{ teamId: string }> }) { - const { teamId } = await params; - - return ; -} - -export const metadata: Metadata = { - title: 'Team Members', -}; diff --git a/src/app/(main)/teams/[teamId]/settings/team/TeamPage.tsx b/src/app/(main)/teams/[teamId]/settings/team/TeamPage.tsx deleted file mode 100644 index a35e6d72..00000000 --- a/src/app/(main)/teams/[teamId]/settings/team/TeamPage.tsx +++ /dev/null @@ -1,6 +0,0 @@ -'use client'; -import { TeamDetails } from './TeamDetails'; - -export function TeamPage({ teamId }: { teamId: string }) { - return ; -} diff --git a/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesPage.tsx b/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesPage.tsx deleted file mode 100644 index d878b941..00000000 --- a/src/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesPage.tsx +++ /dev/null @@ -1,29 +0,0 @@ -'use client'; -import { TeamContext } from '@/app/(main)/teams/[teamId]/TeamProvider'; -import { WebsiteAddButton } from '@/app/(main)/settings/websites/WebsiteAddButton'; -import { useLoginQuery, useMessages } from '@/components/hooks'; -import { SectionHeader } from '@/components/common/SectionHeader'; -import { TeamWebsitesDataTable } from './TeamWebsitesDataTable'; -import { ROLES } from '@/lib/constants'; -import { useContext } from 'react'; -import { Column } from '@umami/react-zen'; - -export function TeamWebsitesPage({ teamId }: { teamId: string }) { - const team = useContext(TeamContext); - const { formatMessage, labels } = useMessages(); - const { user } = useLoginQuery(); - - const canEdit = - !!team?.teamUser?.find( - ({ userId, role }) => userId === user.id && role !== ROLES.teamViewOnly, - ) && user.role !== ROLES.viewOnly; - - return ( - - - {canEdit && } - - - - ); -} diff --git a/src/app/(main)/teams/[teamId]/settings/websites/[websiteId]/page.tsx b/src/app/(main)/teams/[teamId]/settings/websites/[websiteId]/page.tsx deleted file mode 100644 index a18f8a2e..00000000 --- a/src/app/(main)/teams/[teamId]/settings/websites/[websiteId]/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import Page from '@/app/(main)/settings/websites/[websiteId]/page'; - -export default function ({ params }) { - return ; -} diff --git a/src/app/(main)/teams/[teamId]/settings/websites/page.tsx b/src/app/(main)/teams/[teamId]/settings/websites/page.tsx deleted file mode 100644 index e34c35d5..00000000 --- a/src/app/(main)/teams/[teamId]/settings/websites/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { TeamWebsitesPage } from './TeamWebsitesPage'; -import { Metadata } from 'next'; - -export default async function ({ params }: { params: Promise<{ teamId: string }> }) { - const { teamId } = await params; - - return ; -} - -export const metadata: Metadata = { - title: 'Teams Websites', -}; diff --git a/src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx b/src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx index ea0a8bbe..16aa55fb 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx @@ -1,6 +1,6 @@ 'use client'; -import { createContext, ReactNode, useEffect } from 'react'; -import { useModified, useWebsiteQuery } from '@/components/hooks'; +import { createContext, ReactNode } from 'react'; +import { useWebsiteQuery } from '@/components/hooks'; import { Loading } from '@umami/react-zen'; import { Website } from '@/generated/prisma/client'; @@ -13,18 +13,15 @@ export function WebsiteProvider({ websiteId: string; children: ReactNode; }) { - const { modified } = useModified(`website:${websiteId}`); - const { data: website, isFetching, isLoading, refetch } = useWebsiteQuery(websiteId); - - useEffect(() => { - if (modified) { - refetch(); - } - }, [modified]); + const { data: website, isFetching, isLoading } = useWebsiteQuery(websiteId); if (isFetching && isLoading) { return ; } + if (!website) { + return null; + } + return {children}; } diff --git a/src/app/api/teams/[teamId]/users/route.ts b/src/app/api/teams/[teamId]/users/route.ts index 376351ea..cf1b4b9b 100644 --- a/src/app/api/teams/[teamId]/users/route.ts +++ b/src/app/api/teams/[teamId]/users/route.ts @@ -1,13 +1,14 @@ import { z } from 'zod'; import { unauthorized, json, badRequest } from '@/lib/response'; import { canAddUserToTeam, canViewTeam } from '@/lib/auth'; -import { parseRequest } from '@/lib/request'; -import { pagingParams, teamRoleParam } from '@/lib/schema'; +import { getQueryFilters, parseRequest } from '@/lib/request'; +import { pagingParams, teamRoleParam, searchParams } from '@/lib/schema'; import { createTeamUser, getTeamUser, getTeamUsers } from '@/queries'; export async function GET(request: Request, { params }: { params: Promise<{ teamId: string }> }) { const schema = z.object({ ...pagingParams, + ...searchParams, }); const { auth, query, error } = await parseRequest(request, schema); @@ -22,6 +23,8 @@ export async function GET(request: Request, { params }: { params: Promise<{ team return unauthorized('You must be the owner of this team.'); } + const filters = getQueryFilters(query); + const users = await getTeamUsers( { where: { @@ -39,7 +42,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ team }, }, }, - query, + filters, ); return json(users); diff --git a/src/components/common/ConfirmationForm.tsx b/src/components/common/ConfirmationForm.tsx index 39861f61..38c8634d 100644 --- a/src/components/common/ConfirmationForm.tsx +++ b/src/components/common/ConfirmationForm.tsx @@ -25,10 +25,17 @@ export function ConfirmationForm({ return ( - {message} + + {message} + - + {buttonLabel || formatMessage(labels.ok)} diff --git a/src/components/hooks/queries/useTeamQuery.ts b/src/components/hooks/queries/useTeamQuery.ts index 563e16d5..f471172b 100644 --- a/src/components/hooks/queries/useTeamQuery.ts +++ b/src/components/hooks/queries/useTeamQuery.ts @@ -1,10 +1,17 @@ import { useApi } from '../useApi'; +import { useModified } from '@/components/hooks'; +import { keepPreviousData } from '@tanstack/react-query'; +import { ReactQueryOptions } from '@/lib/types'; -export function useTeamQuery(teamId: string) { +export function useTeamQuery(teamId: string, options?: ReactQueryOptions) { const { get, useQuery } = useApi(); + const { modified } = useModified(`teams:${teamId}`); + return useQuery({ - queryKey: ['teams', teamId], + queryKey: ['teams', { teamId, modified }], queryFn: () => get(`/teams/${teamId}`), enabled: !!teamId, + placeholderData: keepPreviousData, + ...options, }); } diff --git a/src/components/hooks/queries/useUserQuery.ts b/src/components/hooks/queries/useUserQuery.ts index baaa084b..6fb476d5 100644 --- a/src/components/hooks/queries/useUserQuery.ts +++ b/src/components/hooks/queries/useUserQuery.ts @@ -1,11 +1,17 @@ import { useApi } from '../useApi'; +import { useModified } from '@/components/hooks'; +import { keepPreviousData } from '@tanstack/react-query'; +import { ReactQueryOptions } from '@/lib/types'; -export function useUserQuery(userId: string, options?: Record) { +export function useUserQuery(userId: string, options?: ReactQueryOptions) { const { get, useQuery } = useApi(); + const { modified } = useModified(`user:${userId}`); + return useQuery({ - queryKey: ['users', userId], + queryKey: ['users', { userId, modified }], queryFn: () => get(`/users/${userId}`), enabled: !!userId, + placeholderData: keepPreviousData, ...options, }); } diff --git a/src/components/hooks/queries/useWebsiteQuery.ts b/src/components/hooks/queries/useWebsiteQuery.ts index 55fe4eba..8faaaa26 100644 --- a/src/components/hooks/queries/useWebsiteQuery.ts +++ b/src/components/hooks/queries/useWebsiteQuery.ts @@ -1,12 +1,17 @@ import { useApi } from '../useApi'; +import { useModified } from '@/components/hooks'; +import { keepPreviousData } from '@tanstack/react-query'; +import { ReactQueryOptions } from '@/lib/types'; -export function useWebsiteQuery(websiteId: string, options?: Record) { +export function useWebsiteQuery(websiteId: string, options?: ReactQueryOptions) { const { get, useQuery } = useApi(); + const { modified } = useModified(`website:${websiteId}`); return useQuery({ - queryKey: ['website', { websiteId }], + queryKey: ['website', { websiteId, modified }], queryFn: () => get(`/websites/${websiteId}`), enabled: !!websiteId, + placeholderData: keepPreviousData, ...options, }); } diff --git a/src/components/input/FilterBar.tsx b/src/components/input/FilterBar.tsx index f4f86b65..224b4c77 100644 --- a/src/components/input/FilterBar.tsx +++ b/src/components/input/FilterBar.tsx @@ -62,7 +62,7 @@ export function FilterBar() { })} - - + {({ close }) => } diff --git a/src/app/(main)/admin/users/UserDeleteButton.tsx b/src/app/(main)/admin/users/UserDeleteButton.tsx index d6d470c1..f3789884 100644 --- a/src/app/(main)/admin/users/UserDeleteButton.tsx +++ b/src/app/(main)/admin/users/UserDeleteButton.tsx @@ -24,7 +24,7 @@ export function UserDeleteButton({ {formatMessage(labels.delete)} - + {({ close }) => ( )} diff --git a/src/app/(main)/admin/users/[userId]/UserEditForm.tsx b/src/app/(main)/admin/users/[userId]/UserEditForm.tsx index 3938a92d..193d2e47 100644 --- a/src/app/(main)/admin/users/[userId]/UserEditForm.tsx +++ b/src/app/(main)/admin/users/[userId]/UserEditForm.tsx @@ -45,7 +45,7 @@ export function UserEditForm({ userId, onSave }: { userId: string; onSave?: () = }; return ( - + diff --git a/src/app/(main)/admin/users/[userId]/UserSettings.tsx b/src/app/(main)/admin/users/[userId]/UserSettings.tsx index 8a775f0b..8369c3f4 100644 --- a/src/app/(main)/admin/users/[userId]/UserSettings.tsx +++ b/src/app/(main)/admin/users/[userId]/UserSettings.tsx @@ -19,7 +19,7 @@ export function UserSettings({ userId }: { userId: string }) { {formatMessage(labels.details)} {formatMessage(labels.websites)} - + diff --git a/src/app/(main)/boards/BoardAddButton.tsx b/src/app/(main)/boards/BoardAddButton.tsx index 40172060..7c98ed16 100644 --- a/src/app/(main)/boards/BoardAddButton.tsx +++ b/src/app/(main)/boards/BoardAddButton.tsx @@ -23,7 +23,7 @@ export function BoardAddButton() { {formatMessage(labels.addBoard)} - + {({ close }) => } diff --git a/src/app/(main)/settings/profile/PasswordChangeButton.tsx b/src/app/(main)/settings/profile/PasswordChangeButton.tsx index a4d65f93..e438ae31 100644 --- a/src/app/(main)/settings/profile/PasswordChangeButton.tsx +++ b/src/app/(main)/settings/profile/PasswordChangeButton.tsx @@ -29,7 +29,7 @@ export function PasswordChangeButton() { {formatMessage(labels.changePassword)} - + {({ close }) => ( diff --git a/src/app/(main)/settings/teams/TeamAddForm.tsx b/src/app/(main)/settings/teams/TeamAddForm.tsx index 2c1746f7..80fd0c62 100644 --- a/src/app/(main)/settings/teams/TeamAddForm.tsx +++ b/src/app/(main)/settings/teams/TeamAddForm.tsx @@ -25,7 +25,7 @@ export function TeamAddForm({ onSave, onClose }: { onSave: () => void; onClose: }; return ( - + diff --git a/src/app/(main)/settings/teams/TeamJoinForm.tsx b/src/app/(main)/settings/teams/TeamJoinForm.tsx index 047b28ad..91ec5aaf 100644 --- a/src/app/(main)/settings/teams/TeamJoinForm.tsx +++ b/src/app/(main)/settings/teams/TeamJoinForm.tsx @@ -25,7 +25,7 @@ export function TeamJoinForm({ onSave, onClose }: { onSave: () => void; onClose: }; return ( - + {formatMessage(labels.leave)} - + {({ close }) => ( void }) { {formatMessage(labels.createTeam)} - + {({ close }) => } diff --git a/src/app/(main)/settings/teams/TeamsJoinButton.tsx b/src/app/(main)/settings/teams/TeamsJoinButton.tsx index 42ae5c3a..7e1e24e7 100644 --- a/src/app/(main)/settings/teams/TeamsJoinButton.tsx +++ b/src/app/(main)/settings/teams/TeamsJoinButton.tsx @@ -22,7 +22,7 @@ export function TeamsJoinButton() { {formatMessage(labels.joinTeam)} - + {({ close }) => } diff --git a/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx b/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx index 635aba55..e4d7e514 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx @@ -41,7 +41,7 @@ export function TeamDetails({ teamId }: { teamId: string }) { {formatMessage(labels.websites)} {isTeamOwner && {formatMessage(labels.manage)}} - + diff --git a/src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx b/src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx index 4fde3fd3..9c053ac8 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx @@ -45,7 +45,7 @@ export function TeamEditForm({ }; return ( - + {({ setValue }) => { return ( <> diff --git a/src/app/(main)/settings/teams/[teamId]/TeamManage.tsx b/src/app/(main)/settings/teams/[teamId]/TeamManage.tsx index 120fe5c9..6c0fe46e 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamManage.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamManage.tsx @@ -22,7 +22,7 @@ export function TeamManage({ teamId }: { teamId: string }) { - + {({ close }) => } diff --git a/src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx b/src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx index 308e3439..c8056146 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx @@ -34,7 +34,7 @@ export function TeamMemberEditButton({ - + {({ close }) => ( + - + {({ close }) => ( {userName}, + target: userName, })} isLoading={isPending} error={error} diff --git a/src/app/(main)/settings/websites/WebsiteAddButton.tsx b/src/app/(main)/settings/websites/WebsiteAddButton.tsx index 74852a14..4db62c44 100644 --- a/src/app/(main)/settings/websites/WebsiteAddButton.tsx +++ b/src/app/(main)/settings/websites/WebsiteAddButton.tsx @@ -32,7 +32,7 @@ export function WebsiteAddButton({ teamId, onSave }: { teamId: string; onSave?: {formatMessage(labels.addWebsite)} - + {({ close }) => ( diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx index d304562f..fce82f50 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx @@ -56,7 +56,7 @@ export function WebsiteData({ websiteId, onSave }: { websiteId: string; onSave?: - + {({ close }) => ( )} @@ -72,7 +72,7 @@ export function WebsiteData({ websiteId, onSave }: { websiteId: string; onSave?: - + {({ close }) => ( )} @@ -90,7 +90,7 @@ export function WebsiteData({ websiteId, onSave }: { websiteId: string; onSave?: {formatMessage(labels.delete)} - + {({ close }) => ( )} diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteEditForm.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteEditForm.tsx index 94197748..cb7cb0d1 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteEditForm.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteEditForm.tsx @@ -33,7 +33,7 @@ export function WebsiteEditForm({ websiteId, onSave }: { websiteId: string; onSa }; return ( - + diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteSettings.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteSettings.tsx index e36cf0ae..0825c663 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteSettings.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteSettings.tsx @@ -37,13 +37,13 @@ export function WebsiteSettings({ {formatMessage(labels.shareUrl)} {formatMessage(labels.manage)} - + - + diff --git a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx index 4c247dcd..9c4dd08c 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx @@ -42,7 +42,7 @@ const ShareButton = ({ websiteId, shareId }) => { Share - + {({ close }) => { return ; }} diff --git a/src/app/(main)/websites/[websiteId]/reports/breakdown/BreakdownPage.tsx b/src/app/(main)/websites/[websiteId]/reports/breakdown/BreakdownPage.tsx index ed6a503d..993b6aab 100644 --- a/src/app/(main)/websites/[websiteId]/reports/breakdown/BreakdownPage.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/breakdown/BreakdownPage.tsx @@ -43,7 +43,7 @@ const FieldsButton = ({ value, onChange }) => { Fields - + {({ close }) => ( )} diff --git a/src/components/common/ConfirmationForm.tsx b/src/components/common/ConfirmationForm.tsx index 38c8634d..c84b176a 100644 --- a/src/components/common/ConfirmationForm.tsx +++ b/src/components/common/ConfirmationForm.tsx @@ -25,9 +25,7 @@ export function ConfirmationForm({ return ( - - {message} - + {message} ; + } + return ( {allowSearch && (data || search) && ( From 2dbe80b7ca7a4160997b369fde6825a3baeb5390 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 12 Jul 2025 13:56:45 -0700 Subject: [PATCH 124/399] Updated db build. --- db/postgresql/schema.prisma | 3 +-- package.json | 2 +- scripts/check-db.js | 2 +- src/index.ts | 26 ++++++++++++-------------- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/db/postgresql/schema.prisma b/db/postgresql/schema.prisma index cfcbf0ef..b258d2b6 100644 --- a/db/postgresql/schema.prisma +++ b/db/postgresql/schema.prisma @@ -1,8 +1,7 @@ generator client { - provider = "prisma-client-js" + provider = "prisma-client" previewFeatures = ["queryCompiler", "driverAdapters"] output = "../src/generated/prisma" - moduleFormat = "esm" } datasource db { diff --git a/package.json b/package.json index 878176db..ce8475b0 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "build-components": "rollup -c rollup.components.config.js", "build-tracker": "rollup -c rollup.tracker.config.js", "build-prisma-client": "node scripts/build-prisma-client.js", - "build-db": "npm-run-all copy-db-files build-db-client build-prisma-client", + "build-db": "npm-run-all copy-db-files build-db-client", "build-lang": "npm-run-all format-lang compile-lang download-country-names download-language-names clean-lang", "build-geo": "node scripts/build-geo.js", "build-db-schema": "prisma db pull", diff --git a/scripts/check-db.js b/scripts/check-db.js index 839c5571..f93135ab 100644 --- a/scripts/check-db.js +++ b/scripts/check-db.js @@ -4,7 +4,7 @@ import 'dotenv/config'; import { execSync } from 'node:child_process'; import chalk from 'chalk'; import semver from 'semver'; -import { PrismaClient } from '../dist/generated/prisma/client.js'; +import { PrismaClient } from '@prisma/client'; import { PrismaPg } from '@prisma/adapter-pg'; if (process.env.SKIP_DB_CHECK) { diff --git a/src/index.ts b/src/index.ts index b3d2de2a..243d5ea7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,19 +1,17 @@ export * from '@/components/hooks'; -export * from '@/app/(main)/teams/[teamId]/settings/members/TeamMemberEditButton'; -export * from '@/app/(main)/teams/[teamId]/settings/members/TeamMemberEditForm'; -export * from '@/app/(main)/teams/[teamId]/settings/members/TeamMemberRemoveButton'; -export * from '@/app/(main)/teams/[teamId]/settings/members/TeamMembersDataTable'; -export * from '@/app/(main)/teams/[teamId]/settings/members/TeamMembersTable'; - -export * from '@/app/(main)/teams/[teamId]/settings/team/TeamDeleteForm'; -export * from '@/app/(main)/teams/[teamId]/settings/team/TeamDetails'; -export * from '@/app/(main)/teams/[teamId]/settings/team/TeamEditForm'; -export * from '@/app/(main)/teams/[teamId]/settings/team/TeamManage'; - -export * from '@/app/(main)/teams/[teamId]/settings/websites/TeamWebsiteRemoveButton'; -export * from '@/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesDataTable'; -export * from '@/app/(main)/teams/[teamId]/settings/websites/TeamWebsitesTable'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamMemberEditButton'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamMemberEditForm'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamMemberRemoveButton'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamMembersDataTable'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamMembersTable'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamDeleteForm'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamDetails'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamEditForm'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamManage'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamWebsiteRemoveButton'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamWebsitesDataTable'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamWebsitesTable'; export * from '@/app/(main)/settings/teams/TeamAddForm'; export * from '@/app/(main)/settings/teams/TeamJoinForm'; From 2a8c707519f341105af4a971cde018e4e2519715 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 12 Jul 2025 14:08:15 -0700 Subject: [PATCH 125/399] Updated db build again. --- package.json | 2 +- scripts/check-db.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ce8475b0..878176db 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "build-components": "rollup -c rollup.components.config.js", "build-tracker": "rollup -c rollup.tracker.config.js", "build-prisma-client": "node scripts/build-prisma-client.js", - "build-db": "npm-run-all copy-db-files build-db-client", + "build-db": "npm-run-all copy-db-files build-db-client build-prisma-client", "build-lang": "npm-run-all format-lang compile-lang download-country-names download-language-names clean-lang", "build-geo": "node scripts/build-geo.js", "build-db-schema": "prisma db pull", diff --git a/scripts/check-db.js b/scripts/check-db.js index f93135ab..839c5571 100644 --- a/scripts/check-db.js +++ b/scripts/check-db.js @@ -4,7 +4,7 @@ import 'dotenv/config'; import { execSync } from 'node:child_process'; import chalk from 'chalk'; import semver from 'semver'; -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from '../dist/generated/prisma/client.js'; import { PrismaPg } from '@prisma/adapter-pg'; if (process.env.SKIP_DB_CHECK) { From b255b4738f7ed0e63a42299dcc6dbfeebe2cf324 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 12 Jul 2025 14:12:59 -0700 Subject: [PATCH 126/399] Fixed imports. --- src/components/input/SettingsButton.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/input/SettingsButton.tsx b/src/components/input/SettingsButton.tsx index 39c1f057..ae7b1eb0 100644 --- a/src/components/input/SettingsButton.tsx +++ b/src/components/input/SettingsButton.tsx @@ -1,6 +1,6 @@ import { Button, Icon, DialogTrigger, Popover, Column, Label } from '@umami/react-zen'; -import { TimezoneSetting } from '@/app/(main)/settings/profile/TimezoneSetting'; -import { DateRangeSetting } from '@/app/(main)/settings/profile/DateRangeSetting'; +import { TimezoneSetting } from '@/app/(main)/settings/preferences/TimezoneSetting'; +import { DateRangeSetting } from '@/app/(main)/settings/preferences/DateRangeSetting'; import { Gear } from '@/components/icons'; import { useMessages } from '@/components/hooks'; From 514ea70d2ac1d4627c7b934d122e48f71e890083 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 12 Jul 2025 14:24:51 -0700 Subject: [PATCH 127/399] Removed queryCompiler. --- db/postgresql/schema.prisma | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/postgresql/schema.prisma b/db/postgresql/schema.prisma index b258d2b6..be78f4d0 100644 --- a/db/postgresql/schema.prisma +++ b/db/postgresql/schema.prisma @@ -1,6 +1,6 @@ generator client { provider = "prisma-client" - previewFeatures = ["queryCompiler", "driverAdapters"] + previewFeatures = ["driverAdapters"] output = "../src/generated/prisma" } From 77131158f755a93d2c91d3d592cfefe65975dda5 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 12 Jul 2025 14:41:10 -0700 Subject: [PATCH 128/399] Updated build config for Vercel. --- next.config.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/next.config.ts b/next.config.ts index f2c07aff..e52df6ab 100644 --- a/next.config.ts +++ b/next.config.ts @@ -199,6 +199,18 @@ export default { typescript: { ignoreBuildErrors: true, }, + functions: { + 'app/api/**/*.js': { + maxDuration: 30, + }, + }, + outputFileTracing: { + include: [ + 'src/generated/prisma/**/*', + 'node_modules/@prisma/client/**/*', + 'node_modules/.prisma/client/**/*', + ], + }, async headers() { return headers; }, From bf6c9395c6d4ce599b992c868f60f7d88e339f15 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 12 Jul 2025 15:18:01 -0700 Subject: [PATCH 129/399] Revert Prisma build. --- db/postgresql/schema.prisma | 3 +-- package.json | 2 +- scripts/check-db.js | 2 +- src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx | 2 +- src/lib/auth.ts | 2 +- src/lib/load.ts | 2 +- src/lib/prisma.ts | 2 +- src/queries/prisma/report.ts | 2 +- src/queries/prisma/team.ts | 2 +- src/queries/prisma/teamUser.ts | 2 +- src/queries/prisma/user.ts | 2 +- src/queries/prisma/website.ts | 2 +- src/queries/sql/events/getEventData.ts | 2 +- src/queries/sql/sessions/createSession.ts | 2 +- 14 files changed, 14 insertions(+), 15 deletions(-) diff --git a/db/postgresql/schema.prisma b/db/postgresql/schema.prisma index be78f4d0..3f5008b7 100644 --- a/db/postgresql/schema.prisma +++ b/db/postgresql/schema.prisma @@ -1,7 +1,6 @@ generator client { - provider = "prisma-client" + provider = "prisma-client-js" previewFeatures = ["driverAdapters"] - output = "../src/generated/prisma" } datasource db { diff --git a/package.json b/package.json index 878176db..ce8475b0 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "build-components": "rollup -c rollup.components.config.js", "build-tracker": "rollup -c rollup.tracker.config.js", "build-prisma-client": "node scripts/build-prisma-client.js", - "build-db": "npm-run-all copy-db-files build-db-client build-prisma-client", + "build-db": "npm-run-all copy-db-files build-db-client", "build-lang": "npm-run-all format-lang compile-lang download-country-names download-language-names clean-lang", "build-geo": "node scripts/build-geo.js", "build-db-schema": "prisma db pull", diff --git a/scripts/check-db.js b/scripts/check-db.js index 839c5571..f93135ab 100644 --- a/scripts/check-db.js +++ b/scripts/check-db.js @@ -4,7 +4,7 @@ import 'dotenv/config'; import { execSync } from 'node:child_process'; import chalk from 'chalk'; import semver from 'semver'; -import { PrismaClient } from '../dist/generated/prisma/client.js'; +import { PrismaClient } from '@prisma/client'; import { PrismaPg } from '@prisma/adapter-pg'; if (process.env.SKIP_DB_CHECK) { diff --git a/src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx b/src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx index 16aa55fb..e5cba326 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx @@ -2,7 +2,7 @@ import { createContext, ReactNode } from 'react'; import { useWebsiteQuery } from '@/components/hooks'; import { Loading } from '@umami/react-zen'; -import { Website } from '@/generated/prisma/client'; +import { Website } from '@prisma/client'; export const WebsiteContext = createContext(null); diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 7811efd0..b30c254e 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -1,5 +1,5 @@ import bcrypt from 'bcryptjs'; -import { Report } from '@/generated/prisma/client'; +import { Report } from '@prisma/client'; import redis from '@/lib/redis'; import debug from 'debug'; import { PERMISSIONS, ROLE_PERMISSIONS, ROLES, SHARE_TOKEN_HEADER } from '@/lib/constants'; diff --git a/src/lib/load.ts b/src/lib/load.ts index badda3a6..d9aa23c2 100644 --- a/src/lib/load.ts +++ b/src/lib/load.ts @@ -1,4 +1,4 @@ -import { Website, Session } from '@/generated/prisma/client'; +import { Website, Session } from '@prisma/client'; import redis from '@/lib/redis'; import { getWebsiteSession, getWebsite } from '@/queries'; diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index cc184b6a..813c844b 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -1,5 +1,5 @@ import debug from 'debug'; -import { PrismaClient } from '@/generated/prisma/client'; +import { PrismaClient } from '@prisma/client'; import { PrismaPg } from '@prisma/adapter-pg'; import { readReplicas } from '@prisma/extension-read-replicas'; import { MYSQL, POSTGRESQL, getDatabaseType } from '@/lib/db'; diff --git a/src/queries/prisma/report.ts b/src/queries/prisma/report.ts index 322193d2..f89a9da0 100644 --- a/src/queries/prisma/report.ts +++ b/src/queries/prisma/report.ts @@ -1,4 +1,4 @@ -import { Prisma, Report } from '@/generated/prisma/client'; +import { Prisma, Report } from '@prisma/client'; import prisma from '@/lib/prisma'; import { PageResult, QueryFilters } from '@/lib/types'; import ReportFindManyArgs = Prisma.ReportFindManyArgs; diff --git a/src/queries/prisma/team.ts b/src/queries/prisma/team.ts index 076ff012..edc082ba 100644 --- a/src/queries/prisma/team.ts +++ b/src/queries/prisma/team.ts @@ -1,4 +1,4 @@ -import { Prisma, Team } from '@/generated/prisma/client'; +import { Prisma, Team } from '@prisma/client'; import { ROLES } from '@/lib/constants'; import { uuid } from '@/lib/crypto'; import prisma from '@/lib/prisma'; diff --git a/src/queries/prisma/teamUser.ts b/src/queries/prisma/teamUser.ts index 45024b41..1b88243c 100644 --- a/src/queries/prisma/teamUser.ts +++ b/src/queries/prisma/teamUser.ts @@ -1,4 +1,4 @@ -import { Prisma, TeamUser } from '@/generated/prisma/client'; +import { Prisma, TeamUser } from '@prisma/client'; import { uuid } from '@/lib/crypto'; import prisma from '@/lib/prisma'; import { PageResult, QueryFilters } from '@/lib/types'; diff --git a/src/queries/prisma/user.ts b/src/queries/prisma/user.ts index 48640ec7..24753d83 100644 --- a/src/queries/prisma/user.ts +++ b/src/queries/prisma/user.ts @@ -1,4 +1,4 @@ -import { Prisma, User } from '@/generated/prisma/client'; +import { Prisma, User } from '@prisma/client'; import { ROLES } from '@/lib/constants'; import prisma from '@/lib/prisma'; import { PageResult, Role, QueryFilters } from '@/lib/types'; diff --git a/src/queries/prisma/website.ts b/src/queries/prisma/website.ts index a959769b..0a7492ad 100644 --- a/src/queries/prisma/website.ts +++ b/src/queries/prisma/website.ts @@ -1,4 +1,4 @@ -import { Prisma, Website } from '@/generated/prisma/client'; +import { Prisma, Website } from '@prisma/client'; import redis from '@/lib/redis'; import prisma from '@/lib/prisma'; import { PageResult, QueryFilters } from '@/lib/types'; diff --git a/src/queries/sql/events/getEventData.ts b/src/queries/sql/events/getEventData.ts index 1167f014..4b2b197d 100644 --- a/src/queries/sql/events/getEventData.ts +++ b/src/queries/sql/events/getEventData.ts @@ -1,4 +1,4 @@ -import { EventData } from '@/generated/prisma/client'; +import { EventData } from '@prisma/client'; import prisma from '@/lib/prisma'; import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; diff --git a/src/queries/sql/sessions/createSession.ts b/src/queries/sql/sessions/createSession.ts index 395f9f4c..d2794c8f 100644 --- a/src/queries/sql/sessions/createSession.ts +++ b/src/queries/sql/sessions/createSession.ts @@ -1,4 +1,4 @@ -import { Prisma } from '@/generated/prisma/client'; +import { Prisma } from '@prisma/client'; import prisma from '@/lib/prisma'; export async function createSession( From 8c26e310f79cab1a0a6f368b39c7384589ec6ae6 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sun, 13 Jul 2025 00:37:43 -0700 Subject: [PATCH 130/399] Fixed editing and navigation issues. --- next.config.ts | 12 --------- src/app/(main)/App.tsx | 4 +-- src/app/(main)/{MenuBar.tsx => TopNav.tsx} | 16 ++++-------- src/app/(main)/admin/users/UserDeleteForm.tsx | 5 ++-- .../admin/websites/AdminWebsitesTable.tsx | 13 +++++++--- src/app/(main)/settings/SettingsLayout.tsx | 2 +- .../settings/teams/[teamId]/TeamDetails.tsx | 9 ++++--- .../teams/[teamId]/TeamMembersTable.tsx | 4 +++ .../settings/websites/WebsitesTable.tsx | 2 +- .../[websiteId]/WebsiteDeleteForm.tsx | 5 +++- .../websites/[websiteId]/WebsiteShareForm.tsx | 2 +- src/app/(main)/websites/WebsitesPage.tsx | 2 +- .../websites/[websiteId]/WebsiteHeader.tsx | 7 +++-- src/app/api/realtime/[websiteId]/route.ts | 2 +- src/app/api/reports/attribution/route.ts | 2 +- src/app/api/reports/breakdown/route.ts | 2 +- src/app/api/reports/funnel/route.ts | 2 +- src/app/api/reports/goal/route.ts | 2 +- src/app/api/reports/journey/route.ts | 2 +- src/app/api/reports/retention/route.ts | 2 +- src/app/api/reports/revenue/route.ts | 2 +- src/app/api/reports/utm/route.ts | 2 +- src/app/api/teams/[teamId]/users/route.ts | 2 +- src/app/api/users/[userId]/usage/route.ts | 2 +- .../[websiteId]/event-data/events/route.ts | 2 +- .../[websiteId]/event-data/fields/route.ts | 2 +- .../event-data/properties/route.ts | 2 +- .../[websiteId]/event-data/stats/route.ts | 2 +- .../[websiteId]/event-data/values/route.ts | 2 +- .../api/websites/[websiteId]/events/route.ts | 2 +- .../[websiteId]/events/series/route.ts | 2 +- .../api/websites/[websiteId]/metrics/route.ts | 13 +++++----- .../websites/[websiteId]/pageviews/route.ts | 4 +-- .../session-data/properties/route.ts | 2 +- .../[websiteId]/session-data/values/route.ts | 2 +- .../sessions/[sessionId]/activity/route.ts | 2 +- .../websites/[websiteId]/sessions/route.ts | 2 +- .../[websiteId]/sessions/stats/route.ts | 2 +- .../[websiteId]/sessions/weekly/route.ts | 2 +- .../api/websites/[websiteId]/stats/route.ts | 9 +++---- .../api/websites/[websiteId]/values/route.ts | 2 +- src/components/common/Pager.tsx | 22 +++++++++------- src/components/hooks/queries/useTeamsQuery.ts | 2 +- .../hooks/queries/useUserWebsitesQuery.ts | 2 +- src/components/input/WebsiteSelect.tsx | 16 +++++------- src/lib/request.ts | 26 ++++++++++--------- src/lib/types.ts | 3 +++ src/queries/sql/events/getEventMetrics.ts | 2 +- src/queries/sql/pageviews/getPageviewStats.ts | 2 +- src/queries/sql/sessions/getSessionMetrics.ts | 2 +- src/queries/sql/sessions/getSessionStats.ts | 2 +- .../sql/sessions/getWebsiteSessions.ts | 2 +- 52 files changed, 118 insertions(+), 122 deletions(-) rename src/app/(main)/{MenuBar.tsx => TopNav.tsx} (80%) diff --git a/next.config.ts b/next.config.ts index e52df6ab..f2c07aff 100644 --- a/next.config.ts +++ b/next.config.ts @@ -199,18 +199,6 @@ export default { typescript: { ignoreBuildErrors: true, }, - functions: { - 'app/api/**/*.js': { - maxDuration: 30, - }, - }, - outputFileTracing: { - include: [ - 'src/generated/prisma/**/*', - 'node_modules/@prisma/client/**/*', - 'node_modules/.prisma/client/**/*', - ], - }, async headers() { return headers; }, diff --git a/src/app/(main)/App.tsx b/src/app/(main)/App.tsx index f3975c3a..ecff5023 100644 --- a/src/app/(main)/App.tsx +++ b/src/app/(main)/App.tsx @@ -4,7 +4,7 @@ import Script from 'next/script'; import { usePathname } from 'next/navigation'; import { UpdateNotice } from './UpdateNotice'; import { SideNav } from '@/app/(main)/SideNav'; -import { MenuBar } from '@/app/(main)/MenuBar'; +import { TopNav } from '@/app/(main)/TopNav'; import { useLoginQuery, useConfig } from '@/components/hooks'; export function App({ children }) { @@ -35,7 +35,7 @@ export function App({ children }) { - + {}; + const { teamId, websiteId, pathname } = useNavigation(); + const isSettings = pathname.includes('/settings'); return ( - {websiteId && ( + {websiteId && !isSettings && ( <> - + )} diff --git a/src/app/(main)/admin/users/UserDeleteForm.tsx b/src/app/(main)/admin/users/UserDeleteForm.tsx index 59b12721..620da1d1 100644 --- a/src/app/(main)/admin/users/UserDeleteForm.tsx +++ b/src/app/(main)/admin/users/UserDeleteForm.tsx @@ -21,6 +21,7 @@ export function UserDeleteForm({ mutate(null, { onSuccess: async () => { touch('users'); + touch(`users:${userId}`); onSave?.(); onClose?.(); }, @@ -35,9 +36,7 @@ export function UserDeleteForm({ confirmLabel={formatMessage(labels.delete)} isDanger > - - {formatMessage(messages.confirmDelete, { target: {username} })} - + {formatMessage(messages.confirmDelete, { target: username })} ); } diff --git a/src/app/(main)/admin/websites/AdminWebsitesTable.tsx b/src/app/(main)/admin/websites/AdminWebsitesTable.tsx index 99105bc3..7b970e7f 100644 --- a/src/app/(main)/admin/websites/AdminWebsitesTable.tsx +++ b/src/app/(main)/admin/websites/AdminWebsitesTable.tsx @@ -1,15 +1,16 @@ import { useState } from 'react'; import Link from 'next/link'; -import { Row, Text, Icon, DataTable, DataColumn, MenuItem, Modal } from '@umami/react-zen'; +import { Row, Text, Icon, DataTable, DataColumn, MenuItem, Modal, Dialog } from '@umami/react-zen'; import { Trash, Users } from '@/components/icons'; import { useMessages } from '@/components/hooks'; import { Edit } from '@/components/icons'; import { MenuButton } from '@/components/input/MenuButton'; import { DateDistance } from '@/components/common/DateDistance'; +import { WebsiteDeleteForm } from '@/app/(main)/settings/websites/[websiteId]/WebsiteDeleteForm'; export function AdminWebsitesTable({ data = [] }: { data: any[] }) { const { formatMessage, labels } = useMessages(); - const [deleteUser, setDeleteUser] = useState(null); + const [deleteWebsite, setDeleteWebsite] = useState(null); return ( <> @@ -64,7 +65,7 @@ export function AdminWebsitesTable({ data = [] }: { data: any[] }) { setDeleteUser(row)} + onAction={() => setDeleteWebsite(id)} data-test="link-button-delete" > @@ -79,7 +80,11 @@ export function AdminWebsitesTable({ data = [] }: { data: any[] }) { }} - + + + setDeleteWebsite(null)} /> + + ); } diff --git a/src/app/(main)/settings/SettingsLayout.tsx b/src/app/(main)/settings/SettingsLayout.tsx index cfc901d4..55c77d7b 100644 --- a/src/app/(main)/settings/SettingsLayout.tsx +++ b/src/app/(main)/settings/SettingsLayout.tsx @@ -42,7 +42,7 @@ export function SettingsLayout({ children }: { children: ReactNode }) { - {children} + {children} diff --git a/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx b/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx index e4d7e514..071c56a8 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx @@ -1,7 +1,7 @@ import { useContext, useState } from 'react'; import { Column, Tabs, TabList, Tab, TabPanel } from '@umami/react-zen'; import { TeamContext } from '@/app/(main)/teams/[teamId]/TeamProvider'; -import { useLoginQuery, useMessages } from '@/components/hooks'; +import { useLoginQuery, useMessages, useNavigation } from '@/components/hooks'; import { SectionHeader } from '@/components/common/SectionHeader'; import { ROLES } from '@/lib/constants'; import { Users } from '@/components/icons'; @@ -15,7 +15,10 @@ export function TeamDetails({ teamId }: { teamId: string }) { const team = useContext(TeamContext); const { formatMessage, labels } = useMessages(); const { user } = useLoginQuery(); - const [tab, setTab] = useState('details'); + const { query, pathname } = useNavigation(); + const [tab, setTab] = useState(query?.tab || 'details'); + + const isAdmin = pathname.includes('/admin'); const isTeamOwner = !!team?.teamUser?.find(({ userId, role }) => role === ROLES.teamOwner && userId === user.id) && @@ -32,7 +35,7 @@ export function TeamDetails({ teamId }: { teamId: string }) { return ( }> - {!isTeamOwner && } + {!isTeamOwner && !isAdmin && } setTab(value)}> diff --git a/src/app/(main)/settings/teams/[teamId]/TeamMembersTable.tsx b/src/app/(main)/settings/teams/[teamId]/TeamMembersTable.tsx index f84f58a9..c4cd45a8 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamMembersTable.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamMembersTable.tsx @@ -33,6 +33,10 @@ export function TeamMembersTable({ {allowEdit && ( {(row: any) => { + if (row?.role === ROLES.teamOwner) { + return null; + } + return ( diff --git a/src/app/(main)/settings/websites/WebsitesTable.tsx b/src/app/(main)/settings/websites/WebsitesTable.tsx index 2d285c75..a7948781 100644 --- a/src/app/(main)/settings/websites/WebsitesTable.tsx +++ b/src/app/(main)/settings/websites/WebsitesTable.tsx @@ -57,7 +57,7 @@ export function WebsitesTable({ )} {allowEdit && ( - + diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteDeleteForm.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteDeleteForm.tsx index 9958e8cb..b6e723d7 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteDeleteForm.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteDeleteForm.tsx @@ -1,4 +1,4 @@ -import { useApi, useMessages } from '@/components/hooks'; +import { useApi, useMessages, useModified } from '@/components/hooks'; import { TypeConfirmationForm } from '@/components/common/TypeConfirmationForm'; const CONFIRM_VALUE = 'DELETE'; @@ -17,10 +17,13 @@ export function WebsiteDeleteForm({ const { mutate, isPending, error } = useMutation({ mutationFn: () => del(`/websites/${websiteId}`), }); + const { touch } = useModified(); const handleConfirm = async () => { mutate(null, { onSuccess: async () => { + touch('websites'); + touch(`websites:${websiteId}`); onSave?.(); onClose?.(); }, diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteShareForm.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteShareForm.tsx index dd3dcd26..4f3fe247 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteShareForm.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteShareForm.tsx @@ -73,7 +73,7 @@ export function WebsiteShareForm({ websiteId, shareId, onSave, onClose }: Websit {id && } - + {onClose && } {formatMessage(labels.save)} diff --git a/src/app/(main)/websites/WebsitesPage.tsx b/src/app/(main)/websites/WebsitesPage.tsx index ce922ca2..d07192dc 100644 --- a/src/app/(main)/websites/WebsitesPage.tsx +++ b/src/app/(main)/websites/WebsitesPage.tsx @@ -18,7 +18,7 @@ export function WebsitesPage() { - + diff --git a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx index 9c4dd08c..75a8e97e 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx @@ -5,12 +5,11 @@ import { Share, Edit } from '@/components/icons'; import { Favicon } from '@/components/common/Favicon'; import { ActiveUsers } from '@/components/metrics/ActiveUsers'; import { WebsiteShareForm } from '@/app/(main)/settings/websites/[websiteId]/WebsiteShareForm'; -import { useMessages, useNavigation } from '@/components/hooks'; +import { useMessages } from '@/components/hooks'; import { LinkButton } from '@/components/common/LinkButton'; export function WebsiteHeader() { const website = useWebsite(); - const { renderUrl } = useNavigation(); return ( } showBorder={false}> @@ -18,7 +17,7 @@ export function WebsiteHeader() { - + @@ -42,7 +41,7 @@ const ShareButton = ({ websiteId, shareId }) => { Share - + {({ close }) => { return ; }} diff --git a/src/app/api/realtime/[websiteId]/route.ts b/src/app/api/realtime/[websiteId]/route.ts index f78688c3..f86bfccc 100644 --- a/src/app/api/realtime/[websiteId]/route.ts +++ b/src/app/api/realtime/[websiteId]/route.ts @@ -21,7 +21,7 @@ export async function GET( return unauthorized(); } - const filters = getQueryFilters({ + const filters = await getQueryFilters({ ...query, websiteId, startAt: subMinutes(startOfMinute(new Date()), REALTIME_RANGE).getTime(), diff --git a/src/app/api/reports/attribution/route.ts b/src/app/api/reports/attribution/route.ts index 8c5ab9b3..5f14d667 100644 --- a/src/app/api/reports/attribution/route.ts +++ b/src/app/api/reports/attribution/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters); const data = await getAttribution(websiteId, parameters as AttributionParameters, filters); diff --git a/src/app/api/reports/breakdown/route.ts b/src/app/api/reports/breakdown/route.ts index a95d22b2..96a55f65 100644 --- a/src/app/api/reports/breakdown/route.ts +++ b/src/app/api/reports/breakdown/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters); const data = await getBreakdown(websiteId, parameters as BreakdownParameters, filters); diff --git a/src/app/api/reports/funnel/route.ts b/src/app/api/reports/funnel/route.ts index db68b3c5..3df426a2 100644 --- a/src/app/api/reports/funnel/route.ts +++ b/src/app/api/reports/funnel/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters); const data = await getFunnel(websiteId, parameters as FunnelParameters, filters); diff --git a/src/app/api/reports/goal/route.ts b/src/app/api/reports/goal/route.ts index f7d82549..450e917c 100644 --- a/src/app/api/reports/goal/route.ts +++ b/src/app/api/reports/goal/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters); const data = await getGoal(websiteId, parameters as GoalParameters, filters); diff --git a/src/app/api/reports/journey/route.ts b/src/app/api/reports/journey/route.ts index 3c751f1b..9be1b936 100644 --- a/src/app/api/reports/journey/route.ts +++ b/src/app/api/reports/journey/route.ts @@ -17,7 +17,7 @@ export async function POST(request: Request) { return unauthorized(); } - const queryFilters = await setWebsiteDate(websiteId, getQueryFilters(filters)); + const queryFilters = await setWebsiteDate(websiteId, await getQueryFilters(filters)); const data = await getJourney(websiteId, parameters, queryFilters); diff --git a/src/app/api/reports/retention/route.ts b/src/app/api/reports/retention/route.ts index dfdde298..50a48937 100644 --- a/src/app/api/reports/retention/route.ts +++ b/src/app/api/reports/retention/route.ts @@ -17,7 +17,7 @@ export async function POST(request: Request) { return unauthorized(); } - const filters = getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters); const parameters = await setWebsiteDate(websiteId, body.parameters); const data = await getRetention(websiteId, parameters as RetentionParameters, filters); diff --git a/src/app/api/reports/revenue/route.ts b/src/app/api/reports/revenue/route.ts index c03b083b..02fc69d6 100644 --- a/src/app/api/reports/revenue/route.ts +++ b/src/app/api/reports/revenue/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters); const data = await getRevenue(websiteId, parameters as RevenuParameters, filters); diff --git a/src/app/api/reports/utm/route.ts b/src/app/api/reports/utm/route.ts index 039f88f2..2449c492 100644 --- a/src/app/api/reports/utm/route.ts +++ b/src/app/api/reports/utm/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters); const data = await getUTM(websiteId, parameters as UTMParameters, filters); diff --git a/src/app/api/teams/[teamId]/users/route.ts b/src/app/api/teams/[teamId]/users/route.ts index cf1b4b9b..6fde0c66 100644 --- a/src/app/api/teams/[teamId]/users/route.ts +++ b/src/app/api/teams/[teamId]/users/route.ts @@ -23,7 +23,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ team return unauthorized('You must be the owner of this team.'); } - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); const users = await getTeamUsers( { diff --git a/src/app/api/users/[userId]/usage/route.ts b/src/app/api/users/[userId]/usage/route.ts index 466d97e5..677e0bd7 100644 --- a/src/app/api/users/[userId]/usage/route.ts +++ b/src/app/api/users/[userId]/usage/route.ts @@ -22,7 +22,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ user } const { userId } = await params; - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); const websites = await getAllUserWebsitesIncludingTeamOwner(userId); diff --git a/src/app/api/websites/[websiteId]/event-data/events/route.ts b/src/app/api/websites/[websiteId]/event-data/events/route.ts index 6b819609..eb984207 100644 --- a/src/app/api/websites/[websiteId]/event-data/events/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/events/route.ts @@ -26,7 +26,7 @@ export async function GET( } const { event } = query; - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); const data = await getEventDataEvents(websiteId, { ...filters, diff --git a/src/app/api/websites/[websiteId]/event-data/fields/route.ts b/src/app/api/websites/[websiteId]/event-data/fields/route.ts index 9448c748..34aa6162 100644 --- a/src/app/api/websites/[websiteId]/event-data/fields/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/fields/route.ts @@ -25,7 +25,7 @@ export async function GET( return unauthorized(); } - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); const data = await getEventDataFields(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/event-data/properties/route.ts b/src/app/api/websites/[websiteId]/event-data/properties/route.ts index 918d51a2..ad39e37a 100644 --- a/src/app/api/websites/[websiteId]/event-data/properties/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/properties/route.ts @@ -27,7 +27,7 @@ export async function GET( } const { propertyName } = query; - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); const data = await getEventDataProperties(websiteId, { ...filters, propertyName }); diff --git a/src/app/api/websites/[websiteId]/event-data/stats/route.ts b/src/app/api/websites/[websiteId]/event-data/stats/route.ts index ffc57f96..79dd0059 100644 --- a/src/app/api/websites/[websiteId]/event-data/stats/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/stats/route.ts @@ -26,7 +26,7 @@ export async function GET( return unauthorized(); } - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); const data = await getEventDataStats(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/event-data/values/route.ts b/src/app/api/websites/[websiteId]/event-data/values/route.ts index 9377c4a4..1eab63b5 100644 --- a/src/app/api/websites/[websiteId]/event-data/values/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/values/route.ts @@ -28,7 +28,7 @@ export async function GET( } const { eventName, propertyName } = query; - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); const data = await getEventDataValues(websiteId, { ...filters, diff --git a/src/app/api/websites/[websiteId]/events/route.ts b/src/app/api/websites/[websiteId]/events/route.ts index 1db9be97..0bf6f72c 100644 --- a/src/app/api/websites/[websiteId]/events/route.ts +++ b/src/app/api/websites/[websiteId]/events/route.ts @@ -27,7 +27,7 @@ export async function GET( return unauthorized(); } - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); const data = await getWebsiteEvents(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/events/series/route.ts b/src/app/api/websites/[websiteId]/events/series/route.ts index f8d86cd5..3d9df347 100644 --- a/src/app/api/websites/[websiteId]/events/series/route.ts +++ b/src/app/api/websites/[websiteId]/events/series/route.ts @@ -29,7 +29,7 @@ export async function GET( return unauthorized(); } - const filters = await setWebsiteDate(websiteId, getQueryFilters(query)); + const filters = await setWebsiteDate(websiteId, await getQueryFilters(query)); const data = await getEventMetrics(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/metrics/route.ts b/src/app/api/websites/[websiteId]/metrics/route.ts index 4e6c321f..c576ff26 100644 --- a/src/app/api/websites/[websiteId]/metrics/route.ts +++ b/src/app/api/websites/[websiteId]/metrics/route.ts @@ -11,10 +11,10 @@ import { VIDEO_DOMAINS, PAID_AD_PARAMS, } from '@/lib/constants'; -import { parseRequest, getQueryFilters, setWebsiteDate } from '@/lib/request'; +import { parseRequest, getQueryFilters } from '@/lib/request'; import { json, unauthorized, badRequest } from '@/lib/response'; import { getPageviewMetrics, getSessionMetrics, getChannelMetrics } from '@/queries'; -import { filterParams } from '@/lib/schema'; +import { dateRangeParams, filterParams, searchParams } from '@/lib/schema'; export async function GET( request: Request, @@ -22,11 +22,10 @@ export async function GET( ) { const schema = z.object({ type: z.string(), - startAt: z.coerce.number().int(), - endAt: z.coerce.number().int(), limit: z.coerce.number().optional(), offset: z.coerce.number().optional(), - search: z.string().optional(), + ...dateRangeParams, + ...searchParams, ...filterParams, }); @@ -37,13 +36,13 @@ export async function GET( } const { websiteId } = await params; - const { type, limit, offset, search } = query; if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } - const filters = await setWebsiteDate(websiteId, getQueryFilters(query)); + const { type, limit, offset, search } = query; + const filters = await getQueryFilters(query, websiteId); if (search) { filters[type] = `c.${search}`; diff --git a/src/app/api/websites/[websiteId]/pageviews/route.ts b/src/app/api/websites/[websiteId]/pageviews/route.ts index 41cb1182..83175d0e 100644 --- a/src/app/api/websites/[websiteId]/pageviews/route.ts +++ b/src/app/api/websites/[websiteId]/pageviews/route.ts @@ -1,6 +1,6 @@ import { z } from 'zod'; import { canViewWebsite } from '@/lib/auth'; -import { getQueryFilters, parseRequest, setWebsiteDate } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { dateRangeParams, filterParams } from '@/lib/schema'; import { getCompareDate } from '@/lib/date'; import { unauthorized, json } from '@/lib/response'; @@ -27,7 +27,7 @@ export async function GET( return unauthorized(); } - const filters = await setWebsiteDate(websiteId, getQueryFilters(query)); + const filters = await getQueryFilters(query, websiteId); const [pageviews, sessions] = await Promise.all([ getPageviewStats(websiteId, filters), diff --git a/src/app/api/websites/[websiteId]/session-data/properties/route.ts b/src/app/api/websites/[websiteId]/session-data/properties/route.ts index f38ec556..bdc7c53c 100644 --- a/src/app/api/websites/[websiteId]/session-data/properties/route.ts +++ b/src/app/api/websites/[websiteId]/session-data/properties/route.ts @@ -22,7 +22,7 @@ export async function GET( const { websiteId } = await params; const { propertyName } = query; - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); diff --git a/src/app/api/websites/[websiteId]/session-data/values/route.ts b/src/app/api/websites/[websiteId]/session-data/values/route.ts index dd7502cd..e236a922 100644 --- a/src/app/api/websites/[websiteId]/session-data/values/route.ts +++ b/src/app/api/websites/[websiteId]/session-data/values/route.ts @@ -22,7 +22,7 @@ export async function GET( const { propertyName } = query; const { websiteId } = await params; - const filters = await setWebsiteDate(websiteId, getQueryFilters(query)); + const filters = await setWebsiteDate(websiteId, await getQueryFilters(query)); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); diff --git a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts index c15d1135..5daf2dfb 100644 --- a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts @@ -25,7 +25,7 @@ export async function GET( return unauthorized(); } - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); const data = await getSessionActivity(websiteId, sessionId, filters); diff --git a/src/app/api/websites/[websiteId]/sessions/route.ts b/src/app/api/websites/[websiteId]/sessions/route.ts index dba227be..e5eaf6f0 100644 --- a/src/app/api/websites/[websiteId]/sessions/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/route.ts @@ -27,7 +27,7 @@ export async function GET( return unauthorized(); } - const filters = await setWebsiteDate(websiteId, getQueryFilters(query)); + const filters = await setWebsiteDate(websiteId, await getQueryFilters(query)); const data = await getWebsiteSessions(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/sessions/stats/route.ts b/src/app/api/websites/[websiteId]/sessions/stats/route.ts index 6bee799c..37289f52 100644 --- a/src/app/api/websites/[websiteId]/sessions/stats/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/stats/route.ts @@ -27,7 +27,7 @@ export async function GET( return unauthorized(); } - const filters = await setWebsiteDate(websiteId, getQueryFilters(query)); + const filters = await setWebsiteDate(websiteId, await getQueryFilters(query)); const metrics = await getWebsiteSessionStats(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/sessions/weekly/route.ts b/src/app/api/websites/[websiteId]/sessions/weekly/route.ts index fb0eb1db..757e9da3 100644 --- a/src/app/api/websites/[websiteId]/sessions/weekly/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/weekly/route.ts @@ -28,7 +28,7 @@ export async function GET( return unauthorized(); } - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); const data = await getWebsiteSessionsWeekly(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/stats/route.ts b/src/app/api/websites/[websiteId]/stats/route.ts index bd85c96a..924d189e 100644 --- a/src/app/api/websites/[websiteId]/stats/route.ts +++ b/src/app/api/websites/[websiteId]/stats/route.ts @@ -1,8 +1,8 @@ import { z } from 'zod'; -import { parseRequest, getQueryFilters, setWebsiteDate } from '@/lib/request'; +import { parseRequest, getQueryFilters } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; -import { filterParams } from '@/lib/schema'; +import { dateRangeParams, filterParams } from '@/lib/schema'; import { getWebsiteStats } from '@/queries'; import { getCompareDate } from '@/lib/date'; @@ -11,9 +11,8 @@ export async function GET( { params }: { params: Promise<{ websiteId: string }> }, ) { const schema = z.object({ - startAt: z.coerce.number().int(), - endAt: z.coerce.number().int(), compare: z.string().optional(), + ...dateRangeParams, ...filterParams, }); @@ -29,7 +28,7 @@ export async function GET( return unauthorized(); } - const filters = await setWebsiteDate(websiteId, getQueryFilters(query)); + const filters = await getQueryFilters(query, websiteId); const data = await getWebsiteStats(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/values/route.ts b/src/app/api/websites/[websiteId]/values/route.ts index 8e5a88ac..937c847a 100644 --- a/src/app/api/websites/[websiteId]/values/route.ts +++ b/src/app/api/websites/[websiteId]/values/route.ts @@ -39,7 +39,7 @@ export async function GET( if (FILTER_GROUPS[type]) { values = (await getWebsiteSegments(websiteId, type)).map(segment => ({ value: segment.name })); } else { - const filters = getQueryFilters(query); + const filters = await getQueryFilters(query); values = await getValues(websiteId, FILTER_COLUMNS[type], filters); } diff --git a/src/components/common/Pager.tsx b/src/components/common/Pager.tsx index 31ff8aa5..abc0c172 100644 --- a/src/components/common/Pager.tsx +++ b/src/components/common/Pager.tsx @@ -42,16 +42,18 @@ export function Pager({ page, pageSize, count, onPageChange }: PagerProps) { total: maxPage.toLocaleString(), })} - - + + + + ); diff --git a/src/components/hooks/queries/useTeamsQuery.ts b/src/components/hooks/queries/useTeamsQuery.ts index 1e78db84..6a0ecc34 100644 --- a/src/components/hooks/queries/useTeamsQuery.ts +++ b/src/components/hooks/queries/useTeamsQuery.ts @@ -11,8 +11,8 @@ export function useTeamsQuery(params?: Record, options?: ReactQuery queryKey: ['teams:admin', { modified, ...params }], queryFn: pageParams => { return get(`/admin/teams`, { - ...params, ...pageParams, + ...params, }); }, ...options, diff --git a/src/components/hooks/queries/useUserWebsitesQuery.ts b/src/components/hooks/queries/useUserWebsitesQuery.ts index 5f37d67d..16c28518 100644 --- a/src/components/hooks/queries/useUserWebsitesQuery.ts +++ b/src/components/hooks/queries/useUserWebsitesQuery.ts @@ -17,8 +17,8 @@ export function useUserWebsitesQuery( queryKey: ['websites', { userId, teamId, modified, ...params }], queryFn: pageParams => { return get(teamId ? `/teams/${teamId}/websites` : `/users/${userId || user.id}/websites`, { - ...params, ...pageParams, + ...params, }); }, ...options, diff --git a/src/components/input/WebsiteSelect.tsx b/src/components/input/WebsiteSelect.tsx index 3a8d5519..6e32b0e1 100644 --- a/src/components/input/WebsiteSelect.tsx +++ b/src/components/input/WebsiteSelect.tsx @@ -1,28 +1,24 @@ import { useState } from 'react'; import { Select, SelectProps, ListItem } from '@umami/react-zen'; -import { useUserWebsitesQuery, useMessages } from '@/components/hooks'; +import { useUserWebsitesQuery, useWebsiteQuery, useNavigation } from '@/components/hooks'; export function WebsiteSelect({ websiteId, teamId, variant, - onSelect, ...props }: { websiteId?: string; teamId?: string; variant?: 'primary' | 'outline' | 'quiet' | 'danger' | 'zero'; - onSelect?: (key: any) => void; } & SelectProps) { - const { formatMessage, labels } = useMessages(); + const { router, renderUrl } = useNavigation(); const [search, setSearch] = useState(''); - const [selectedId, setSelectedId] = useState(websiteId); - + const { data: website } = useWebsiteQuery(websiteId); const { data, isLoading } = useUserWebsitesQuery({ teamId }, { search, pageSize: 5 }); const handleSelect = (value: any) => { - setSelectedId(value); - onSelect?.(value); + router.push(renderUrl(`/websites/${value}`)); }; const handleSearch = (value: string) => { @@ -33,14 +29,14 @@ export function WebsiteSelect({ diff --git a/src/lib/request.ts b/src/lib/request.ts index b0df42a3..3d0048f1 100644 --- a/src/lib/request.ts +++ b/src/lib/request.ts @@ -66,7 +66,7 @@ export function getRequestDateRange(query: Record) { }; } -export async function getRequestFilters(query: Record, websiteId?: string) { +export function getRequestFilters(query: Record) { const result: Record = {}; for (const key of Object.keys(FILTER_COLUMNS)) { @@ -76,20 +76,17 @@ export async function getRequestFilters(query: Record, websiteId?: } } + return result; +} + +export async function getRequestSegments(websiteId: string, query: Record) { for (const key of Object.keys(FILTER_GROUPS)) { const value = query[key]; + if (value !== undefined) { - const segment = await getWebsiteSegment(websiteId, key, value); - if (key === 'segment') { - // merge filters into result - Object.assign(result, segment.parameters); - } else { - result[key] = segment.parameters; - } + return getWebsiteSegment(websiteId, key, value); } } - - return result; } export async function setWebsiteDate(websiteId: string, data: Record) { @@ -102,13 +99,18 @@ export async function setWebsiteDate(websiteId: string, data: Record): QueryFilters { - const dateRange = getRequestDateRange(params); +export async function getQueryFilters( + params: Record, + websiteId?: string, +): Promise { + const dateRange = await setWebsiteDate(websiteId, getRequestDateRange(params)); const filters = getRequestFilters(params); + const segments = await getRequestSegments(websiteId, params); return { ...dateRange, ...filters, + ...segments, page: params?.page, pageSize: params?.page ? params?.pageSize || DEFAULT_PAGE_SIZE : undefined, orderBy: params?.orderBy, diff --git a/src/lib/types.ts b/src/lib/types.ts index e1263826..29d566a5 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -71,6 +71,9 @@ export interface FilterParams { search?: string; tag?: string; eventType?: number; + segment?: string; + cohort?: string; + compare?: string; } export interface SortParams { diff --git a/src/queries/sql/events/getEventMetrics.ts b/src/queries/sql/events/getEventMetrics.ts index 0e078ff1..06c141ba 100644 --- a/src/queries/sql/events/getEventMetrics.ts +++ b/src/queries/sql/events/getEventMetrics.ts @@ -85,7 +85,7 @@ async function clickhouseQuery( from ( select arrayJoin(event_name) as event_name, created_at - from website_event_stats_hourly website_event + from website_event_stats_hourly as website_event where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} and event_type = {eventType:UInt32} diff --git a/src/queries/sql/pageviews/getPageviewStats.ts b/src/queries/sql/pageviews/getPageviewStats.ts index 7ef51137..704dea1e 100644 --- a/src/queries/sql/pageviews/getPageviewStats.ts +++ b/src/queries/sql/pageviews/getPageviewStats.ts @@ -81,7 +81,7 @@ async function clickhouseQuery( select ${getDateSQL('website_event.created_at', unit, timezone)} as t, sum(views) as y - from website_event_stats_hourly website_event + from website_event_stats_hourly as website_event ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} diff --git a/src/queries/sql/sessions/getSessionMetrics.ts b/src/queries/sql/sessions/getSessionMetrics.ts index 285eaa7f..7e2393cf 100644 --- a/src/queries/sql/sessions/getSessionMetrics.ts +++ b/src/queries/sql/sessions/getSessionMetrics.ts @@ -103,7 +103,7 @@ async function clickhouseQuery( ${column} x, uniq(session_id) y ${includeCountry ? ', country' : ''} - from website_event_stats_hourly website_event + from website_event_stats_hourly as website_event ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} diff --git a/src/queries/sql/sessions/getSessionStats.ts b/src/queries/sql/sessions/getSessionStats.ts index 9911a235..258de290 100644 --- a/src/queries/sql/sessions/getSessionStats.ts +++ b/src/queries/sql/sessions/getSessionStats.ts @@ -81,7 +81,7 @@ async function clickhouseQuery( select ${getDateSQL('website_event.created_at', unit, timezone)} as t, uniq(session_id) as y - from website_event_stats_hourly website_event + from website_event_stats_hourly as website_event where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} and event_type = {eventType:UInt32} diff --git a/src/queries/sql/sessions/getWebsiteSessions.ts b/src/queries/sql/sessions/getWebsiteSessions.ts index 57dba14e..19b6cf93 100644 --- a/src/queries/sql/sessions/getWebsiteSessions.ts +++ b/src/queries/sql/sessions/getWebsiteSessions.ts @@ -94,7 +94,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) { uniq(visit_id) as visits, sumIf(views, event_type = 1) as views, lastAt as createdAt - from website_event_stats_hourly website_event + from website_event_stats_hourly as website_event ${cohortQuery} where website_id = {websiteId:UUID} ${dateQuery} From 465a03f98755dbc467a807ed9941fa7b2fbed86f Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sun, 13 Jul 2025 21:10:59 -0700 Subject: [PATCH 131/399] Fixed paging in events/sessions. --- src/app/(main)/websites/[websiteId]/WebsiteTabs.tsx | 2 +- .../websites/[websiteId]/events/EventsDataTable.tsx | 12 ++++++------ src/app/api/websites/[websiteId]/events/route.ts | 5 +++-- .../api/websites/[websiteId]/events/series/route.ts | 4 ++-- .../hooks/queries/useWebsiteEventsQuery.ts | 3 ++- .../hooks/queries/useWebsiteSessionsQuery.ts | 7 ++++--- src/lib/request.ts | 8 ++++++-- src/lib/schema.ts | 1 - src/queries/sql/events/getWebsiteEvents.ts | 3 ++- 9 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/app/(main)/websites/[websiteId]/WebsiteTabs.tsx b/src/app/(main)/websites/[websiteId]/WebsiteTabs.tsx index 234df59f..c569b73c 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteTabs.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteTabs.tsx @@ -23,7 +23,7 @@ export function WebsiteTabs() { }, { id: 'sessions', - label: formatMessage(labels.users), + label: formatMessage(labels.sessions), icon: , path: '/sessions', }, diff --git a/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx b/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx index f73ec442..145f06dd 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx @@ -13,7 +13,7 @@ export function EventsDataTable({ children?: ReactNode; }) { const { formatMessage, labels } = useMessages(); - const queryResult = useWebsiteEventsQuery(websiteId); + const query = useWebsiteEventsQuery(websiteId); const [view, setView] = useState('all'); const buttons = [ @@ -22,12 +22,12 @@ export function EventsDataTable({ label: formatMessage(labels.all), }, { - id: 'page', - label: formatMessage(labels.page), + id: 'views', + label: formatMessage(labels.views), }, { - id: 'event', - label: formatMessage(labels.event), + id: 'events', + label: formatMessage(labels.events), }, ]; @@ -37,7 +37,7 @@ export function EventsDataTable({ return ( get(`/websites/${websiteId}/events`, { ...date, ...filters, pageSize: 20 }), + queryFn: pageParams => + get(`/websites/${websiteId}/events`, { ...date, ...filters, ...pageParams, pageSize: 20 }), enabled: !!websiteId, ...options, }); diff --git a/src/components/hooks/queries/useWebsiteSessionsQuery.ts b/src/components/hooks/queries/useWebsiteSessionsQuery.ts index 1d2fad67..f16cfc85 100644 --- a/src/components/hooks/queries/useWebsiteSessionsQuery.ts +++ b/src/components/hooks/queries/useWebsiteSessionsQuery.ts @@ -15,11 +15,12 @@ export function useWebsiteSessionsQuery( return usePagedQuery({ queryKey: ['sessions', { websiteId, modified, ...params, ...date, ...filters }], - queryFn: () => { + queryFn: pageParams => { return get(`/websites/${websiteId}/sessions`, { - ...params, - ...filters, ...date, + ...filters, + ...pageParams, + ...params, pageSize: 20, }); }, diff --git a/src/lib/request.ts b/src/lib/request.ts index 3d0048f1..8fd31529 100644 --- a/src/lib/request.ts +++ b/src/lib/request.ts @@ -103,9 +103,13 @@ export async function getQueryFilters( params: Record, websiteId?: string, ): Promise { - const dateRange = await setWebsiteDate(websiteId, getRequestDateRange(params)); + const dateRange = getRequestDateRange(params); const filters = getRequestFilters(params); - const segments = await getRequestSegments(websiteId, params); + const segments = websiteId ? await getRequestSegments(websiteId, params) : null; + + if (websiteId) { + await setWebsiteDate(websiteId, dateRange); + } return { ...dateRange, diff --git a/src/lib/schema.ts b/src/lib/schema.ts index d44da1f9..2bcbb2bf 100644 --- a/src/lib/schema.ts +++ b/src/lib/schema.ts @@ -50,7 +50,6 @@ export const pagingParams = { export const sortingParams = { orderBy: z.string().optional(), - sortDescending: z.string().optional(), }; export const userRoleParam = z.enum(['admin', 'user', 'view-only']); diff --git a/src/queries/sql/events/getWebsiteEvents.ts b/src/queries/sql/events/getWebsiteEvents.ts index c7e2af17..31493ca2 100644 --- a/src/queries/sql/events/getWebsiteEvents.ts +++ b/src/queries/sql/events/getWebsiteEvents.ts @@ -16,6 +16,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { const { filterQuery, dateQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, + search: `%${search}%`, }); const searchQuery = filters.search @@ -46,7 +47,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { ${searchQuery} order by created_at desc `, - { ...queryParams, search: `%${search}%` }, + queryParams, filters, ); } From 5e6799a715f6738627cbd3f23b1e5913862c6646 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 15 Jul 2025 01:31:08 -0700 Subject: [PATCH 132/399] Fixed properties queries. --- package.json | 2 +- pnpm-lock.yaml | 402 +----------------- .../settings/websites/WebsiteAddButton.tsx | 17 +- .../websites/WebsitesSettingsPage.tsx | 10 +- .../websites/[websiteId]/WebsiteLayout.tsx | 2 - .../[websiteId]/events/EventsDataTable.tsx | 2 +- .../[websiteId]/events/EventsTable.tsx | 42 +- .../[websiteId]/sessions/SessionsTable.tsx | 2 +- .../sessions/[sessionId]/SessionActivity.tsx | 12 +- .../sessions/[sessionId]/SessionInfo.tsx | 14 +- src/app/api/realtime/[websiteId]/route.ts | 12 +- src/app/api/reports/attribution/route.ts | 2 +- src/app/api/reports/breakdown/route.ts | 2 +- src/app/api/reports/funnel/route.ts | 2 +- src/app/api/reports/goal/route.ts | 2 +- src/app/api/reports/journey/route.ts | 4 +- src/app/api/reports/retention/route.ts | 2 +- src/app/api/reports/revenue/route.ts | 2 +- src/app/api/reports/utm/route.ts | 2 +- .../[websiteId]/event-data/events/route.ts | 2 +- .../[websiteId]/event-data/fields/route.ts | 2 +- .../event-data/properties/route.ts | 2 +- .../[websiteId]/event-data/stats/route.ts | 2 +- .../[websiteId]/event-data/values/route.ts | 2 +- .../session-data/properties/route.ts | 5 +- .../[websiteId]/session-data/values/route.ts | 7 +- .../sessions/[sessionId]/activity/route.ts | 2 +- .../websites/[websiteId]/sessions/route.ts | 4 +- .../[websiteId]/sessions/stats/route.ts | 4 +- .../[websiteId]/sessions/weekly/route.ts | 2 +- .../api/websites/[websiteId]/values/route.ts | 2 +- .../hooks/queries/useWebsiteEventsQuery.ts | 15 +- src/components/input/WebsiteSelect.tsx | 1 + src/components/messages.ts | 2 + src/lib/request.ts | 4 +- .../sql/events/getEventDataProperties.ts | 18 +- src/queries/sql/events/getWebsiteEvents.ts | 9 +- .../sql/sessions/getSessionDataProperties.ts | 18 +- 38 files changed, 139 insertions(+), 499 deletions(-) diff --git a/package.json b/package.json index ce8475b0..2acd714c 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "@react-spring/web": "^9.7.3", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.80.10", - "@umami/react-zen": "^0.145.0", + "@umami/react-zen": "^0.147.0", "@umami/redis-client": "^0.27.0", "bcryptjs": "^2.4.3", "chalk": "^4.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9443ea0c..bbb4ecc0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^5.80.10 version: 5.80.10(react@19.1.0) '@umami/react-zen': - specifier: ^0.145.0 - version: 0.145.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) + specifier: ^0.147.0 + version: 0.147.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) '@umami/redis-client': specifier: ^0.27.0 version: 0.27.0 @@ -355,45 +355,6 @@ importers: specifier: ^5.5.3 version: 5.8.3 - dist: - dependencies: - '@tanstack/react-query': - specifier: ^4.33.0 - version: 4.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - classnames: - specifier: ^2.3.1 - version: 2.5.1 - colord: - specifier: ^2.9.2 - version: 2.9.3 - date-fns-tz: - specifier: ^1.1.4 - version: 1.3.8(date-fns@2.30.0) - immer: - specifier: ^9.0.12 - version: 9.0.21 - moment-timezone: - specifier: ^0.5.35 - version: 0.5.48 - next: - specifier: ^13.4.0 - version: 13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - next-basics: - specifier: ^0.36.0 - version: 0.36.0(next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - react-intl: - specifier: ^5.24.7 - version: 5.25.1(react@18.3.1)(typescript@4.9.5) - zustand: - specifier: ^4.3.8 - version: 4.5.7(@types/react@19.1.8)(immer@9.0.21)(react@18.3.1) - packages: '@ampproject/remapping@2.3.0': @@ -1095,9 +1056,6 @@ packages: '@formatjs/ecma402-abstract@2.3.4': resolution: {integrity: sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==} - '@formatjs/fast-memoize@1.2.1': - resolution: {integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==} - '@formatjs/fast-memoize@2.2.3': resolution: {integrity: sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==} @@ -1122,15 +1080,9 @@ packages: '@formatjs/icu-skeleton-parser@1.8.8': resolution: {integrity: sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==} - '@formatjs/intl-displaynames@5.4.3': - resolution: {integrity: sha512-4r12A3mS5dp5hnSaQCWBuBNfi9Amgx2dzhU4lTFfhSxgb5DOAiAbMpg6+7gpWZgl4ahsj3l2r/iHIjdmdXOE2Q==} - '@formatjs/intl-displaynames@6.8.5': resolution: {integrity: sha512-85b+GdAKCsleS6cqVxf/Aw/uBd+20EM0wDpgaxzHo3RIR3bxF4xCJqH/Grbzx8CXurTgDDZHPdPdwJC+May41w==} - '@formatjs/intl-listformat@6.5.3': - resolution: {integrity: sha512-ozpz515F/+3CU+HnLi5DYPsLa6JoCfBggBSSg/8nOB5LYSFW9+ZgNQJxJ8tdhKYeODT+4qVHX27EeJLoxLGLNg==} - '@formatjs/intl-listformat@7.7.5': resolution: {integrity: sha512-Wzes10SMNeYgnxYiKsda4rnHP3Q3II4XT2tZyOgnH5fWuHDtIkceuWlRQNsvrI3uiwP4hLqp2XdQTCsfkhXulg==} @@ -1154,14 +1106,6 @@ packages: typescript: optional: true - '@formatjs/intl@2.2.1': - resolution: {integrity: sha512-vgvyUOOrzqVaOFYzTf2d3+ToSkH2JpR7x/4U1RyoHQLmvEaTQvXJ7A2qm1Iy3brGNXC/+/7bUlc3lpH+h/LOJA==} - peerDependencies: - typescript: ^4.5 - peerDependenciesMeta: - typescript: - optional: true - '@formatjs/ts-transformer@2.13.0': resolution: {integrity: sha512-mu7sHXZk1NWZrQ3eUqugpSYo8x5/tXkrI4uIbFqCEC0eNgQaIcoKgVeDFgDAcgG+cEme2atAUYSFF+DFWC4org==} peerDependencies: @@ -1437,111 +1381,54 @@ packages: resolution: {integrity: sha512-SCF2UPT+mDrfO3DDeUb7eTRqHycBEx4aJ8vACm17Nyn2b2ueaLlS5u/2V42SSZF/F6LydI7R78fv3xPW7HHdWw==} engines: {node: '>=18.0.0'} - '@next/env@13.5.11': - resolution: {integrity: sha512-fbb2C7HChgM7CemdCY+y3N1n8pcTKdqtQLbC7/EQtPdLvlMUT9JX/dBYl8MMZAtYG4uVMyPFHXckb68q/NRwqg==} - '@next/env@15.3.4': resolution: {integrity: sha512-ZkdYzBseS6UjYzz6ylVKPOK+//zLWvD6Ta+vpoye8cW11AjiQjGYVibF0xuvT4L0iJfAPfZLFidaEzAOywyOAQ==} '@next/eslint-plugin-next@14.2.30': resolution: {integrity: sha512-mvVsMIutMxQ4NGZEMZ1kiBNc+la8Xmlk30bKUmCPQz2eFkmsLv54Mha8QZarMaCtSPkkFA1TMD+FIZk0l/PpzA==} - '@next/swc-darwin-arm64@13.5.9': - resolution: {integrity: sha512-pVyd8/1y1l5atQRvOaLOvfbmRwefxLhqQOzYo/M7FQ5eaRwA1+wuCn7t39VwEgDd7Aw1+AIWwd+MURXUeXhwDw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - '@next/swc-darwin-arm64@15.3.4': resolution: {integrity: sha512-z0qIYTONmPRbwHWvpyrFXJd5F9YWLCsw3Sjrzj2ZvMYy9NPQMPZ1NjOJh4ojr4oQzcGYwgJKfidzehaNa1BpEg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@13.5.9': - resolution: {integrity: sha512-DwdeJqP7v8wmoyTWPbPVodTwCybBZa02xjSJ6YQFIFZFZ7dFgrieKW4Eo0GoIcOJq5+JxkQyejmI+8zwDp3pwA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - '@next/swc-darwin-x64@15.3.4': resolution: {integrity: sha512-Z0FYJM8lritw5Wq+vpHYuCIzIlEMjewG2aRkc3Hi2rcbULknYL/xqfpBL23jQnCSrDUGAo/AEv0Z+s2bff9Zkw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@13.5.9': - resolution: {integrity: sha512-wdQsKsIsGSNdFojvjW3Ozrh8Q00+GqL3wTaMjDkQxVtRbAqfFBtrLPO0IuWChVUP2UeuQcHpVeUvu0YgOP00+g==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - '@next/swc-linux-arm64-gnu@15.3.4': resolution: {integrity: sha512-l8ZQOCCg7adwmsnFm8m5q9eIPAHdaB2F3cxhufYtVo84pymwKuWfpYTKcUiFcutJdp9xGHC+F1Uq3xnFU1B/7g==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@13.5.9': - resolution: {integrity: sha512-6VpS+bodQqzOeCwGxoimlRoosiWlSc0C224I7SQWJZoyJuT1ChNCo+45QQH+/GtbR/s7nhaUqmiHdzZC9TXnXA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - '@next/swc-linux-arm64-musl@15.3.4': resolution: {integrity: sha512-wFyZ7X470YJQtpKot4xCY3gpdn8lE9nTlldG07/kJYexCUpX1piX+MBfZdvulo+t1yADFVEuzFfVHfklfEx8kw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@13.5.9': - resolution: {integrity: sha512-XxG3yj61WDd28NA8gFASIR+2viQaYZEFQagEodhI/R49gXWnYhiflTeeEmCn7Vgnxa/OfK81h1gvhUZ66lozpw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - '@next/swc-linux-x64-gnu@15.3.4': resolution: {integrity: sha512-gEbH9rv9o7I12qPyvZNVTyP/PWKqOp8clvnoYZQiX800KkqsaJZuOXkWgMa7ANCCh/oEN2ZQheh3yH8/kWPSEg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@13.5.9': - resolution: {integrity: sha512-/dnscWqfO3+U8asd+Fc6dwL2l9AZDl7eKtPNKW8mKLh4Y4wOpjJiamhe8Dx+D+Oq0GYVjuW0WwjIxYWVozt2bA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - '@next/swc-linux-x64-musl@15.3.4': resolution: {integrity: sha512-Cf8sr0ufuC/nu/yQ76AnarbSAXcwG/wj+1xFPNbyNo8ltA6kw5d5YqO8kQuwVIxk13SBdtgXrNyom3ZosHAy4A==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@13.5.9': - resolution: {integrity: sha512-T/iPnyurOK5a4HRUcxAlss8uzoEf5h9tkd+W2dSWAfzxv8WLKlUgbfk+DH43JY3Gc2xK5URLuXrxDZ2mGfk/jw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - '@next/swc-win32-arm64-msvc@15.3.4': resolution: {integrity: sha512-ay5+qADDN3rwRbRpEhTOreOn1OyJIXS60tg9WMYTWCy3fB6rGoyjLVxc4dR9PYjEdR2iDYsaF5h03NA+XuYPQQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-ia32-msvc@13.5.9': - resolution: {integrity: sha512-BLiPKJomaPrTAb7ykjA0LPcuuNMLDVK177Z1xe0nAem33+9FIayU4k/OWrtSn9SAJW/U60+1hoey5z+KCHdRLQ==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - - '@next/swc-win32-x64-msvc@13.5.9': - resolution: {integrity: sha512-/72/dZfjXXNY/u+n8gqZDjI6rxKMpYsgBBYNZKWOQw0BpBF7WCnPflRy3ZtvQ2+IYI3ZH2bPyj7K+6a6wNk90Q==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - '@next/swc-win32-x64-msvc@15.3.4': resolution: {integrity: sha512-4kDt31Bc9DGyYs41FTL1/kNpDeHyha2TC0j5sRRoKCyrhNcfZ/nRQkAUlF27mETwm8QyHqIjHJitfcza2Iykfg==} engines: {node: '>= 10'} @@ -2429,27 +2316,9 @@ packages: '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} - '@swc/helpers@0.5.2': - resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} - - '@tanstack/query-core@4.40.0': - resolution: {integrity: sha512-7MJTtZkCSuehMC7IxMOCGsLvHS3jHx4WjveSrGsG1Nc1UQLjaFwwkpLA2LmPfvOAxnH4mszMOBFD6LlZE+aB+Q==} - '@tanstack/query-core@5.80.10': resolution: {integrity: sha512-mUNQOtzxkjL6jLbyChZoSBP6A5gQDVRUiPvW+/zw/9ftOAz+H754zCj3D8PwnzPKyHzGkQ9JbH48ukhym9LK1Q==} - '@tanstack/react-query@4.40.1': - resolution: {integrity: sha512-mgD07S5N8e5v81CArKDWrHE4LM7HxZ9k/KLeD3+NUD9WimGZgKIqojUZf/rXkfAMYZU9p0Chzj2jOXm7xpgHHQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-native: '*' - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - '@tanstack/react-query@5.80.10': resolution: {integrity: sha512-6zM098J8sLy9oU60XAdzUlAH4wVzoMVsWUWiiE/Iz4fd67PplxeyL4sw/MPcVJJVhbwGGXCsHn9GrQt2mlAzig==} peerDependencies: @@ -2678,8 +2547,8 @@ packages: resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@umami/react-zen@0.145.0': - resolution: {integrity: sha512-bbbdgWDwW0MIXfSc3JJPDOcmATZpwDsbrDdj37LEvP6rdtUgwAarnATjJa9l3133LGhhEAdYitZqwrDfHHPI5g==} + '@umami/react-zen@0.147.0': + resolution: {integrity: sha512-29A4IxHX/IC4w2v9cCXg8uU8lZ3VPVUrlJH9mngTKSSaCcMzlkgNjKosrQ2xV+wEsMWHl1zV3JRmLL0sgJ9TxA==} '@umami/redis-client@0.27.0': resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==} @@ -4186,9 +4055,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - glob@10.3.10: resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} engines: {node: '>=16 || 14 >=14.17'} @@ -4425,9 +4291,6 @@ packages: intl-messageformat@10.7.7: resolution: {integrity: sha512-F134jIoeYMro/3I0h08D0Yt4N9o9pjddU/4IIxMMURqbAtI2wu70X8hvG1V48W49zXHXv3RKSF/po+0fDfsGjA==} - intl-messageformat@9.13.0: - resolution: {integrity: sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==} - ipaddr.js@2.2.0: resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} engines: {node: '>= 10'} @@ -5219,12 +5082,6 @@ packages: resolution: {integrity: sha512-DXO4L9W+08T+A7h5+xdT32l7IMot8z7WOH+7C1Maol571PnktQ8un7Ni4CyPFp4H+vht/FDA5/tpjRvWMFQDMw==} engines: {node: '>=10', npm: '>=6'} - moment-timezone@0.5.48: - resolution: {integrity: sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==} - - moment@2.30.1: - resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} - ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -5244,28 +5101,6 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - next-basics@0.36.0: - resolution: {integrity: sha512-Nwou8pCjFuoD/ZxUw9iKC7hhZeWbo/ng0ze74yck3W89MNc/CepwCDziflAHY5XcmIVNmpXOCu9OfmzTdVRPWQ==} - peerDependencies: - next: ^13.4.0 - react: ^18.2.0 - react-dom: ^18.2.0 - - next@13.5.11: - resolution: {integrity: sha512-WUPJ6WbAX9tdC86kGTu92qkrRdgRqVrY++nwM+shmWQwmyxt4zhZfR59moXSI4N8GDYCBY3lIAqhzjDd4rTC8Q==} - engines: {node: '>=16.14.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - sass: - optional: true - next@15.3.4: resolution: {integrity: sha512-mHKd50C+mCjam/gcnwqL1T1vPx/XQNFlXqFIVdgQdVAFY9iIQtY0IfaVflEYzKiqjeA7B0cYYMaCrmAYFjs4rA==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} @@ -6101,11 +5936,6 @@ packages: react: ^18.2.0 react-dom: ^18.2.0 - react-dom@18.3.1: - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} - peerDependencies: - react: ^18.3.1 - react-dom@19.1.0: resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} peerDependencies: @@ -6133,15 +5963,6 @@ packages: peerDependencies: react: '*' - react-intl@5.25.1: - resolution: {integrity: sha512-pkjdQDvpJROoXLMltkP/5mZb0/XqrqLoPGKUCfbdkP8m6U9xbK40K51Wu+a4aQqTEvEK5lHBk0fWzUV72SJ3Hg==} - peerDependencies: - react: ^16.3.0 || 17 || 18 - typescript: ^4.5 - peerDependenciesMeta: - typescript: - optional: true - react-intl@6.8.9: resolution: {integrity: sha512-TUfj5E7lyUDvz/GtovC9OMh441kBr08rtIbgh3p0R8iF3hVY+V2W9Am7rb8BpJ/29BH1utJOqOOhmvEVh3GfZg==} peerDependencies: @@ -6197,10 +6018,6 @@ packages: react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - react@19.1.0: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} @@ -6387,9 +6204,6 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} @@ -6649,19 +6463,6 @@ packages: style-search@0.1.0: resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} - styled-jsx@5.1.1: - resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - styled-jsx@5.1.6: resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} engines: {node: '>= 12.0.0'} @@ -7038,10 +6839,6 @@ packages: walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - watchpack@2.4.0: - resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} - engines: {node: '>=10.13.0'} - web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -7157,21 +6954,6 @@ packages: zod@3.25.67: resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} - zustand@4.5.7: - resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==} - engines: {node: '>=12.7.0'} - peerDependencies: - '@types/react': '>=16.8' - immer: '>=9.0.6' - react: '>=16.8' - peerDependenciesMeta: - '@types/react': - optional: true - immer: - optional: true - react: - optional: true - zustand@5.0.5: resolution: {integrity: sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==} engines: {node: '>=12.20.0'} @@ -7845,10 +7627,6 @@ snapshots: decimal.js: 10.6.0 tslib: 2.8.1 - '@formatjs/fast-memoize@1.2.1': - dependencies: - tslib: 2.8.1 - '@formatjs/fast-memoize@2.2.3': dependencies: tslib: 2.8.1 @@ -7890,24 +7668,12 @@ snapshots: '@formatjs/ecma402-abstract': 2.2.4 tslib: 2.8.1 - '@formatjs/intl-displaynames@5.4.3': - dependencies: - '@formatjs/ecma402-abstract': 1.11.4 - '@formatjs/intl-localematcher': 0.2.25 - tslib: 2.8.1 - '@formatjs/intl-displaynames@6.8.5': dependencies: '@formatjs/ecma402-abstract': 2.2.4 '@formatjs/intl-localematcher': 0.5.8 tslib: 2.8.1 - '@formatjs/intl-listformat@6.5.3': - dependencies: - '@formatjs/ecma402-abstract': 1.11.4 - '@formatjs/intl-localematcher': 0.2.25 - tslib: 2.8.1 - '@formatjs/intl-listformat@7.7.5': dependencies: '@formatjs/ecma402-abstract': 2.2.4 @@ -7943,18 +7709,6 @@ snapshots: optionalDependencies: typescript: 5.8.3 - '@formatjs/intl@2.2.1(typescript@4.9.5)': - dependencies: - '@formatjs/ecma402-abstract': 1.11.4 - '@formatjs/fast-memoize': 1.2.1 - '@formatjs/icu-messageformat-parser': 2.1.0 - '@formatjs/intl-displaynames': 5.4.3 - '@formatjs/intl-listformat': 6.5.3 - intl-messageformat: 9.13.0 - tslib: 2.8.1 - optionalDependencies: - typescript: 4.9.5 - '@formatjs/ts-transformer@2.13.0(ts-jest@29.4.0(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.5)(jest-util@29.7.0)(jest@29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@types/node@22.15.32)(typescript@5.8.3)))(typescript@5.8.3))': dependencies: intl-messageformat-parser: 6.1.2 @@ -8316,62 +8070,33 @@ snapshots: '@netlify/plugin-nextjs@5.11.3': {} - '@next/env@13.5.11': {} - '@next/env@15.3.4': {} '@next/eslint-plugin-next@14.2.30': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@13.5.9': - optional: true - '@next/swc-darwin-arm64@15.3.4': optional: true - '@next/swc-darwin-x64@13.5.9': - optional: true - '@next/swc-darwin-x64@15.3.4': optional: true - '@next/swc-linux-arm64-gnu@13.5.9': - optional: true - '@next/swc-linux-arm64-gnu@15.3.4': optional: true - '@next/swc-linux-arm64-musl@13.5.9': - optional: true - '@next/swc-linux-arm64-musl@15.3.4': optional: true - '@next/swc-linux-x64-gnu@13.5.9': - optional: true - '@next/swc-linux-x64-gnu@15.3.4': optional: true - '@next/swc-linux-x64-musl@13.5.9': - optional: true - '@next/swc-linux-x64-musl@15.3.4': optional: true - '@next/swc-win32-arm64-msvc@13.5.9': - optional: true - '@next/swc-win32-arm64-msvc@15.3.4': optional: true - '@next/swc-win32-ia32-msvc@13.5.9': - optional: true - - '@next/swc-win32-x64-msvc@13.5.9': - optional: true - '@next/swc-win32-x64-msvc@15.3.4': optional: true @@ -9728,22 +9453,8 @@ snapshots: dependencies: tslib: 2.8.1 - '@swc/helpers@0.5.2': - dependencies: - tslib: 2.8.1 - - '@tanstack/query-core@4.40.0': {} - '@tanstack/query-core@5.80.10': {} - '@tanstack/react-query@4.40.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@tanstack/query-core': 4.40.0 - react: 18.3.1 - use-sync-external-store: 1.5.0(react@18.3.1) - optionalDependencies: - react-dom: 18.3.1(react@18.3.1) - '@tanstack/react-query@5.80.10(react@19.1.0)': dependencies: '@tanstack/query-core': 5.80.10 @@ -10025,7 +9736,7 @@ snapshots: '@typescript-eslint/types': 8.34.1 eslint-visitor-keys: 4.2.1 - '@umami/react-zen@0.145.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': + '@umami/react-zen@0.147.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': dependencies: '@fontsource/jetbrains-mono': 5.2.6 '@internationalized/date': 3.8.2 @@ -11848,8 +11559,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob-to-regexp@0.4.1: {} - glob@10.3.10: dependencies: foreground-child: 3.3.1 @@ -12079,13 +11788,6 @@ snapshots: '@formatjs/icu-messageformat-parser': 2.9.4 tslib: 2.8.1 - intl-messageformat@9.13.0: - dependencies: - '@formatjs/ecma402-abstract': 1.11.4 - '@formatjs/fast-memoize': 1.2.1 - '@formatjs/icu-messageformat-parser': 2.1.0 - tslib: 2.8.1 - ipaddr.js@2.2.0: {} is-array-buffer@3.0.5: @@ -13062,12 +12764,6 @@ snapshots: mmdb-lib@2.2.1: {} - moment-timezone@0.5.48: - dependencies: - moment: 2.30.1 - - moment@2.30.1: {} - ms@2.1.2: {} ms@2.1.3: {} @@ -13078,40 +12774,6 @@ snapshots: natural-compare@1.4.0: {} - next-basics@0.36.0(next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - bcryptjs: 2.4.3 - jsonwebtoken: 9.0.2 - next: 13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - pure-rand: 6.1.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@next/env': 13.5.11 - '@swc/helpers': 0.5.2 - busboy: 1.6.0 - caniuse-lite: 1.0.30001727 - postcss: 8.4.31 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.1(@babel/core@7.27.1)(react@18.3.1) - watchpack: 2.4.0 - optionalDependencies: - '@next/swc-darwin-arm64': 13.5.9 - '@next/swc-darwin-x64': 13.5.9 - '@next/swc-linux-arm64-gnu': 13.5.9 - '@next/swc-linux-arm64-musl': 13.5.9 - '@next/swc-linux-x64-gnu': 13.5.9 - '@next/swc-linux-x64-musl': 13.5.9 - '@next/swc-win32-arm64-msvc': 13.5.9 - '@next/swc-win32-ia32-msvc': 13.5.9 - '@next/swc-win32-x64-msvc': 13.5.9 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - next@15.3.4(@babel/core@7.27.1)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@next/env': 15.3.4 @@ -13997,12 +13659,6 @@ snapshots: react-hook-form: 7.56.4(react@19.1.0) react-window: 1.8.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react-dom@18.3.1(react@18.3.1): - dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 - react-dom@19.1.0(react@19.1.0): dependencies: react: 19.1.0 @@ -14025,22 +13681,6 @@ snapshots: dependencies: react: 19.1.0 - react-intl@5.25.1(react@18.3.1)(typescript@4.9.5): - dependencies: - '@formatjs/ecma402-abstract': 1.11.4 - '@formatjs/icu-messageformat-parser': 2.1.0 - '@formatjs/intl': 2.2.1(typescript@4.9.5) - '@formatjs/intl-displaynames': 5.4.3 - '@formatjs/intl-listformat': 6.5.3 - '@types/hoist-non-react-statics': 3.3.6 - '@types/react': 18.3.23 - hoist-non-react-statics: 3.3.2 - intl-messageformat: 9.13.0 - react: 18.3.1 - tslib: 2.8.1 - optionalDependencies: - typescript: 4.9.5 - react-intl@6.8.9(react@19.1.0)(typescript@5.8.3): dependencies: '@formatjs/ecma402-abstract': 2.2.4 @@ -14123,10 +13763,6 @@ snapshots: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - react@18.3.1: - dependencies: - loose-envify: 1.4.0 - react@19.1.0: {} read-babelrc-up@1.1.0: @@ -14360,10 +13996,6 @@ snapshots: safer-buffer@2.1.2: {} - scheduler@0.23.2: - dependencies: - loose-envify: 1.4.0 - scheduler@0.26.0: {} schema-utils@2.7.1: @@ -14682,13 +14314,6 @@ snapshots: style-search@0.1.0: {} - styled-jsx@5.1.1(@babel/core@7.27.1)(react@18.3.1): - dependencies: - client-only: 0.0.1 - react: 18.3.1 - optionalDependencies: - '@babel/core': 7.27.1 - styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.1.0): dependencies: client-only: 0.0.1 @@ -15070,10 +14695,6 @@ snapshots: dependencies: react: 19.1.0 - use-sync-external-store@1.5.0(react@18.3.1): - dependencies: - react: 18.3.1 - use-sync-external-store@1.5.0(react@19.1.0): dependencies: react: 19.1.0 @@ -15119,11 +14740,6 @@ snapshots: dependencies: makeerror: 1.0.12 - watchpack@2.4.0: - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - web-streams-polyfill@3.3.3: {} which-boxed-primitive@1.1.1: @@ -15265,14 +14881,6 @@ snapshots: zod@3.25.67: {} - zustand@4.5.7(@types/react@19.1.8)(immer@9.0.21)(react@18.3.1): - dependencies: - use-sync-external-store: 1.5.0(react@18.3.1) - optionalDependencies: - '@types/react': 19.1.8 - immer: 9.0.21 - react: 18.3.1 - zustand@5.0.5(@types/react@19.1.8)(immer@9.0.21)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)): optionalDependencies: '@types/react': 19.1.8 diff --git a/src/app/(main)/settings/websites/WebsiteAddButton.tsx b/src/app/(main)/settings/websites/WebsiteAddButton.tsx index 4db62c44..050098f0 100644 --- a/src/app/(main)/settings/websites/WebsiteAddButton.tsx +++ b/src/app/(main)/settings/websites/WebsiteAddButton.tsx @@ -1,14 +1,5 @@ import { useMessages, useModified } from '@/components/hooks'; -import { - Button, - Icon, - Modal, - Dialog, - DialogTrigger, - Text, - Column, - useToast, -} from '@umami/react-zen'; +import { Button, Icon, Modal, Dialog, DialogTrigger, Text, useToast } from '@umami/react-zen'; import { Plus } from '@/components/icons'; import { WebsiteAddForm } from './WebsiteAddForm'; @@ -33,11 +24,7 @@ export function WebsiteAddButton({ teamId, onSave }: { teamId: string; onSave?: - {({ close }) => ( - - - - )} + {({ close }) => } diff --git a/src/app/(main)/settings/websites/WebsitesSettingsPage.tsx b/src/app/(main)/settings/websites/WebsitesSettingsPage.tsx index 675c9499..6196e759 100644 --- a/src/app/(main)/settings/websites/WebsitesSettingsPage.tsx +++ b/src/app/(main)/settings/websites/WebsitesSettingsPage.tsx @@ -1,21 +1,15 @@ 'use client'; import { Column } from '@umami/react-zen'; -import { useLoginQuery, useMessages } from '@/components/hooks'; +import { useMessages } from '@/components/hooks'; import { WebsitesDataTable } from './WebsitesDataTable'; -import { ROLES } from '@/lib/constants'; import { SectionHeader } from '@/components/common/SectionHeader'; -import { WebsiteAddButton } from './WebsiteAddButton'; export function WebsitesSettingsPage({ teamId }: { teamId: string }) { - const { user } = useLoginQuery(); - const canCreate = user.role !== ROLES.viewOnly; const { formatMessage, labels } = useMessages(); return ( - - {canCreate && } - + ); diff --git a/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx b/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx index 3a3255bd..3f85b4f3 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx @@ -4,14 +4,12 @@ import { Column } from '@umami/react-zen'; import { WebsiteProvider } from './WebsiteProvider'; import { PageBody } from '@/components/common/PageBody'; import { WebsiteHeader } from './WebsiteHeader'; -import { WebsiteTabs } from './WebsiteTabs'; export function WebsiteLayout({ websiteId, children }: { websiteId: string; children: ReactNode }) { return ( - {children} diff --git a/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx b/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx index 145f06dd..22b0f679 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx @@ -13,8 +13,8 @@ export function EventsDataTable({ children?: ReactNode; }) { const { formatMessage, labels } = useMessages(); - const query = useWebsiteEventsQuery(websiteId); const [view, setView] = useState('all'); + const query = useWebsiteEventsQuery(websiteId); const buttons = [ { diff --git a/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx b/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx index 598e3c7d..c034c9ea 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx @@ -1,5 +1,5 @@ import { DataTable, DataColumn, Icon, Row } from '@umami/react-zen'; -import { useMessages, useNavigation } from '@/components/hooks'; +import { useFormat, useMessages, useNavigation } from '@/components/hooks'; import { Empty } from '@/components/common/Empty'; import { Avatar } from '@/components/common/Avatar'; import Link from 'next/link'; @@ -10,6 +10,7 @@ import { TypeIcon } from '@/components/common/TypeIcon'; export function EventsTable({ data = [] }) { const { formatMessage, labels } = useMessages(); const { renderUrl } = useNavigation(); + const { formatValue } = useFormat(); if (data.length === 0) { return ; @@ -20,7 +21,10 @@ export function EventsTable({ data = [] }) { {(row: any) => { return ( - + + + + {row.eventName ? : } {formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)} {row.eventName || row.urlPath} @@ -28,22 +32,30 @@ export function EventsTable({ data = [] }) { ); }} - + {(row: any) => ( - - - - - - - - - - - - + + {row.city ? `${row.city}, ` : ''} {formatValue(row.country, 'country')} + )} + + {(row: any) => ( + + {formatValue(row.browser, 'browser')} + + )} + + + {(row: any) => ( + + {formatValue(row.device, 'device')} + + )} + + + {(row: any) => } + ); } diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx index 1d40e4ac..fa3be6c7 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx @@ -14,7 +14,7 @@ export function SessionsTable({ data = [] }: { data: any[]; showDomain?: boolean {(row: any) => ( - + )} diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx index a5fc93aa..d88fff7a 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx @@ -13,7 +13,7 @@ import { } from '@umami/react-zen'; import { LoadingPanel } from '@/components/common/LoadingPanel'; import { Bolt, Eye, FileText } from '@/components/icons'; -import { useSessionActivityQuery, useTimezone } from '@/components/hooks'; +import { useMessages, useSessionActivityQuery, useTimezone } from '@/components/hooks'; import { EventData } from '@/components/metrics/EventData'; export function SessionActivity({ @@ -27,6 +27,7 @@ export function SessionActivity({ startDate: Date; endDate: Date; }) { + const { formatMessage, labels } = useMessages(); const { formatTimezoneDate } = useTimezone(); const { data, isLoading, error } = useSessionActivityQuery( websiteId, @@ -50,9 +51,14 @@ export function SessionActivity({ {formatTimezoneDate(createdAt, 'pp')} - + {eventName ? : } - {eventName || urlPath} + + {eventName + ? formatMessage(labels.triggeredEvent) + : formatMessage(labels.viewedPage)} + + {eventName || urlPath} {hasData > 0 && } diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx index 3a1d6829..629e1da6 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx @@ -44,6 +44,13 @@ export function SessionInfo({ data }) { {data?.city} + } + > + {formatValue(data?.browser, 'browser')} + + } @@ -57,13 +64,6 @@ export function SessionInfo({ data }) { > {formatValue(data?.device, 'device')} - - } - > - {formatValue(data?.browser, 'browser')} - ); } diff --git a/src/app/api/realtime/[websiteId]/route.ts b/src/app/api/realtime/[websiteId]/route.ts index f86bfccc..d06d460a 100644 --- a/src/app/api/realtime/[websiteId]/route.ts +++ b/src/app/api/realtime/[websiteId]/route.ts @@ -21,12 +21,14 @@ export async function GET( return unauthorized(); } - const filters = await getQueryFilters({ - ...query, + const filters = await getQueryFilters( + { + ...query, + startAt: subMinutes(startOfMinute(new Date()), REALTIME_RANGE).getTime(), + endAt: Date.now(), + }, websiteId, - startAt: subMinutes(startOfMinute(new Date()), REALTIME_RANGE).getTime(), - endAt: Date.now(), - }); + ); const data = await getRealtimeData(websiteId, filters); diff --git a/src/app/api/reports/attribution/route.ts b/src/app/api/reports/attribution/route.ts index 5f14d667..689c6400 100644 --- a/src/app/api/reports/attribution/route.ts +++ b/src/app/api/reports/attribution/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = await getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters, websiteId); const data = await getAttribution(websiteId, parameters as AttributionParameters, filters); diff --git a/src/app/api/reports/breakdown/route.ts b/src/app/api/reports/breakdown/route.ts index 96a55f65..f948051d 100644 --- a/src/app/api/reports/breakdown/route.ts +++ b/src/app/api/reports/breakdown/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = await getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters, websiteId); const data = await getBreakdown(websiteId, parameters as BreakdownParameters, filters); diff --git a/src/app/api/reports/funnel/route.ts b/src/app/api/reports/funnel/route.ts index 3df426a2..0acab5c9 100644 --- a/src/app/api/reports/funnel/route.ts +++ b/src/app/api/reports/funnel/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = await getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters, websiteId); const data = await getFunnel(websiteId, parameters as FunnelParameters, filters); diff --git a/src/app/api/reports/goal/route.ts b/src/app/api/reports/goal/route.ts index 450e917c..86c80a0e 100644 --- a/src/app/api/reports/goal/route.ts +++ b/src/app/api/reports/goal/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = await getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters, websiteId); const data = await getGoal(websiteId, parameters as GoalParameters, filters); diff --git a/src/app/api/reports/journey/route.ts b/src/app/api/reports/journey/route.ts index 9be1b936..4b31216e 100644 --- a/src/app/api/reports/journey/route.ts +++ b/src/app/api/reports/journey/route.ts @@ -1,6 +1,6 @@ import { canViewWebsite } from '@/lib/auth'; import { unauthorized, json } from '@/lib/response'; -import { getQueryFilters, parseRequest, setWebsiteDate } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { getJourney } from '@/queries'; import { reportResultSchema } from '@/lib/schema'; @@ -17,7 +17,7 @@ export async function POST(request: Request) { return unauthorized(); } - const queryFilters = await setWebsiteDate(websiteId, await getQueryFilters(filters)); + const queryFilters = await getQueryFilters(filters, websiteId); const data = await getJourney(websiteId, parameters, queryFilters); diff --git a/src/app/api/reports/retention/route.ts b/src/app/api/reports/retention/route.ts index 50a48937..9367ab70 100644 --- a/src/app/api/reports/retention/route.ts +++ b/src/app/api/reports/retention/route.ts @@ -17,7 +17,7 @@ export async function POST(request: Request) { return unauthorized(); } - const filters = await getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters, websiteId); const parameters = await setWebsiteDate(websiteId, body.parameters); const data = await getRetention(websiteId, parameters as RetentionParameters, filters); diff --git a/src/app/api/reports/revenue/route.ts b/src/app/api/reports/revenue/route.ts index 02fc69d6..b8a6ae4c 100644 --- a/src/app/api/reports/revenue/route.ts +++ b/src/app/api/reports/revenue/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = await getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters, websiteId); const data = await getRevenue(websiteId, parameters as RevenuParameters, filters); diff --git a/src/app/api/reports/utm/route.ts b/src/app/api/reports/utm/route.ts index 2449c492..17c5c1c6 100644 --- a/src/app/api/reports/utm/route.ts +++ b/src/app/api/reports/utm/route.ts @@ -18,7 +18,7 @@ export async function POST(request: Request) { } const parameters = await setWebsiteDate(websiteId, body.parameters); - const filters = await getQueryFilters(body.filters); + const filters = await getQueryFilters(body.filters, websiteId); const data = await getUTM(websiteId, parameters as UTMParameters, filters); diff --git a/src/app/api/websites/[websiteId]/event-data/events/route.ts b/src/app/api/websites/[websiteId]/event-data/events/route.ts index eb984207..2f1de5d3 100644 --- a/src/app/api/websites/[websiteId]/event-data/events/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/events/route.ts @@ -26,7 +26,7 @@ export async function GET( } const { event } = query; - const filters = await getQueryFilters(query); + const filters = await getQueryFilters(query, websiteId); const data = await getEventDataEvents(websiteId, { ...filters, diff --git a/src/app/api/websites/[websiteId]/event-data/fields/route.ts b/src/app/api/websites/[websiteId]/event-data/fields/route.ts index 34aa6162..1d97a4ba 100644 --- a/src/app/api/websites/[websiteId]/event-data/fields/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/fields/route.ts @@ -25,7 +25,7 @@ export async function GET( return unauthorized(); } - const filters = await getQueryFilters(query); + const filters = await getQueryFilters(query, websiteId); const data = await getEventDataFields(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/event-data/properties/route.ts b/src/app/api/websites/[websiteId]/event-data/properties/route.ts index ad39e37a..5043e272 100644 --- a/src/app/api/websites/[websiteId]/event-data/properties/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/properties/route.ts @@ -27,7 +27,7 @@ export async function GET( } const { propertyName } = query; - const filters = await getQueryFilters(query); + const filters = await getQueryFilters(query, websiteId); const data = await getEventDataProperties(websiteId, { ...filters, propertyName }); diff --git a/src/app/api/websites/[websiteId]/event-data/stats/route.ts b/src/app/api/websites/[websiteId]/event-data/stats/route.ts index 79dd0059..9b7fe357 100644 --- a/src/app/api/websites/[websiteId]/event-data/stats/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/stats/route.ts @@ -26,7 +26,7 @@ export async function GET( return unauthorized(); } - const filters = await getQueryFilters(query); + const filters = await getQueryFilters(query, websiteId); const data = await getEventDataStats(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/event-data/values/route.ts b/src/app/api/websites/[websiteId]/event-data/values/route.ts index 1eab63b5..6210de84 100644 --- a/src/app/api/websites/[websiteId]/event-data/values/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/values/route.ts @@ -28,7 +28,7 @@ export async function GET( } const { eventName, propertyName } = query; - const filters = await getQueryFilters(query); + const filters = await getQueryFilters(query, websiteId); const data = await getEventDataValues(websiteId, { ...filters, diff --git a/src/app/api/websites/[websiteId]/session-data/properties/route.ts b/src/app/api/websites/[websiteId]/session-data/properties/route.ts index bdc7c53c..b51f1c2f 100644 --- a/src/app/api/websites/[websiteId]/session-data/properties/route.ts +++ b/src/app/api/websites/[websiteId]/session-data/properties/route.ts @@ -21,13 +21,14 @@ export async function GET( } const { websiteId } = await params; - const { propertyName } = query; - const filters = await getQueryFilters(query); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } + const { propertyName } = query; + const filters = await getQueryFilters(query, websiteId); + const data = await getSessionDataProperties(websiteId, { ...filters, propertyName }); return json(data); diff --git a/src/app/api/websites/[websiteId]/session-data/values/route.ts b/src/app/api/websites/[websiteId]/session-data/values/route.ts index e236a922..858aa5e3 100644 --- a/src/app/api/websites/[websiteId]/session-data/values/route.ts +++ b/src/app/api/websites/[websiteId]/session-data/values/route.ts @@ -1,5 +1,5 @@ import { canViewWebsite } from '@/lib/auth'; -import { getQueryFilters, parseRequest, setWebsiteDate } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; import { getSessionDataValues } from '@/queries'; import { z } from 'zod'; @@ -20,14 +20,15 @@ export async function GET( return error(); } - const { propertyName } = query; const { websiteId } = await params; - const filters = await setWebsiteDate(websiteId, await getQueryFilters(query)); if (!(await canViewWebsite(auth, websiteId))) { return unauthorized(); } + const { propertyName } = query; + const filters = await getQueryFilters(query, websiteId); + const data = await getSessionDataValues(websiteId, { ...filters, propertyName, diff --git a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts index 5daf2dfb..268e7bf8 100644 --- a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts @@ -25,7 +25,7 @@ export async function GET( return unauthorized(); } - const filters = await getQueryFilters(query); + const filters = await getQueryFilters(query, websiteId); const data = await getSessionActivity(websiteId, sessionId, filters); diff --git a/src/app/api/websites/[websiteId]/sessions/route.ts b/src/app/api/websites/[websiteId]/sessions/route.ts index e5eaf6f0..bcc4b8bc 100644 --- a/src/app/api/websites/[websiteId]/sessions/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { getQueryFilters, parseRequest, setWebsiteDate } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { dateRangeParams, filterParams, pagingParams } from '@/lib/schema'; @@ -27,7 +27,7 @@ export async function GET( return unauthorized(); } - const filters = await setWebsiteDate(websiteId, await getQueryFilters(query)); + const filters = await getQueryFilters(query, websiteId); const data = await getWebsiteSessions(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/sessions/stats/route.ts b/src/app/api/websites/[websiteId]/sessions/stats/route.ts index 37289f52..d78be852 100644 --- a/src/app/api/websites/[websiteId]/sessions/stats/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/stats/route.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { parseRequest, getQueryFilters, setWebsiteDate } from '@/lib/request'; +import { parseRequest, getQueryFilters } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; import { filterParams } from '@/lib/schema'; @@ -27,7 +27,7 @@ export async function GET( return unauthorized(); } - const filters = await setWebsiteDate(websiteId, await getQueryFilters(query)); + const filters = await getQueryFilters(query, websiteId); const metrics = await getWebsiteSessionStats(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/sessions/weekly/route.ts b/src/app/api/websites/[websiteId]/sessions/weekly/route.ts index 757e9da3..2c7b227f 100644 --- a/src/app/api/websites/[websiteId]/sessions/weekly/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/weekly/route.ts @@ -28,7 +28,7 @@ export async function GET( return unauthorized(); } - const filters = await getQueryFilters(query); + const filters = await getQueryFilters(query, websiteId); const data = await getWebsiteSessionsWeekly(websiteId, filters); diff --git a/src/app/api/websites/[websiteId]/values/route.ts b/src/app/api/websites/[websiteId]/values/route.ts index 937c847a..e4140e14 100644 --- a/src/app/api/websites/[websiteId]/values/route.ts +++ b/src/app/api/websites/[websiteId]/values/route.ts @@ -39,7 +39,7 @@ export async function GET( if (FILTER_GROUPS[type]) { values = (await getWebsiteSegments(websiteId, type)).map(segment => ({ value: segment.name })); } else { - const filters = await getQueryFilters(query); + const filters = await getQueryFilters(query, websiteId); values = await getValues(websiteId, FILTER_COLUMNS[type], filters); } diff --git a/src/components/hooks/queries/useWebsiteEventsQuery.ts b/src/components/hooks/queries/useWebsiteEventsQuery.ts index 186cab07..3406285a 100644 --- a/src/components/hooks/queries/useWebsiteEventsQuery.ts +++ b/src/components/hooks/queries/useWebsiteEventsQuery.ts @@ -4,15 +4,24 @@ import { useDateParameters } from '../useDateParameters'; import { usePagedQuery } from '../usePagedQuery'; import { ReactQueryOptions } from '@/lib/types'; -export function useWebsiteEventsQuery(websiteId: string, options?: ReactQueryOptions) { +export function useWebsiteEventsQuery( + websiteId: string, + params?: Record, + options?: ReactQueryOptions, +) { const { get } = useApi(); const date = useDateParameters(websiteId); const filters = useFilterParameters(); return usePagedQuery({ - queryKey: ['websites:events', { websiteId, ...date, ...filters }], + queryKey: ['websites:events', { websiteId, ...date, ...filters, ...params }], queryFn: pageParams => - get(`/websites/${websiteId}/events`, { ...date, ...filters, ...pageParams, pageSize: 20 }), + get(`/websites/${websiteId}/events`, { + ...date, + ...filters, + ...pageParams, + ...params, + }), enabled: !!websiteId, ...options, }); diff --git a/src/components/input/WebsiteSelect.tsx b/src/components/input/WebsiteSelect.tsx index 6e32b0e1..11c50718 100644 --- a/src/components/input/WebsiteSelect.tsx +++ b/src/components/input/WebsiteSelect.tsx @@ -28,6 +28,7 @@ export function WebsiteSelect({ return ( + {events?.map(p => ( + + {p} + + ))} + + + + {propertyName && ( + + )} + + ); +} + +const EventValues = ({ websiteId, eventName, propertyName }) => { + const { + data: values, + isLoading, + isFetching, + error, + } = useEventDataValuesQuery(websiteId, eventName, propertyName); const propertySum = useMemo(() => { return values?.reduce((sum, { total }) => sum + total, 0) ?? 0; @@ -55,43 +104,19 @@ export function EventProperties({ websiteId }: { websiteId: string }) { })); }, [propertyName, values, propertySum]); - const handleRowClick = row => { - setEventName(row.eventName); - setPropertyName(row.propertyName); - }; - return ( - - - - - {(row: any) => handleRowClick(row)}>{row.eventName}} - - - {(row: any) => handleRowClick(row)}>{row.propertyName}} - - - - {propertyName && ( - - - {`${eventName}: ${propertyName}`} - setPropertyView(value[0])}> - {formatMessage(labels.table)} - {formatMessage(labels.chart)} - - - - {!values ? ( - - ) : propertyView === 'table' ? ( - - ) : ( - - )} - - )} - + + + {values && } + + ); -} +}; diff --git a/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx b/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx index fbf11e8e..7e4ef98a 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx @@ -5,7 +5,6 @@ import { useState } from 'react'; import { EventsDataTable } from './EventsDataTable'; import { Panel } from '@/components/common/Panel'; import { EventsChart } from '@/components/metrics/EventsChart'; -import { GridRow } from '@/components/common/GridRow'; import { useMessages } from '@/components/hooks'; import { EventProperties } from './EventProperties'; import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls'; @@ -22,29 +21,28 @@ export function EventsPage({ websiteId }) { return ( - - - - - - - - setTab(value)}> {formatMessage(labels.activity)} + {formatMessage(labels.chart)} {formatMessage(labels.properties)} + + + + + + diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx index 03e5759a..b3c2a960 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx @@ -1,51 +1,93 @@ -import { Grid, DataColumn, DataTable } from '@umami/react-zen'; +import { useMemo, useState } from 'react'; +import { Select, ListItem, Grid } from '@umami/react-zen'; import { + useMessages, useSessionDataPropertiesQuery, useSessionDataValuesQuery, - useMessages, } from '@/components/hooks'; import { LoadingPanel } from '@/components/common/LoadingPanel'; import { PieChart } from '@/components/charts/PieChart'; -import { useState } from 'react'; import { CHART_COLORS } from '@/lib/constants'; +import { ListTable } from '@/components/metrics/ListTable'; export function SessionProperties({ websiteId }: { websiteId: string }) { const [propertyName, setPropertyName] = useState(''); const { formatMessage, labels } = useMessages(); const { data, isLoading, isFetching, error } = useSessionDataPropertiesQuery(websiteId); - const { data: values } = useSessionDataValuesQuery(websiteId, propertyName); - const chartData = - propertyName && values - ? { - labels: values.map(({ value }) => value), - datasets: [ - { - data: values.map(({ total }) => total), - backgroundColor: CHART_COLORS, - borderWidth: 0, - }, - ], - } - : null; + + const properties: string[] = data?.map(e => e.propertyName); return ( - - - - - {(row: any) => ( -
setPropertyName(row.propertyName)}>{row.propertyName}
- )} -
- -
- {propertyName && ( -
-
{propertyName}
- -
- )} + + + + {propertyName && } ); } + +const SessionValues = ({ websiteId, propertyName }) => { + const { data, isLoading, isFetching, error } = useSessionDataValuesQuery(websiteId, propertyName); + + const propertySum = useMemo(() => { + return data?.reduce((sum, { total }) => sum + total, 0) ?? 0; + }, [data]); + + const chartData = useMemo(() => { + if (!propertyName || !data) return null; + return { + labels: data.map(({ value }) => value), + datasets: [ + { + data: data.map(({ total }) => total), + backgroundColor: CHART_COLORS, + borderWidth: 0, + }, + ], + }; + }, [propertyName, data]); + + const tableData = useMemo(() => { + if (!propertyName || !data || propertySum === 0) return []; + return data.map(({ value, total }) => ({ + x: value, + y: total, + z: 100 * (total / propertySum), + })); + }, [propertyName, data, propertySum]); + + return ( + + + {data && } + + + + ); +}; diff --git a/src/components/common/PageBody.tsx b/src/components/common/PageBody.tsx index 638ff610..0733a10d 100644 --- a/src/components/common/PageBody.tsx +++ b/src/components/common/PageBody.tsx @@ -1,6 +1,6 @@ 'use client'; import { ReactNode } from 'react'; -import { AlertBanner, Loading, Column } from '@umami/react-zen'; +import { AlertBanner, Loading, Column, ColumnProps } from '@umami/react-zen'; import { useMessages } from '@/components/hooks'; export function PageBody({ @@ -14,7 +14,7 @@ export function PageBody({ error?: unknown; isLoading?: boolean; children?: ReactNode; -}) { +} & ColumnProps) { const { formatMessage, messages } = useMessages(); if (error) { diff --git a/src/components/hooks/useFields.ts b/src/components/hooks/useFields.ts index f48b2dda..d1f1c14f 100644 --- a/src/components/hooks/useFields.ts +++ b/src/components/hooks/useFields.ts @@ -7,7 +7,6 @@ export function useFields() { { name: 'path', type: 'string', label: formatMessage(labels.path) }, // { name: 'cohort', type: 'string', label: formatMessage(labels.cohort) }, // { name: 'segment', type: 'string', label: formatMessage(labels.segment) }, - { name: 'url', type: 'string', label: formatMessage(labels.url) }, { name: 'title', type: 'string', label: formatMessage(labels.pageTitle) }, { name: 'referrer', type: 'string', label: formatMessage(labels.referrer) }, //{ name: 'query', type: 'string', label: formatMessage(labels.query) }, diff --git a/src/components/messages.ts b/src/components/messages.ts index 7f1a3b89..1ebc2939 100644 --- a/src/components/messages.ts +++ b/src/components/messages.ts @@ -338,6 +338,9 @@ export const labels = defineMessages({ location: { id: 'label.location', defaultMessage: 'Location' }, chart: { id: 'label.chart', defaultMessage: 'Chart' }, table: { id: 'label.table', defaultMessage: 'Table' }, + core: { id: 'label.core', defaultMessage: 'Core' }, + behavior: { id: 'label.behavior', defaultMessage: 'Behavior' }, + growth: { id: 'label.growth', defaultMessage: 'Growth' }, }); export const messages = defineMessages({ diff --git a/src/queries/sql/sessions/getSessionDataValues.ts b/src/queries/sql/sessions/getSessionDataValues.ts index 57792136..682bfe4f 100644 --- a/src/queries/sql/sessions/getSessionDataValues.ts +++ b/src/queries/sql/sessions/getSessionDataValues.ts @@ -17,7 +17,7 @@ async function relationalQuery( filters: QueryFilters & { propertyName?: string }, ) { const { rawQuery, parseFilters, getDateSQL } = prisma; - const { filterQuery, cohortQuery, queryParams } = parseFilters(filters); + const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId }); return rawQuery( ` @@ -49,7 +49,7 @@ async function clickhouseQuery( filters: QueryFilters & { propertyName?: string }, ): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, cohortQuery, queryParams } = parseFilters(filters); + const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId }); return rawQuery( ` From 876f4c883e87f698a88e6ebad6b5d08843052520 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 18 Jul 2025 00:22:06 -0700 Subject: [PATCH 135/399] Updated layout. Fixed properties rendering. --- package.json | 2 +- pnpm-lock.yaml | 10 +-- src/app/(main)/App.tsx | 16 +--- src/app/(main)/SideNav.tsx | 77 +++++++++---------- src/app/(main)/TopNav.tsx | 27 +++++-- src/app/(main)/settings/SettingsLayout.tsx | 9 +-- .../websites/[websiteId]/WebsiteHeader.tsx | 2 +- .../websites/[websiteId]/WebsiteLayout.tsx | 18 ++--- .../websites/[websiteId]/WebsiteNav.tsx | 62 +++++++++------ .../[websiteId]/events/EventProperties.tsx | 70 +++++++++-------- .../sessions/SessionProperties.tsx | 40 +++++----- src/components/common/Empty.tsx | 1 + src/components/common/PageHeader.tsx | 6 +- src/components/icons.ts | 1 + src/components/input/PanelButton.tsx | 14 ++++ src/components/input/TeamsButton.tsx | 26 +++---- src/components/input/WebsiteSelect.tsx | 7 +- src/components/messages.ts | 2 +- 18 files changed, 214 insertions(+), 176 deletions(-) create mode 100644 src/components/input/PanelButton.tsx diff --git a/package.json b/package.json index 3726a638..c1784e5b 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "@react-spring/web": "^9.7.3", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.80.10", - "@umami/react-zen": "^0.148.0", + "@umami/react-zen": "^0.150.0", "@umami/redis-client": "^0.27.0", "bcryptjs": "^2.4.3", "chalk": "^4.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 39232881..1ce41ec3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^5.80.10 version: 5.80.10(react@19.1.0) '@umami/react-zen': - specifier: ^0.148.0 - version: 0.148.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) + specifier: ^0.150.0 + version: 0.150.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) '@umami/redis-client': specifier: ^0.27.0 version: 0.27.0 @@ -2553,8 +2553,8 @@ packages: resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@umami/react-zen@0.148.0': - resolution: {integrity: sha512-4bI8wBgqep6bYNsnhQ87lSAYqiKLj/9o1emFfIot0NIxKd2jsmgEwGrymxDjmunXK4OwRs8ukOYvzuH3WbieGA==} + '@umami/react-zen@0.150.0': + resolution: {integrity: sha512-ogtdNm7jg7BnzWnQtchOAE1eE36EuxRLZaoalPLm8VrK4eQweqnbRFw+ddeAA12xI0hPP8gKOxOJDhH9pJpVVg==} '@umami/redis-client@0.27.0': resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==} @@ -9739,7 +9739,7 @@ snapshots: '@typescript-eslint/types': 8.34.1 eslint-visitor-keys: 4.2.1 - '@umami/react-zen@0.148.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': + '@umami/react-zen@0.150.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': dependencies: '@fontsource/jetbrains-mono': 5.2.6 '@internationalized/date': 3.8.2 diff --git a/src/app/(main)/App.tsx b/src/app/(main)/App.tsx index ecff5023..53d305fe 100644 --- a/src/app/(main)/App.tsx +++ b/src/app/(main)/App.tsx @@ -1,5 +1,5 @@ 'use client'; -import { Grid, Loading, Column, Row } from '@umami/react-zen'; +import { Grid, Loading, Column } from '@umami/react-zen'; import Script from 'next/script'; import { usePathname } from 'next/navigation'; import { UpdateNotice } from './UpdateNotice'; @@ -30,20 +30,12 @@ export function App({ children }) { } return ( - - + + - + - - {children} diff --git a/src/app/(main)/SideNav.tsx b/src/app/(main)/SideNav.tsx index 12b0d4ba..4cfe78a7 100644 --- a/src/app/(main)/SideNav.tsx +++ b/src/app/(main)/SideNav.tsx @@ -1,12 +1,11 @@ import Link from 'next/link'; import { Sidebar, - SidebarHeader, SidebarSection, SidebarItem, - Button, - Icon, + SidebarHeader, Row, + SidebarProps, } from '@umami/react-zen'; import { Globe, @@ -16,14 +15,14 @@ import { Grid2X2, Settings, LockKeyhole, - PanelLeft, } from '@/components/icons'; import { useMessages, useNavigation, useGlobalState } from '@/components/hooks'; +import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav'; -export function SideNav(props: any) { +export function SideNav(props: SidebarProps) { const { formatMessage, labels } = useMessages(); - const { pathname, renderUrl } = useNavigation(); - const [isCollapsed, setCollapsed] = useGlobalState('sidenav-collapsed'); + const { pathname, renderUrl, websiteId } = useNavigation(); + const [isCollapsed] = useGlobalState('sidenav-collapsed'); const links = [ { @@ -68,37 +67,37 @@ export function SideNav(props: any) { ]; return ( - - - } /> - - - {links.map(({ id, path, label, icon }) => { - return ( - - - - ); - })} - - - {bottomLinks.map(({ id, path, label, icon }) => { - return ( - - - - ); - })} - - - - - - - + + + + } /> + + + {links.map(({ id, path, label, icon }) => { + return ( + + + + ); + })} + + + {bottomLinks.map(({ id, path, label, icon }) => { + return ( + + + + ); + })} + + + {websiteId && } + ); } diff --git a/src/app/(main)/TopNav.tsx b/src/app/(main)/TopNav.tsx index db1eefdb..ff2b8f54 100644 --- a/src/app/(main)/TopNav.tsx +++ b/src/app/(main)/TopNav.tsx @@ -5,6 +5,7 @@ import { TeamsButton } from '@/components/input/TeamsButton'; import { WebsiteSelect } from '@/components/input/WebsiteSelect'; import { Slash } from '@/components/icons'; import { useNavigation } from '@/components/hooks'; +import { PanelButton } from '@/components/input/PanelButton'; export function TopNav() { const { teamId, websiteId, pathname } = useNavigation(); @@ -14,21 +15,27 @@ export function TopNav() { + + {websiteId && !isSettings && ( <> - - - - + + )} @@ -41,3 +48,11 @@ export function TopNav() { ); } + +const Seperator = () => { + return ( + + + + ); +}; diff --git a/src/app/(main)/settings/SettingsLayout.tsx b/src/app/(main)/settings/SettingsLayout.tsx index 1f5e3439..4a9a01cf 100644 --- a/src/app/(main)/settings/SettingsLayout.tsx +++ b/src/app/(main)/settings/SettingsLayout.tsx @@ -1,14 +1,13 @@ 'use client'; import { ReactNode } from 'react'; import { Grid, Column } from '@umami/react-zen'; -import { useLoginQuery, useMessages, useNavigation } from '@/components/hooks'; +import { useMessages, useNavigation } from '@/components/hooks'; import { SideMenu } from '@/components/common/SideMenu'; import { PageHeader } from '@/components/common/PageHeader'; import { Panel } from '@/components/common/Panel'; import { PageBody } from '@/components/common/PageBody'; export function SettingsLayout({ children }: { children: ReactNode }) { - const { user } = useLoginQuery(); const { formatMessage, labels } = useMessages(); const { pathname } = useNavigation(); @@ -23,13 +22,13 @@ export function SettingsLayout({ children }: { children: ReactNode }) { label: formatMessage(labels.profile), url: '/settings/profile', }, - { id: 'teams', label: formatMessage(labels.teams), url: '/settings/teams' }, - user.isAdmin && { + { id: 'websites', label: formatMessage(labels.websites), url: '/settings/websites', }, - ].filter(n => n); + { id: 'teams', label: formatMessage(labels.teams), url: '/settings/teams' }, + ]; const value = items.find(({ url }) => pathname.includes(url))?.id; diff --git a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx index 7d8d0f4a..ae2cf1bb 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx @@ -12,7 +12,7 @@ export function WebsiteHeader() { const website = useWebsite(); return ( - }> + } marginBottom="3"> diff --git a/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx b/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx index 3c751ae1..14374904 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx @@ -1,25 +1,17 @@ 'use client'; import { ReactNode } from 'react'; -import { Column, Grid } from '@umami/react-zen'; +import { Column } from '@umami/react-zen'; import { WebsiteProvider } from './WebsiteProvider'; import { PageBody } from '@/components/common/PageBody'; import { WebsiteHeader } from './WebsiteHeader'; -import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav'; export function WebsiteLayout({ websiteId, children }: { websiteId: string; children: ReactNode }) { return ( - - - - - - - - {children} - - - + + + {children} + ); } diff --git a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx index d9b1345d..37411c0a 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx @@ -1,4 +1,4 @@ -import { Icon, Text, Row, NavMenu, NavMenuItem, NavMenuGroup } from '@umami/react-zen'; +import { Icon, Text, Row, NavMenu, NavMenuItem, NavMenuGroup, Column } from '@umami/react-zen'; import { Eye, Lightning, @@ -12,6 +12,8 @@ import { Tag, Money, Network, + UserPlus, + ChartPie, } from '@/components/icons'; import { useMessages, useNavigation } from '@/components/hooks'; import Link from 'next/link'; @@ -22,7 +24,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) { const links = [ { - label: formatMessage(labels.core), + label: formatMessage(labels.traffic), items: [ { id: 'overview', @@ -88,6 +90,18 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) { icon: , path: '/breakdown', }, + { + id: 'segments', + label: formatMessage(labels.segments), + icon: , + path: '/segments', + }, + { + id: 'cohorts', + label: formatMessage(labels.cohorts), + icon: , + path: '/cohorts', + }, ], }, { @@ -120,27 +134,29 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) { 'overview'; return ( - - {links.map(({ label, items }) => { - return ( - - {items.map(({ id, label, icon, path }) => { - const isSelected = selected === id; + + + {links.map(({ label, items }) => { + return ( + + {items.map(({ id, label, icon, path }) => { + const isSelected = selected === id; - return ( - - - - {icon} - {label} - - - - ); - })} - - ); - })} - + return ( + + + + {icon} + {label} + + + + ); + })} + + ); + })} + + ); } diff --git a/src/app/(main)/websites/[websiteId]/events/EventProperties.tsx b/src/app/(main)/websites/[websiteId]/events/EventProperties.tsx index 3ed887c7..25e65405 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventProperties.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventProperties.tsx @@ -28,41 +28,43 @@ export function EventProperties({ websiteId }: { websiteId: string }) { return ( - - - - - {propertyName && ( + {data && ( + + + + + )} + {eventName && propertyName && ( )} @@ -113,10 +115,12 @@ const EventValues = ({ websiteId, eventName, propertyName }) => { minHeight="300px" gap="6" > - - {values && } - - + {values && ( + + + + + )}
); }; diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx index b3c2a960..d60713d9 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx @@ -26,20 +26,22 @@ export function SessionProperties({ websiteId }: { websiteId: string }) { minHeight="300px" gap="6" > - - - + {data && ( + + + + )} {propertyName && }
); @@ -84,10 +86,12 @@ const SessionValues = ({ websiteId, propertyName }) => { minHeight="300px" gap="6" > - - {data && } - - + {data && ( + + + + + )} ); }; diff --git a/src/components/common/Empty.tsx b/src/components/common/Empty.tsx index 8a20be3a..8bd8d82d 100644 --- a/src/components/common/Empty.tsx +++ b/src/components/common/Empty.tsx @@ -16,6 +16,7 @@ export function Empty({ message }: EmptyProps) { width="100%" height="100%" minHeight="70px" + flexGrow={1} > {message || formatMessage(messages.noDataAvailable)} diff --git a/src/components/common/PageHeader.tsx b/src/components/common/PageHeader.tsx index 26cf3c54..9f3365ad 100644 --- a/src/components/common/PageHeader.tsx +++ b/src/components/common/PageHeader.tsx @@ -1,5 +1,5 @@ import { ReactNode } from 'react'; -import { Heading, Icon, Row, Text } from '@umami/react-zen'; +import { Heading, Icon, Row, RowProps, Text } from '@umami/react-zen'; export function PageHeader({ title, @@ -7,6 +7,7 @@ export function PageHeader({ icon, showBorder = true, children, + ...props }: { title: string; description?: string; @@ -15,7 +16,7 @@ export function PageHeader({ allowEdit?: boolean; className?: string; children?: ReactNode; -}) { +} & RowProps) { return ( {icon && {icon}} diff --git a/src/components/icons.ts b/src/components/icons.ts index c566e4b3..0f7e3a0f 100644 --- a/src/components/icons.ts +++ b/src/components/icons.ts @@ -45,6 +45,7 @@ export { Upload, User, Users, + UserPlus, X as Close, } from 'lucide-react'; export * from '@/components/svg'; diff --git a/src/components/input/PanelButton.tsx b/src/components/input/PanelButton.tsx new file mode 100644 index 00000000..fe6c8b66 --- /dev/null +++ b/src/components/input/PanelButton.tsx @@ -0,0 +1,14 @@ +import { Button, Icon } from '@umami/react-zen'; +import { PanelLeft } from '@/components/icons'; +import { useGlobalState } from '@/components/hooks'; + +export function PanelButton() { + const [isCollapsed, setIsCollapsed] = useGlobalState('sidenav-collapsed'); + return ( + + ); +} diff --git a/src/components/input/TeamsButton.tsx b/src/components/input/TeamsButton.tsx index 5b5d6a9f..a0048909 100644 --- a/src/components/input/TeamsButton.tsx +++ b/src/components/input/TeamsButton.tsx @@ -16,13 +16,7 @@ import { import { useLoginQuery, useMessages, useUserTeamsQuery, useNavigation } from '@/components/hooks'; import { Chevron, User, Users } from '@/components/icons'; -export function TeamsButton({ - className, - showText = true, -}: { - className?: string; - showText?: boolean; -}) { +export function TeamsButton({ showText = true }: { showText?: boolean }) { const { user } = useLoginQuery(); const { formatMessage, labels } = useMessages(); const { data } = useUserTeamsQuery(user.id); @@ -41,13 +35,17 @@ export function TeamsButton({ return ( - diff --git a/src/components/input/WebsiteSelect.tsx b/src/components/input/WebsiteSelect.tsx index 11c50718..3b5bd669 100644 --- a/src/components/input/WebsiteSelect.tsx +++ b/src/components/input/WebsiteSelect.tsx @@ -1,16 +1,17 @@ import { useState } from 'react'; import { Select, SelectProps, ListItem } from '@umami/react-zen'; import { useUserWebsitesQuery, useWebsiteQuery, useNavigation } from '@/components/hooks'; +import { ButtonProps } from 'react-basics'; export function WebsiteSelect({ websiteId, teamId, - variant, + buttonProps, ...props }: { websiteId?: string; teamId?: string; - variant?: 'primary' | 'outline' | 'quiet' | 'danger' | 'zero'; + buttonProps?: ButtonProps; } & SelectProps) { const { router, renderUrl } = useNavigation(); const [search, setSearch] = useState(''); @@ -32,7 +33,7 @@ export function WebsiteSelect({ items={data?.['data'] || []} value={websiteId} isLoading={isLoading} - buttonProps={{ variant }} + buttonProps={buttonProps} allowSearch={true} searchValue={search} onSearch={handleSearch} diff --git a/src/components/messages.ts b/src/components/messages.ts index 1ebc2939..d6d5a87a 100644 --- a/src/components/messages.ts +++ b/src/components/messages.ts @@ -338,7 +338,7 @@ export const labels = defineMessages({ location: { id: 'label.location', defaultMessage: 'Location' }, chart: { id: 'label.chart', defaultMessage: 'Chart' }, table: { id: 'label.table', defaultMessage: 'Table' }, - core: { id: 'label.core', defaultMessage: 'Core' }, + traffic: { id: 'label.traffic', defaultMessage: 'Traffic' }, behavior: { id: 'label.behavior', defaultMessage: 'Behavior' }, growth: { id: 'label.growth', defaultMessage: 'Growth' }, }); From 25f96f6b6bcebb2ea73e898f071c1f2774310be3 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sun, 20 Jul 2025 00:38:15 -0700 Subject: [PATCH 136/399] Fixed nav display. --- src/app/(main)/SideNav.tsx | 24 ++++++++-------- src/app/(main)/TopNav.tsx | 28 +++++++++---------- .../websites/[websiteId]/WebsiteNav.tsx | 2 +- src/components/input/PanelButton.tsx | 6 ++-- .../sql/pageviews/getPageviewMetrics.ts | 2 -- 5 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/app/(main)/SideNav.tsx b/src/app/(main)/SideNav.tsx index 4cfe78a7..d11d80d3 100644 --- a/src/app/(main)/SideNav.tsx +++ b/src/app/(main)/SideNav.tsx @@ -21,8 +21,9 @@ import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav'; export function SideNav(props: SidebarProps) { const { formatMessage, labels } = useMessages(); - const { pathname, renderUrl, websiteId } = useNavigation(); + const { pathname, renderUrl, websiteId, teamId } = useNavigation(); const [isCollapsed] = useGlobalState('sidenav-collapsed'); + const isWebsite = websiteId && !pathname.includes('/settings'); const links = [ { @@ -67,10 +68,10 @@ export function SideNav(props: SidebarProps) { ]; return ( - + - {bottomLinks.map(({ id, path, label, icon }) => { - return ( - - - - ); - })} + {!teamId && + bottomLinks.map(({ id, path, label, icon }) => { + return ( + + + + ); + })} - {websiteId && } + {isWebsite && } ); } diff --git a/src/app/(main)/TopNav.tsx b/src/app/(main)/TopNav.tsx index ff2b8f54..c537e278 100644 --- a/src/app/(main)/TopNav.tsx +++ b/src/app/(main)/TopNav.tsx @@ -9,7 +9,7 @@ import { PanelButton } from '@/components/input/PanelButton'; export function TopNav() { const { teamId, websiteId, pathname } = useNavigation(); - const isSettings = pathname.includes('/settings'); + const isWebsite = websiteId && !pathname.includes('/settings'); return ( - + - - - {websiteId && !isSettings && ( - <> - - - - )} - + + {isWebsite && ( + <> + + + + )} diff --git a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx index 37411c0a..dd551553 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx @@ -134,7 +134,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) { 'overview'; return ( - + {links.map(({ label, items }) => { return ( diff --git a/src/components/input/PanelButton.tsx b/src/components/input/PanelButton.tsx index fe6c8b66..04a9b01c 100644 --- a/src/components/input/PanelButton.tsx +++ b/src/components/input/PanelButton.tsx @@ -1,11 +1,11 @@ -import { Button, Icon } from '@umami/react-zen'; +import { Button, Icon, ButtonProps } from '@umami/react-zen'; import { PanelLeft } from '@/components/icons'; import { useGlobalState } from '@/components/hooks'; -export function PanelButton() { +export function PanelButton(props: ButtonProps) { const [isCollapsed, setIsCollapsed] = useGlobalState('sidenav-collapsed'); return ( - - {({ close }) => ( - - - - )} + {({ close }) => } diff --git a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx index dd551553..9ba78662 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx @@ -17,10 +17,11 @@ import { } from '@/components/icons'; import { useMessages, useNavigation } from '@/components/hooks'; import Link from 'next/link'; +import { WebsiteSelect } from '@/components/input/WebsiteSelect'; export function WebsiteNav({ websiteId }: { websiteId: string }) { const { formatMessage, labels } = useMessages(); - const { pathname, renderUrl } = useNavigation(); + const { pathname, renderUrl, teamId } = useNavigation(); const links = [ { @@ -135,7 +136,8 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) { return ( - + + {links.map(({ label, items }) => { return ( diff --git a/src/components/icons.ts b/src/components/icons.ts index 0f7e3a0f..95094acb 100644 --- a/src/components/icons.ts +++ b/src/components/icons.ts @@ -44,6 +44,7 @@ export { Trash, Upload, User, + CircleUserRound as UserCircle, Users, UserPlus, X as Close, diff --git a/src/components/input/ProfileButton.tsx b/src/components/input/ProfileButton.tsx index 17587f31..e30557f1 100644 --- a/src/components/input/ProfileButton.tsx +++ b/src/components/input/ProfileButton.tsx @@ -11,8 +11,8 @@ import { Text, } from '@umami/react-zen'; import { useRouter } from 'next/navigation'; -import { User, LogOut, CircleUserRound } from 'lucide-react'; import { useMessages, useLoginQuery } from '@/components/hooks'; +import { LogOut, Settings, UserCircle, LockKeyhole } from '@/components/icons'; export function ProfileButton() { const { formatMessage, labels } = useMessages(); @@ -21,31 +21,34 @@ export function ProfileButton() { const cloudMode = !!process.env.cloudMode; const handleSelect = (key: Key) => { - if (key === 'profile') { - router.push('/settings/profile'); - } - if (key === 'logout') { - router.push('/logout'); - } + router.push(`/${key}`); }; return ( - + - + - {formatMessage(labels.profile)} + {formatMessage(labels.settings)} + {user.isAdmin && ( + + + + + {formatMessage(labels.admin)} + + )} {!cloudMode && ( diff --git a/src/components/input/TeamsButton.tsx b/src/components/input/TeamsButton.tsx index a0048909..b5288968 100644 --- a/src/components/input/TeamsButton.tsx +++ b/src/components/input/TeamsButton.tsx @@ -3,7 +3,6 @@ import { useRouter } from 'next/navigation'; import { Text, Icon, - Button, Menu, MenuItem, MenuTrigger, @@ -12,6 +11,8 @@ import { Popover, Row, Box, + SidebarItem, + Pressable, } from '@umami/react-zen'; import { useLoginQuery, useMessages, useUserTeamsQuery, useNavigation } from '@/components/hooks'; import { Chevron, User, Users } from '@/components/icons'; @@ -35,19 +36,20 @@ export function TeamsButton({ showText = true }: { showText?: boolean }) { return ( - + + onClick(item)}> - + {text} From 2e69e574453ad02d01abf04134b4bbb601b388b3 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 24 Jul 2025 16:09:49 -0700 Subject: [PATCH 138/399] Support event type filtering. --- .../[websiteId]/events/EventsDataTable.tsx | 2 +- src/components/common/DataGrid.tsx | 18 ++++++---- .../hooks/queries/useWebsiteEventsQuery.ts | 7 +++- src/components/input/TeamsButton.tsx | 34 +++++++++++-------- src/components/metrics/EventsTable.tsx | 5 --- src/lib/constants.ts | 1 + src/lib/schema.ts | 1 + 7 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx b/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx index 22b0f679..d93c7d8c 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx @@ -14,7 +14,7 @@ export function EventsDataTable({ }) { const { formatMessage, labels } = useMessages(); const [view, setView] = useState('all'); - const query = useWebsiteEventsQuery(websiteId); + const query = useWebsiteEventsQuery(websiteId, { view }); const buttons = [ { diff --git a/src/components/common/DataGrid.tsx b/src/components/common/DataGrid.tsx index 1533e25f..e112a410 100644 --- a/src/components/common/DataGrid.tsx +++ b/src/components/common/DataGrid.tsx @@ -16,6 +16,7 @@ export interface DataGridProps { allowPaging?: boolean; autoFocus?: boolean; renderActions?: () => ReactNode; + renderEmpty?: () => ReactNode; children: ReactNode | ((data: any) => ReactNode); } @@ -26,12 +27,13 @@ export function DataGrid({ allowPaging = true, autoFocus, renderActions, + renderEmpty = () => , children, }: DataGridProps) { const { formatMessage, labels } = useMessages(); const { data, error, isLoading, isFetching } = query; const { router, updateParams, query: queryParams } = useNavigation(); - const [search, setSearch] = useState(queryParams?.saerch || data?.search || ''); + const [search, setSearch] = useState(queryParams?.search || data?.search || ''); const handleSearch = (value: string) => { if (value !== search) { @@ -47,13 +49,9 @@ export function DataGrid({ [search], ); - if (data?.data?.length === 0) { - return ; - } - return ( - {allowSearch && (data || search) && ( + {allowSearch && ( )} - + {data && ( <> {typeof children === 'function' ? children(data) : children} diff --git a/src/components/hooks/queries/useWebsiteEventsQuery.ts b/src/components/hooks/queries/useWebsiteEventsQuery.ts index 3406285a..6a21f6df 100644 --- a/src/components/hooks/queries/useWebsiteEventsQuery.ts +++ b/src/components/hooks/queries/useWebsiteEventsQuery.ts @@ -4,6 +4,11 @@ import { useDateParameters } from '../useDateParameters'; import { usePagedQuery } from '../usePagedQuery'; import { ReactQueryOptions } from '@/lib/types'; +const EVENT_TYPES = { + views: 1, + events: 2, +}; + export function useWebsiteEventsQuery( websiteId: string, params?: Record, @@ -20,7 +25,7 @@ export function useWebsiteEventsQuery( ...date, ...filters, ...pageParams, - ...params, + eventType: EVENT_TYPES[params.view], }), enabled: !!websiteId, ...options, diff --git a/src/components/input/TeamsButton.tsx b/src/components/input/TeamsButton.tsx index b5288968..d9fd5e08 100644 --- a/src/components/input/TeamsButton.tsx +++ b/src/components/input/TeamsButton.tsx @@ -37,18 +37,18 @@ export function TeamsButton({ showText = true }: { showText?: boolean }) { return ( - : } - > - + + : } + > {showText && ( )} - - + + @@ -60,20 +60,24 @@ export function TeamsButton({ showText = true }: { showText?: boolean }) { > - - - - {user.username} + + + + + {user.username} + {data?.data?.map(({ id, name }) => ( - - - - {name} + + + + + {name} + ))} diff --git a/src/components/metrics/EventsTable.tsx b/src/components/metrics/EventsTable.tsx index 2ee4dace..f0f5d495 100644 --- a/src/components/metrics/EventsTable.tsx +++ b/src/components/metrics/EventsTable.tsx @@ -8,10 +8,6 @@ export interface EventsTableProps extends MetricsTableProps { export function EventsTable({ onLabelClick, ...props }: EventsTableProps) { const { formatMessage, labels } = useMessages(); - const handleDataLoad = (data: any) => { - props.onDataLoad?.(data); - }; - const renderLabel = ({ x: label }) => { if (onLabelClick) { return ( @@ -30,7 +26,6 @@ export function EventsTable({ onLabelClick, ...props }: EventsTableProps) { title={formatMessage(labels.events)} type="event" metric={formatMessage(labels.actions)} - onDataLoad={handleDataLoad} renderLabel={renderLabel} allowDownload={false} /> diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 0dc964e9..b5350872 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -71,6 +71,7 @@ export const FILTER_COLUMNS = { language: 'language', event: 'event_name', tag: 'tag', + eventType: 'event_type', }; export const COLLECTION_TYPE = { diff --git a/src/lib/schema.ts b/src/lib/schema.ts index 2bcbb2bf..41931b7b 100644 --- a/src/lib/schema.ts +++ b/src/lib/schema.ts @@ -37,6 +37,7 @@ export const filterParams = { event: z.string().optional(), segment: z.string().optional(), cohort: z.string().optional(), + eventType: z.coerce.number().int().positive().optional(), }; export const searchParams = { From 2ad624ccc8befcaad256f2981eb136dd916d2354 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sun, 27 Jul 2025 02:08:19 -0700 Subject: [PATCH 139/399] Added segment filtering to filter form. --- .../[websiteId]/WebsiteFilterButton.tsx | 28 ++-- .../[websiteId]/events/EventsPage.tsx | 8 +- .../[websiteId]/events/EventsTable.tsx | 2 +- .../[websiteId]/sessions/SessionsPage.tsx | 14 +- src/components/common/FilterEditForm.tsx | 135 +++++++----------- src/components/hooks/index.ts | 1 + .../hooks/queries/useWebsiteSegementsQuery.ts | 21 +++ src/components/hooks/useFields.ts | 1 - src/components/hooks/useNavigation.ts | 7 +- src/components/input/FieldFilters.tsx | 74 ++++++++++ src/components/input/FilterBar.tsx | 93 +++++++----- src/components/input/SegmentFilters.tsx | 36 +++++ src/components/input/WebsiteDateFilter.tsx | 2 +- src/lib/prisma.ts | 66 ++------- src/lib/storage.ts | 6 +- 15 files changed, 301 insertions(+), 193 deletions(-) create mode 100644 src/components/hooks/queries/useWebsiteSegementsQuery.ts create mode 100644 src/components/input/FieldFilters.tsx create mode 100644 src/components/input/SegmentFilters.tsx diff --git a/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx b/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx index f745c7e0..cf1cae24 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx @@ -13,19 +13,26 @@ export function WebsiteFilterButton({ showText?: boolean; }) { const { formatMessage, labels } = useMessages(); - const { updateParams, router } = useNavigation(); + const { + replaceParams, + router, + query: { segment }, + } = useNavigation(); const { filters } = useFilters(); - const handleChange = (filters: any[]) => { - const params = filters.reduce((obj, filter) => { - const { name, operator, value } = filter; + const handleChange = ({ filters, segment }) => { + const params = filters.reduce( + (obj: { [x: string]: string }, filter: { name: any; operator: any; value: any }) => { + const { name, operator, value } = filter; - obj[name] = `${operator}.${value}`; + obj[name] = `${operator}.${value}`; - return obj; - }, {}); + return obj; + }, + {}, + ); - const url = updateParams(params); + const url = replaceParams({ ...params, segment: segment?.id }); router.push(url); }; @@ -39,12 +46,13 @@ export function WebsiteFilterButton({ {showText && {formatMessage(labels.filter)}} - + {({ close }) => { return ( diff --git a/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx b/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx index 6af76a91..14a90c9f 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx @@ -14,7 +14,7 @@ const KEY_NAME = 'umami.events.tab'; export function EventsPage({ websiteId }) { const [label, setLabel] = useState(null); - const [tab, setTab] = useState(getItem(KEY_NAME) || 'activity'); + const [tab, setTab] = useState(getItem(KEY_NAME) || 'chart'); const { formatMessage, labels } = useMessages(); const handleLabelClick = (value: string) => { @@ -32,8 +32,8 @@ export function EventsPage({ websiteId }) { handleSelect(key)}> - {formatMessage(labels.activity)} {formatMessage(labels.chart)} + {formatMessage(labels.activity)} {formatMessage(labels.properties)} @@ -41,7 +41,9 @@ export function EventsPage({ websiteId }) { - + + + )} - + {(row: any) => ( {formatValue(row.browser, 'browser')} diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx index 7e18bbed..68eef29c 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx @@ -1,21 +1,29 @@ 'use client'; -import { useState } from 'react'; +import { Key, useState } from 'react'; import { TabList, Tab, Tabs, TabPanel, Column } from '@umami/react-zen'; import { SessionsDataTable } from './SessionsDataTable'; import { SessionProperties } from './SessionProperties'; import { useMessages } from '@/components/hooks'; import { Panel } from '@/components/common/Panel'; import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls'; +import { getItem, setItem } from '@/lib/storage'; + +const KEY_NAME = 'umami.sessions.tab'; export function SessionsPage({ websiteId }) { - const [tab, setTab] = useState('activity'); + const [tab, setTab] = useState(getItem(KEY_NAME) || 'activity'); const { formatMessage, labels } = useMessages(); + const handleSelect = (value: Key) => { + setItem(KEY_NAME, value); + setTab(value); + }; + return ( - setTab(value)}> + {formatMessage(labels.activity)} {formatMessage(labels.properties)} diff --git a/src/components/common/FilterEditForm.tsx b/src/components/common/FilterEditForm.tsx index 850bd91d..80574c5e 100644 --- a/src/components/common/FilterEditForm.tsx +++ b/src/components/common/FilterEditForm.tsx @@ -1,99 +1,68 @@ -import { useState, Key } from 'react'; -import { Grid, Row, Column, Label, List, ListItem, Button, Heading } from '@umami/react-zen'; -import { useDateRange, useFilters, useMessages } from '@/components/hooks'; -import { FilterRecord } from '@/components/common/FilterRecord'; -import { Empty } from '@/components/common/Empty'; +import { useState } from 'react'; +import { Column, Tabs, TabList, Tab, TabPanel, Row, Button } from '@umami/react-zen'; +import { useMessages } from '@/components/hooks'; +import { FieldFilters } from '@/components/input/FieldFilters'; +import { SegmentFilters } from '@/components/input/SegmentFilters'; export interface FilterEditFormProps { websiteId?: string; - data: any[]; - onChange?: (filters: { name: string; type: string; operator: string; value: string }[]) => void; + filters: any[]; + segmentId?: string; + onChange?: (params: { filters: any[]; segment: any }) => void; onClose?: () => void; } -export function FilterEditForm({ websiteId, data = [], onChange, onClose }: FilterEditFormProps) { - const { formatMessage, labels, messages } = useMessages(); - const [filters, setFilters] = useState(data); - const { fields } = useFilters(); - const { - dateRange: { startDate, endDate }, - } = useDateRange(websiteId); +export function FilterEditForm({ + websiteId, + filters = [], + segmentId, + onChange, + onClose, +}: FilterEditFormProps) { + const { formatMessage, labels } = useMessages(); + const [currentFilters, setCurrentFilters] = useState(filters); + const [currentSegment, setCurrentSegment] = useState(null); - const updateFilter = (name: string, props: Record) => { - setFilters(filters => - filters.map(filter => (filter.name === name ? { ...filter, ...props } : filter)), - ); + const handleReset = () => { + setCurrentFilters([]); }; - const handleAdd = (name: Key) => { - setFilters(filters.concat({ name, operator: 'eq', value: '' })); - }; - - const handleChange = (name: string, value: Key) => { - updateFilter(name, { value }); - }; - - const handleSelect = (name: string, operator: Key) => { - updateFilter(name, { operator }); - }; - - const handleRemove = (name: string) => { - setFilters(filters.filter(filter => filter.name !== name)); - }; - - const handleApply = () => { - onChange?.(filters.filter(f => f.value)); + const handleSave = () => { + onChange?.({ filters: currentFilters.filter(f => f.value), segment: currentSegment }); onClose?.(); }; + const handleSegmentChange = (segment?: { id: string }) => { + setCurrentSegment(segment); + }; + return ( - - - {formatMessage(labels.filters)} + + + + {formatMessage(labels.fields)} + {formatMessage(labels.segments)} + + + + + + + + + + + + + + - - - - {fields.map((field: any) => { - const isDisabled = filters.find(({ name }) => name === field.name); - return ( - - {field.label} - - ); - })} - - - - {filters.map(filter => { - return ( - - ); - })} - {!filters.length && } - - - - - - + ); } diff --git a/src/components/hooks/index.ts b/src/components/hooks/index.ts index d385196c..5c0d8d6b 100644 --- a/src/components/hooks/index.ts +++ b/src/components/hooks/index.ts @@ -26,6 +26,7 @@ export * from './queries/useTeamMembersQuery'; export * from './queries/useUserQuery'; export * from './queries/useUsersQuery'; export * from './queries/useWebsiteQuery'; +export * from './queries/useWebsiteSegementsQuery'; export * from './queries/useWebsitesQuery'; export * from './queries/useWebsiteEventsQuery'; export * from './queries/useWebsiteEventsSeriesQuery'; diff --git a/src/components/hooks/queries/useWebsiteSegementsQuery.ts b/src/components/hooks/queries/useWebsiteSegementsQuery.ts new file mode 100644 index 00000000..aecf1d52 --- /dev/null +++ b/src/components/hooks/queries/useWebsiteSegementsQuery.ts @@ -0,0 +1,21 @@ +import { useApi } from '../useApi'; +import { useModified } from '@/components/hooks'; +import { keepPreviousData } from '@tanstack/react-query'; +import { ReactQueryOptions } from '@/lib/types'; + +export function useWebsiteSegmentsQuery( + websiteId: string, + params?: Record, + options?: ReactQueryOptions, +) { + const { get, useQuery } = useApi(); + const { modified } = useModified(`website:${websiteId}`); + + return useQuery({ + queryKey: ['website:segments', { websiteId, modified, ...params }], + queryFn: () => get(`/websites/${websiteId}/segments`, { ...params }), + enabled: !!websiteId, + placeholderData: keepPreviousData, + ...options, + }); +} diff --git a/src/components/hooks/useFields.ts b/src/components/hooks/useFields.ts index d1f1c14f..3b78d94f 100644 --- a/src/components/hooks/useFields.ts +++ b/src/components/hooks/useFields.ts @@ -6,7 +6,6 @@ export function useFields() { const fields = [ { name: 'path', type: 'string', label: formatMessage(labels.path) }, // { name: 'cohort', type: 'string', label: formatMessage(labels.cohort) }, - // { name: 'segment', type: 'string', label: formatMessage(labels.segment) }, { name: 'title', type: 'string', label: formatMessage(labels.pageTitle) }, { name: 'referrer', type: 'string', label: formatMessage(labels.referrer) }, //{ name: 'query', type: 'string', label: formatMessage(labels.query) }, diff --git a/src/components/hooks/useNavigation.ts b/src/components/hooks/useNavigation.ts index 174f9879..4db2dfe9 100644 --- a/src/components/hooks/useNavigation.ts +++ b/src/components/hooks/useNavigation.ts @@ -11,7 +11,11 @@ export function useNavigation() { const [queryParams, setQueryParams] = useState(Object.fromEntries(searchParams)); const updateParams = (params?: Record) => { - return !params ? pathname : buildUrl(pathname, { ...queryParams, ...params }); + return buildUrl(pathname, { ...queryParams, ...params }); + }; + + const replaceParams = (params?: Record) => { + return buildUrl(pathname, params); }; useEffect(() => { @@ -33,6 +37,7 @@ export function useNavigation() { teamId, websiteId, updateParams, + replaceParams, renderUrl, }; } diff --git a/src/components/input/FieldFilters.tsx b/src/components/input/FieldFilters.tsx new file mode 100644 index 00000000..d37f8850 --- /dev/null +++ b/src/components/input/FieldFilters.tsx @@ -0,0 +1,74 @@ +import { Key } from 'react'; +import { Grid, Column, List, ListItem } from '@umami/react-zen'; +import { useDateRange, useFields, useMessages } from '@/components/hooks'; +import { FilterRecord } from '@/components/common/FilterRecord'; +import { Empty } from '@/components/common/Empty'; + +export interface FieldFiltersProps { + websiteId: string; + filters: { name: string; operator: string; value: string }[]; + onSave?: (data: any) => void; +} + +export function FieldFilters({ websiteId, filters, onSave }: FieldFiltersProps) { + const { formatMessage, messages } = useMessages(); + const { fields } = useFields(); + const { + dateRange: { startDate, endDate }, + } = useDateRange(websiteId); + + const updateFilter = (name: string, props: Record) => { + onSave(filters.map(filter => (filter.name === name ? { ...filter, ...props } : filter))); + }; + + const handleAdd = (name: Key) => { + onSave(filters.concat({ name: name.toString(), operator: 'eq', value: '' })); + }; + + const handleChange = (name: string, value: Key) => { + updateFilter(name, { value }); + }; + + const handleSelect = (name: string, operator: Key) => { + updateFilter(name, { operator }); + }; + + const handleRemove = (name: string) => { + onSave(filters.filter(filter => filter.name !== name)); + }; + + return ( + + + + {fields.map((field: any) => { + const isDisabled = !!filters.find(({ name }) => name === field.name); + return ( + + {field.label} + + ); + })} + + + + {filters.map(filter => { + return ( + + ); + })} + {!filters.length && } + + + ); +} diff --git a/src/components/input/FilterBar.tsx b/src/components/input/FilterBar.tsx index 224b4c77..51409b26 100644 --- a/src/components/input/FilterBar.tsx +++ b/src/components/input/FilterBar.tsx @@ -1,4 +1,3 @@ -import { MouseEvent } from 'react'; import { Button, Icon, Text, Row, TooltipTrigger, Tooltip } from '@umami/react-zen'; import { useNavigation, useMessages, useFormat, useFilters } from '@/components/hooks'; import { Close } from '@/components/icons'; @@ -7,57 +6,55 @@ import { isSearchOperator } from '@/lib/params'; export function FilterBar() { const { formatMessage, labels } = useMessages(); const { formatValue } = useFormat(); - const { router, updateParams } = useNavigation(); + const { + router, + updateParams, + replaceParams, + query: { segment }, + } = useNavigation(); const { filters, operatorLabels } = useFilters(); - const handleCloseFilter = (param: string, e: MouseEvent) => { - e.stopPropagation(); + const handleCloseFilter = (param: string) => { router.push(updateParams({ [param]: undefined })); }; const handleResetFilter = () => { - router.push(updateParams()); + router.push(replaceParams()); }; - if (!filters.length) { + const handleSegmentRemove = () => { + router.push(updateParams({ segment: undefined })); + }; + + if (!filters.length && !segment) { return null; } return ( - {Object.keys(filters).map(key => { - const filter = filters[key]; + {segment && ( + + )} + {filters.map(filter => { const { name, label, operator, value } = filter; const paramValue = isSearchOperator(operator) ? value : formatValue(value, name); return ( - - - - - {label} - - {operatorLabels[operator]} - - {paramValue} - - - handleCloseFilter(name, e)} size="xs"> - - - - + name={name} + label={label} + operator={operatorLabels[operator]} + value={paramValue} + onRemove={name => handleCloseFilter(name)} + /> ); })} @@ -74,3 +71,33 @@ export function FilterBar() { ); } + +const FilterItem = ({ name, label, operator, value, onRemove }) => { + return ( + + + + + {label} + + {operator} + + {value} + + + onRemove(name)} size="xs"> + + + + + ); +}; diff --git a/src/components/input/SegmentFilters.tsx b/src/components/input/SegmentFilters.tsx new file mode 100644 index 00000000..51690a01 --- /dev/null +++ b/src/components/input/SegmentFilters.tsx @@ -0,0 +1,36 @@ +import { useState } from 'react'; +import { List, Column, ListItem } from '@umami/react-zen'; +import { useWebsiteSegmentsQuery } from '@/components/hooks'; +import { LoadingPanel } from '@/components/common/LoadingPanel'; + +export interface SegmentFiltersProps { + websiteId: string; + segmentId: string; + onSave?: (data: any) => void; +} + +export function SegmentFilters({ websiteId, segmentId, onSave }: SegmentFiltersProps) { + const { data, isLoading } = useWebsiteSegmentsQuery(websiteId, { type: 'segment' }); + const [currentSegment, setCurrentSegment] = useState(segmentId); + + const handleSave = (id: string) => { + setCurrentSegment(id); + onSave?.(data.find(item => item.id === id)); + }; + + return ( + + + handleSave(id[0])}> + {data?.map(item => { + return ( + + {item.name} + + ); + })} + + + + ); +} diff --git a/src/components/input/WebsiteDateFilter.tsx b/src/components/input/WebsiteDateFilter.tsx index 4737517a..0bf74846 100644 --- a/src/components/input/WebsiteDateFilter.tsx +++ b/src/components/input/WebsiteDateFilter.tsx @@ -100,9 +100,9 @@ export function WebsiteDateFilter({ {compare ? : } {formatMessage(compare ? labels.cancel : labels.compareDates)} - )} + ); } diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index 813c844b..b8ad4984 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -2,7 +2,6 @@ import debug from 'debug'; import { PrismaClient } from '@prisma/client'; import { PrismaPg } from '@prisma/adapter-pg'; import { readReplicas } from '@prisma/extension-read-replicas'; -import { MYSQL, POSTGRESQL, getDatabaseType } from '@/lib/db'; import { SESSION_COLUMNS, OPERATORS, DEFAULT_PAGE_SIZE } from './constants'; import { QueryOptions, QueryFilters } from './types'; import { filtersToArray } from './params'; @@ -19,7 +18,7 @@ const PRISMA_LOG_OPTIONS = { ], }; -const POSTGRESQL_DATE_FORMATS = { +const DATE_FORMATS = { minute: 'YYYY-MM-DD HH24:MI:00', hour: 'YYYY-MM-DD HH24:00:00', day: 'YYYY-MM-DD HH24:00:00', @@ -28,47 +27,23 @@ const POSTGRESQL_DATE_FORMATS = { }; function getAddIntervalQuery(field: string, interval: string): string { - const db = getDatabaseType(); - - if (db === POSTGRESQL) { - return `${field} + interval '${interval}'`; - } - - if (db === MYSQL) { - return `DATE_ADD(${field}, interval ${interval})`; - } + return `${field} + interval '${interval}'`; } function getDayDiffQuery(field1: string, field2: string): string { - const db = getDatabaseType(); - - if (db === POSTGRESQL) { - return `${field1}::date - ${field2}::date`; - } - - if (db === MYSQL) { - return `DATEDIFF(${field1}, ${field2})`; - } + return `${field1}::date - ${field2}::date`; } function getCastColumnQuery(field: string, type: string): string { - const db = getDatabaseType(); - - if (db === POSTGRESQL) { - return `${field}::${type}`; - } - - if (db === MYSQL) { - return `${field}`; - } + return `${field}::${type}`; } function getDateSQL(field: string, unit: string, timezone?: string): string { if (timezone) { - return `to_char(date_trunc('${unit}', ${field} at time zone '${timezone}'), '${POSTGRESQL_DATE_FORMATS[unit]}')`; + return `to_char(date_trunc('${unit}', ${field} at time zone '${timezone}'), '${DATE_FORMATS[unit]}')`; } - return `to_char(date_trunc('${unit}', ${field}), '${POSTGRESQL_DATE_FORMATS[unit]}')`; + return `to_char(date_trunc('${unit}', ${field}), '${DATE_FORMATS[unit]}')`; } function getDateWeeklySQL(field: string, timezone?: string) { @@ -105,18 +80,15 @@ function mapFilter(column: string, operator: string, name: string, type: string } function mapCohortFilter(column: string, operator: string, value: string) { - const db = getDatabaseType(); - const like = db === POSTGRESQL ? 'ilike' : 'like'; - switch (operator) { case OPERATORS.equals: return `${column} = '${value}'`; case OPERATORS.notEquals: return `${column} != '${value}'`; case OPERATORS.contains: - return `${column} ${like} '${value}'`; + return `${column} ilike '${value}'`; case OPERATORS.doesNotContain: - return `${column} not ${like} '${value}'`; + return `${column} not ilike '${value}'`; default: return ''; } @@ -229,14 +201,8 @@ async function rawQuery(sql: string, data: object): Promise { log('QUERY:\n', sql); log('PARAMETERS:\n', data); } - - const db = getDatabaseType(); const params = []; - if (db !== POSTGRESQL && db !== MYSQL) { - return Promise.reject(new Error('Unknown database.')); - } - const query = sql?.replaceAll(/\{\{\s*(\w+)(::\w+)?\s*}}/g, (...args) => { const [, name, type] = args; @@ -244,7 +210,7 @@ async function rawQuery(sql: string, data: object): Promise { params.push(value); - return db === MYSQL ? '?' : `$${params.length}${type ?? ''}`; + return `$${params.length}${type ?? ''}`; }); return process.env.DATABASE_REPLICA_URL @@ -301,20 +267,9 @@ async function pagedRawQuery( return { data, count, page: +page, pageSize: size, orderBy }; } -function getQueryMode(): { mode?: 'default' | 'insensitive' } { - const db = getDatabaseType(); - - if (db === POSTGRESQL) { - return { mode: 'insensitive' }; - } - - return {}; -} - function getSearchParameters(query: string, filters: Record[]) { if (!query) return; - const mode = getQueryMode(); const parseFilter = (filter: Record) => { const [[key, value]] = Object.entries(filter); @@ -323,7 +278,7 @@ function getSearchParameters(query: string, filters: Record[]) { typeof value === 'string' ? { [value]: query, - ...mode, + mode: 'insensitive', } : parseFilter(value), }; @@ -404,7 +359,6 @@ export default { getSearchParameters, getTimestampDiffSQL, getSearchSQL, - getQueryMode, pagedQuery, pagedRawQuery, parseFilters, diff --git a/src/lib/storage.ts b/src/lib/storage.ts index f08a7f7a..fd19b3b6 100644 --- a/src/lib/storage.ts +++ b/src/lib/storage.ts @@ -9,7 +9,11 @@ export function getItem(key: string, session?: boolean): any { const value = (session ? sessionStorage : localStorage).getItem(key); if (value !== 'undefined' && value !== null) { - return JSON.parse(value); + try { + return JSON.parse(value); + } catch { + return null; + } } } } From 86e0fc22628965691a49812eaf180852e2ad6125 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Mon, 28 Jul 2025 17:13:13 -0700 Subject: [PATCH 140/399] convert clickhouse getChannels to SQL query --- .../api/websites/[websiteId]/metrics/route.ts | 95 ++----------------- src/queries/sql/getChannelMetrics.ts | 74 ++++++++++++--- 2 files changed, 68 insertions(+), 101 deletions(-) diff --git a/src/app/api/websites/[websiteId]/metrics/route.ts b/src/app/api/websites/[websiteId]/metrics/route.ts index 488f85fc..e1291836 100644 --- a/src/app/api/websites/[websiteId]/metrics/route.ts +++ b/src/app/api/websites/[websiteId]/metrics/route.ts @@ -1,27 +1,15 @@ -import { z } from 'zod'; -import thenby from 'thenby'; import { canViewWebsite } from '@/lib/auth'; +import { EVENT_COLUMNS, FILTER_COLUMNS, OPERATORS, SESSION_COLUMNS } from '@/lib/constants'; +import { getRequestDateRange, getRequestFilters, parseRequest } from '@/lib/request'; +import { badRequest, json, unauthorized } from '@/lib/response'; +import { filterParams } from '@/lib/schema'; import { - SESSION_COLUMNS, - EVENT_COLUMNS, - FILTER_COLUMNS, - OPERATORS, - SEARCH_DOMAINS, - SOCIAL_DOMAINS, - EMAIL_DOMAINS, - SHOPPING_DOMAINS, - VIDEO_DOMAINS, - PAID_AD_PARAMS, -} from '@/lib/constants'; -import { getRequestFilters, getRequestDateRange, parseRequest } from '@/lib/request'; -import { json, unauthorized, badRequest } from '@/lib/response'; -import { + getChannelMetrics, + getEventMetrics, getPageviewMetrics, getSessionMetrics, - getEventMetrics, - getChannelMetrics, } from '@/queries'; -import { filterParams } from '@/lib/schema'; +import { z } from 'zod'; export async function GET( request: Request, @@ -104,75 +92,8 @@ export async function GET( if (type === 'channel') { const data = await getChannelMetrics(websiteId, filters); - const channels = getChannels(data); - - return json( - Object.keys(channels) - .map(key => ({ x: key, y: channels[key] })) - .sort(thenby.firstBy('y', -1)), - ); + return json(data); } return badRequest(); } - -function getChannels(data: { domain: string; query: string; visitors: number }[]) { - const channels = { - direct: 0, - referral: 0, - affiliate: 0, - email: 0, - sms: 0, - organicSearch: 0, - organicSocial: 0, - organicShopping: 0, - organicVideo: 0, - paidAds: 0, - paidSearch: 0, - paidSocial: 0, - paidShopping: 0, - paidVideo: 0, - }; - - const match = (value: string) => { - return (str: string | RegExp) => { - return typeof str === 'string' ? value?.includes(str) : (str as RegExp).test(value); - }; - }; - - for (const { domain, query, visitors } of data) { - if (!domain && !query) { - channels.direct += Number(visitors); - } - - const prefix = /utm_medium=(.*cp.*|ppc|retargeting|paid.*)/.test(query) ? 'paid' : 'organic'; - - if (PAID_AD_PARAMS.some(match(query))) { - channels.paidAds += Number(visitors); - } else if (/utm_medium=(referral|app|link)/.test(query)) { - channels.referral += Number(visitors); - } else if (/utm_medium=affiliate/.test(query)) { - channels.affiliate += Number(visitors); - } else if (/utm_(source|medium)=sms/.test(query)) { - channels.sms += Number(visitors); - } else if (SEARCH_DOMAINS.some(match(domain)) || /utm_medium=organic/.test(query)) { - channels[`${prefix}Search`] += Number(visitors); - } else if ( - SOCIAL_DOMAINS.some(match(domain)) || - /utm_medium=(social|social-network|social-media|sm|social network|social media)/.test(query) - ) { - channels[`${prefix}Social`] += Number(visitors); - } else if (EMAIL_DOMAINS.some(match(domain)) || /utm_medium=(.*e[-_ ]?mail.*)/.test(query)) { - channels.email += Number(visitors); - } else if ( - SHOPPING_DOMAINS.some(match(domain)) || - /utm_campaign=(.*(([^a-df-z]|^)shop|shopping).*)/.test(query) - ) { - channels[`${prefix}Shopping`] += Number(visitors); - } else if (VIDEO_DOMAINS.some(match(domain)) || /utm_medium=(.*video.*)/.test(query)) { - channels[`${prefix}Video`] += Number(visitors); - } - } - - return channels; -} diff --git a/src/queries/sql/getChannelMetrics.ts b/src/queries/sql/getChannelMetrics.ts index 25f866d4..b6d6f90e 100644 --- a/src/queries/sql/getChannelMetrics.ts +++ b/src/queries/sql/getChannelMetrics.ts @@ -1,6 +1,15 @@ -import prisma from '@/lib/prisma'; import clickhouse from '@/lib/clickhouse'; -import { runQuery, CLICKHOUSE, PRISMA } from '@/lib/db'; +import { + EMAIL_DOMAINS, + EVENT_TYPE, + PAID_AD_PARAMS, + SEARCH_DOMAINS, + SHOPPING_DOMAINS, + SOCIAL_DOMAINS, + VIDEO_DOMAINS, +} from '@/lib/constants'; +import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; +import prisma from '@/lib/prisma'; import { QueryFilters } from '@/lib/types'; export async function getChannelMetrics(...args: [websiteId: string, filters?: QueryFilters]) { @@ -37,21 +46,58 @@ async function clickhouseQuery( filters: QueryFilters, ): Promise<{ x: string; y: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { params, filterQuery, cohortQuery, dateQuery } = await parseFilters(websiteId, filters); + const { params, filterQuery, cohortQuery } = await parseFilters(websiteId, { + ...filters, + eventType: EVENT_TYPE.pageView, + }); const sql = ` - select - referrer_domain as domain, - url_query as query, - uniq(session_id) as visitors - from website_event - ${cohortQuery} - where website_id = {websiteId:UUID} - ${filterQuery} - ${dateQuery} - group by 1, 2 - order by visitors desc + WITH channels as ( + select case when multiSearchAny(utm_medium, ['cp', 'ppc', 'retargeting', 'paid']) != 0 then 'paid' else 'organic' end prefix, + case + when referrer_domain = '' and url_query = '' then 'direct' + when multiSearchAny(url_query, [${toClickHouseStringArray( + PAID_AD_PARAMS, + )}]) != 0 then 'paidAds' + when multiSearchAny(utm_medium, ['referral', 'app','link']) != 0 then 'referral' + when position(utm_medium, 'affiliate') > 0 then 'affiliate' + when position(utm_medium, 'sms') > 0 or position(utm_source, 'sms') > 0 then 'sms' + when multiSearchAny(referrer_domain, [${toClickHouseStringArray( + SEARCH_DOMAINS, + )}]) != 0 or position(utm_medium, 'organic') > 0 then concat(prefix, 'Search') + when multiSearchAny(referrer_domain, [${toClickHouseStringArray( + SOCIAL_DOMAINS, + )}]) != 0 then concat(prefix, 'Social') + when multiSearchAny(referrer_domain, [${toClickHouseStringArray( + EMAIL_DOMAINS, + )}]) != 0 or position(utm_medium, 'mail') > 0 then 'email' + when multiSearchAny(referrer_domain, [${toClickHouseStringArray( + SHOPPING_DOMAINS, + )}]) != 0 or position(utm_medium, 'shop') > 0 then concat(prefix, 'Shopping') + when multiSearchAny(referrer_domain, [${toClickHouseStringArray( + VIDEO_DOMAINS, + )}]) != 0 or position(utm_medium, 'video') > 0 then concat(prefix, 'Video') + else '' end AS x, + count(distinct session_id) y + from website_event + ${cohortQuery} + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and event_type = {eventType:UInt32} + ${filterQuery} + group by 1, 2 + order by y desc) + + select x, sum(y) y + from channels + where x != '' + group by x + order by y desc; `; return rawQuery(sql, params); } + +function toClickHouseStringArray(arr: string[]): string { + return arr.map(p => `'${p.replace(/'/g, "\\'")}'`).join(', '); +} From fba7e12c3679319f9fcc204ff020cd12ca5ec4e7 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 31 Jul 2025 02:33:35 -0700 Subject: [PATCH 141/399] Updated segment handling. --- .../websites/[websiteId]/(reports)/page.tsx | 3 - .../[websiteId]/WebsiteFilterButton.tsx | 2 +- src/components/common/FilterEditForm.tsx | 9 +-- .../hooks/queries/useWebsiteMetricsQuery.ts | 3 - src/components/hooks/useFilterParameters.ts | 6 ++ src/components/input/SegmentFilters.tsx | 9 +-- src/lib/clickhouse.ts | 63 +++++-------------- src/lib/params.ts | 2 +- src/lib/prisma.ts | 4 +- src/lib/request.ts | 20 +++--- src/lib/schema.ts | 4 +- src/lib/types.ts | 14 ++++- src/queries/prisma/segment.ts | 10 +-- 13 files changed, 59 insertions(+), 90 deletions(-) delete mode 100644 src/app/(main)/websites/[websiteId]/(reports)/page.tsx diff --git a/src/app/(main)/websites/[websiteId]/(reports)/page.tsx b/src/app/(main)/websites/[websiteId]/(reports)/page.tsx deleted file mode 100644 index c9916b15..00000000 --- a/src/app/(main)/websites/[websiteId]/(reports)/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import GoalsPage from './goals/page'; - -export default GoalsPage; diff --git a/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx b/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx index cf1cae24..94022e87 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx @@ -32,7 +32,7 @@ export function WebsiteFilterButton({ {}, ); - const url = replaceParams({ ...params, segment: segment?.id }); + const url = replaceParams({ ...params, segment }); router.push(url); }; diff --git a/src/components/common/FilterEditForm.tsx b/src/components/common/FilterEditForm.tsx index 80574c5e..45c402d2 100644 --- a/src/components/common/FilterEditForm.tsx +++ b/src/components/common/FilterEditForm.tsx @@ -21,10 +21,11 @@ export function FilterEditForm({ }: FilterEditFormProps) { const { formatMessage, labels } = useMessages(); const [currentFilters, setCurrentFilters] = useState(filters); - const [currentSegment, setCurrentSegment] = useState(null); + const [currentSegment, setCurrentSegment] = useState(segmentId); const handleReset = () => { setCurrentFilters([]); + setCurrentSegment(null); }; const handleSave = () => { @@ -32,8 +33,8 @@ export function FilterEditForm({ onClose?.(); }; - const handleSegmentChange = (segment?: { id: string }) => { - setCurrentSegment(segment); + const handleSegmentChange = (id: string) => { + setCurrentSegment(id); }; return ( @@ -49,7 +50,7 @@ export function FilterEditForm({ diff --git a/src/components/hooks/queries/useWebsiteMetricsQuery.ts b/src/components/hooks/queries/useWebsiteMetricsQuery.ts index 17db2d92..f521798e 100644 --- a/src/components/hooks/queries/useWebsiteMetricsQuery.ts +++ b/src/components/hooks/queries/useWebsiteMetricsQuery.ts @@ -2,7 +2,6 @@ import { keepPreviousData } from '@tanstack/react-query'; import { useApi } from '../useApi'; import { useFilterParameters } from '../useFilterParameters'; import { useDateParameters } from '../useDateParameters'; -import { useSearchParams } from 'next/navigation'; import { ReactQueryOptions } from '@/lib/types'; export type WebsiteMetricsData = { @@ -18,7 +17,6 @@ export function useWebsiteMetricsQuery( const { get, useQuery } = useApi(); const date = useDateParameters(websiteId); const filters = useFilterParameters(); - const searchParams = useSearchParams(); return useQuery({ queryKey: [ @@ -34,7 +32,6 @@ export function useWebsiteMetricsQuery( get(`/websites/${websiteId}/metrics`, { ...date, ...filters, - [searchParams.get('view')]: undefined, ...params, }), enabled: !!websiteId, diff --git a/src/components/hooks/useFilterParameters.ts b/src/components/hooks/useFilterParameters.ts index 44c8896e..54032120 100644 --- a/src/components/hooks/useFilterParameters.ts +++ b/src/components/hooks/useFilterParameters.ts @@ -21,6 +21,8 @@ export function useFilterParameters() { page, pageSize, search, + segment, + cohort, }, } = useNavigation(); @@ -41,6 +43,8 @@ export function useFilterParameters() { tag, hostname, search, + segment, + cohort, }; }, [ path, @@ -60,5 +64,7 @@ export function useFilterParameters() { page, pageSize, search, + segment, + cohort, ]); } diff --git a/src/components/input/SegmentFilters.tsx b/src/components/input/SegmentFilters.tsx index 51690a01..6d1936ee 100644 --- a/src/components/input/SegmentFilters.tsx +++ b/src/components/input/SegmentFilters.tsx @@ -1,4 +1,3 @@ -import { useState } from 'react'; import { List, Column, ListItem } from '@umami/react-zen'; import { useWebsiteSegmentsQuery } from '@/components/hooks'; import { LoadingPanel } from '@/components/common/LoadingPanel'; @@ -11,17 +10,15 @@ export interface SegmentFiltersProps { export function SegmentFilters({ websiteId, segmentId, onSave }: SegmentFiltersProps) { const { data, isLoading } = useWebsiteSegmentsQuery(websiteId, { type: 'segment' }); - const [currentSegment, setCurrentSegment] = useState(segmentId); - const handleSave = (id: string) => { - setCurrentSegment(id); - onSave?.(data.find(item => item.id === id)); + const handleChange = (id: string) => { + onSave?.(id); }; return ( - handleSave(id[0])}> + handleChange(id[0])}> {data?.map(item => { return ( diff --git a/src/lib/clickhouse.ts b/src/lib/clickhouse.ts index 1670546e..bb184d6b 100644 --- a/src/lib/clickhouse.ts +++ b/src/lib/clickhouse.ts @@ -87,21 +87,6 @@ function mapFilter(column: string, operator: string, name: string, type: string } } -function mapCohortFilter(column: string, operator: string, value: string) { - switch (operator) { - case OPERATORS.equals: - return `${column} = '${value}'`; - case OPERATORS.notEquals: - return `${column} != '${value}'`; - case OPERATORS.contains: - return `positionCaseInsensitive(${column}, '${value}') > 0`; - case OPERATORS.doesNotContain: - return `positionCaseInsensitive(${column}, '${value}') = 0`; - default: - return ''; - } -} - function getFilterQuery(filters: Record, options: QueryOptions = {}) { const query = filtersToArray(filters, options).reduce((arr, { name, column, operator }) => { if (column) { @@ -118,40 +103,22 @@ function getFilterQuery(filters: Record, options: QueryOptions = {} return query.join('\n'); } -function getCohortQuery(websiteId: string, filters: QueryFilters = {}, options: QueryOptions = {}) { - const query = filtersToArray(filters, options).reduce( - (arr, { name, column, operator, value }) => { - if (column) { - arr.push( - `${arr.length === 0 ? 'where' : 'and'} ${mapCohortFilter(column, operator, value)}`, - ); - - if (name === 'referrer') { - arr.push(`and referrer_domain != hostname`); - } - } - - return arr; - }, - [], - ); - - if (query.length > 0) { - // add website and date range filters - query.push(`and website_id = '${websiteId}'`); - query.push( - `and created_at between parseDateTimeBestEffort('${filters.startDate}') and parseDateTimeBestEffort('${filters.endDate}')`, - ); - - return `join - (select distinct session_id - from website_event - ${query.join('\n')}) cohort - on cohort.session_id = website_event.session_id - `; +function getCohortQuery(filters: Record, options: QueryOptions = {}) { + if (!filters) { + return ''; } - return ''; + const filterQuery = getFilterQuery(filters, options); + + return `join ( + select distinct session_id + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + ${filterQuery} + ) as cohort + on cohort.session_id = website_event.session_id + `; } function getDateQuery(filters: Record) { @@ -192,7 +159,7 @@ function parseFilters(filters: Record, options?: QueryOptions) { filterQuery: getFilterQuery(filters, options), dateQuery: getDateQuery(filters), queryParams: getQueryParams(filters), - cohortQuery: getCohortQuery(filters?.cohort), + cohortQuery: getCohortQuery(filters?.cohortFilters, options), }; } diff --git a/src/lib/params.ts b/src/lib/params.ts index e769ed61..9b3abf58 100644 --- a/src/lib/params.ts +++ b/src/lib/params.ts @@ -5,7 +5,7 @@ export function parseParameterValue(param: any) { if (typeof param === 'string') { const [, operator, value] = param.match(/^([a-z]+)\.(.*)/) || []; - return { operator, value }; + return { operator: operator || OPERATORS.equals, value: value || param }; } return { operator: OPERATORS.equals, value: param }; } diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index b8ad4984..ab97b7d6 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -241,7 +241,7 @@ async function pagedQuery(model: string, criteria: T, filters?: QueryFilters) return { data, count, page: +page, pageSize: size, orderBy, search }; } -async function pagedRawQuery( +async function rawPagedQuery( query: string, filters: QueryFilters, queryParams: Record, @@ -360,7 +360,7 @@ export default { getTimestampDiffSQL, getSearchSQL, pagedQuery, - pagedRawQuery, + pagedRawQuery: rawPagedQuery, parseFilters, rawQuery, }; diff --git a/src/lib/request.ts b/src/lib/request.ts index 3b16f355..c5e5b9bc 100644 --- a/src/lib/request.ts +++ b/src/lib/request.ts @@ -1,5 +1,5 @@ import { z } from 'zod/v4'; -import { FILTER_COLUMNS, DEFAULT_PAGE_SIZE, FILTER_GROUPS } from '@/lib/constants'; +import { FILTER_COLUMNS, DEFAULT_PAGE_SIZE } from '@/lib/constants'; import { badRequest, unauthorized } from '@/lib/response'; import { getAllowedUnits, getMinimumUnit, maxDate } from '@/lib/date'; import { checkAuth } from '@/lib/auth'; @@ -79,16 +79,6 @@ export function getRequestFilters(query: Record) { return result; } -export async function getRequestSegments(websiteId: string, query: Record) { - for (const key of Object.keys(FILTER_GROUPS)) { - const value = query[key]; - - if (value !== undefined) { - return getWebsiteSegment(websiteId, key, value); - } - } -} - export async function setWebsiteDate(websiteId: string, data: Record) { const website = await fetchWebsite(websiteId); @@ -109,7 +99,13 @@ export async function getQueryFilters( if (websiteId) { await setWebsiteDate(websiteId, dateRange); - Object.assign(filters, await getRequestSegments(websiteId, params)); + if (params.segment) { + Object.assign(filters, (await getWebsiteSegment(websiteId, params.segment))?.parameters); + } + + if (params.cohort) { + filters.cohortFilters = (await getWebsiteSegment(websiteId, params.cohort))?.parameters; + } } return { diff --git a/src/lib/schema.ts b/src/lib/schema.ts index 41931b7b..7a655498 100644 --- a/src/lib/schema.ts +++ b/src/lib/schema.ts @@ -35,8 +35,8 @@ export const filterParams = { hostname: z.string().optional(), language: z.string().optional(), event: z.string().optional(), - segment: z.string().optional(), - cohort: z.string().optional(), + segment: z.string().uuid().optional(), + cohort: z.string().uuid().optional(), eventType: z.coerce.number().int().positive().optional(), }; diff --git a/src/lib/types.ts b/src/lib/types.ts index 29d566a5..81627458 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -44,7 +44,14 @@ export interface QueryOptions { prefix?: string; } -export interface QueryFilters extends DateParams, FilterParams, SortParams, PageParams {} +export interface QueryFilters + extends DateParams, + FilterParams, + SortParams, + PageParams, + SegmentParams { + cohortFilters?: QueryFilters; +} export interface DateParams { startDate?: Date; @@ -86,6 +93,11 @@ export interface PageParams { pageSize?: number; } +export interface SegmentParams { + segment?: string; + cohort?: string; +} + export interface PageResult { data: T; count: number; diff --git a/src/queries/prisma/segment.ts b/src/queries/prisma/segment.ts index 1f962e8f..01b82e9b 100644 --- a/src/queries/prisma/segment.ts +++ b/src/queries/prisma/segment.ts @@ -13,13 +13,9 @@ export async function getSegment(segmentId: string): Promise { }); } -export async function getWebsiteSegment( - websiteId: string, - type: string, - name: string, -): Promise { - return prisma.client.segment.findFirst({ - where: { websiteId, type, name }, +export async function getWebsiteSegment(websiteId: string, segmentId: string): Promise { + return prisma.client.Segment.findFirst({ + where: { id: segmentId, websiteId }, }); } From c8b4ee8ca55a64ed0634cc1cbfdab0b3c33f6a08 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Thu, 31 Jul 2025 09:45:19 -0700 Subject: [PATCH 142/399] update psql getChannelMetrics --- src/queries/sql/getChannelMetrics.ts | 42 +++++++++++++++++++++------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/queries/sql/getChannelMetrics.ts b/src/queries/sql/getChannelMetrics.ts index 9054b18b..c240cc86 100644 --- a/src/queries/sql/getChannelMetrics.ts +++ b/src/queries/sql/getChannelMetrics.ts @@ -29,17 +29,35 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { return rawQuery( ` - select - referrer_domain as domain, - url_query as query, - count(distinct session_id) as visitors - from website_event - ${cohortQuery} - where website_id = {{websiteId::uuid}} - ${filterQuery} + WITH channels as ( + select case when ${toPostgresPositionClause('utm_medium', ['cp', 'ppc', 'retargeting', 'paid'])} then 'paid' else 'organic' end prefix, + case + when referrer_domain = '' and url_query = '' then 'direct' + when ${toPostgresPositionClause('url_query', PAID_AD_PARAMS)} then 'paidAds' + when ${toPostgresPositionClause('utm_medium', ['referral', 'app', 'link'])} then 'referral' + when position(utm_medium, 'affiliate') > 0 then 'affiliate' + when position(utm_medium, 'sms') > 0 or position(utm_source, 'sms') > 0 then 'sms' + when ${toPostgresPositionClause('referrer_domain', SEARCH_DOMAINS)} or position(utm_medium, 'organic') > 0 then concat(prefix, 'Search') + when ${toPostgresPositionClause('referrer_domain', SOCIAL_DOMAINS)} then concat(prefix, 'Social') + when ${toPostgresPositionClause('referrer_domain', EMAIL_DOMAINS)} or position(utm_medium, 'mail') > 0 then 'email' + when ${toPostgresPositionClause('referrer_domain', SHOPPING_DOMAINS)} or position(utm_medium, 'shop') > 0 then concat(prefix, 'Shopping') + when ${toPostgresPositionClause('referrer_domain', VIDEO_DOMAINS)} or position(utm_medium, 'video') > 0 then concat(prefix, 'Video') + else '' end AS x, + count(distinct session_id) y + from website_event + ${cohortQuery} + where website_id = {{websiteId::uuid}} + and event_type = {{eventType}} ${dateQuery} - group by 1, 2 - order by visitors desc + ${filterQuery} + group by 1, 2 + order by y desc) + + select x, sum(y) y + from channels + where x != '' + group by x + order by y desc; `, queryParams, ); @@ -106,3 +124,7 @@ async function clickhouseQuery( function toClickHouseStringArray(arr: string[]): string { return arr.map(p => `'${p.replace(/'/g, "\\'")}'`).join(', '); } + +function toPostgresPositionClause(column: string, arr: string[]) { + return arr.map(val => `position(${column}, '${val.replace(/'/g, "''")}') > 0`).join(' OR\n '); +} From 2dbcf63eebac866ca000794d966ee00924fb1117 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 31 Jul 2025 21:32:22 -0700 Subject: [PATCH 143/399] Segment editing. --- .../websites/[websiteId]/WebsiteControls.tsx | 6 +- .../[websiteId]/WebsiteFilterButton.tsx | 12 +-- .../[websiteId]/segments/SegmentAddButton.tsx | 26 ++++++ .../[websiteId]/segments/SegmentEditForm.tsx | 79 +++++++++++++++++++ .../segments/SegmentsDataTable.tsx | 24 ++++++ .../[websiteId]/segments/SegmentsPage.tsx | 16 ++++ .../[websiteId]/segments/SegmentsTable.tsx | 49 ++++++++++++ .../websites/[websiteId]/segments/page.tsx | 12 +++ .../websites/[websiteId]/segments/route.ts | 3 +- src/components/common/FilterEditForm.tsx | 14 +++- src/components/hooks/index.ts | 3 +- .../hooks/queries/useWebsiteSegmentQuery.ts | 21 +++++ ...ntsQuery.ts => useWebsiteSegmentsQuery.ts} | 8 +- src/components/input/FieldFilters.tsx | 15 ++-- src/components/input/FilterBar.tsx | 15 +++- src/components/input/SegmentFilters.tsx | 2 +- src/components/input/WebsiteDateFilter.tsx | 2 - src/lib/clickhouse.ts | 6 +- src/lib/params.ts | 18 ++++- src/lib/prisma.ts | 8 +- src/lib/types.ts | 7 ++ src/queries/prisma/segment.ts | 2 +- 22 files changed, 306 insertions(+), 42 deletions(-) create mode 100644 src/app/(main)/websites/[websiteId]/segments/SegmentAddButton.tsx create mode 100644 src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx create mode 100644 src/app/(main)/websites/[websiteId]/segments/SegmentsDataTable.tsx create mode 100644 src/app/(main)/websites/[websiteId]/segments/SegmentsPage.tsx create mode 100644 src/app/(main)/websites/[websiteId]/segments/SegmentsTable.tsx create mode 100644 src/app/(main)/websites/[websiteId]/segments/page.tsx create mode 100644 src/components/hooks/queries/useWebsiteSegmentQuery.ts rename src/components/hooks/queries/{useWebsiteSegementsQuery.ts => useWebsiteSegmentsQuery.ts} (58%) diff --git a/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx b/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx index 655e8ea0..f0471ed6 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteControls.tsx @@ -3,6 +3,7 @@ import { WebsiteFilterButton } from '@/app/(main)/websites/[websiteId]/WebsiteFi import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter'; import { FilterBar } from '@/components/input/FilterBar'; import { WebsiteMonthSelect } from '@/components/input/WebsiteMonthSelect'; +import { ExportButton } from '@/components/input/ExportButton'; export function WebsiteControls({ websiteId, @@ -10,21 +11,24 @@ export function WebsiteControls({ allowDateFilter = true, allowMonthFilter, allowCompare, + allowDownload = false, }: { websiteId: string; allowFilter?: boolean; allowCompare?: boolean; allowDateFilter?: boolean; allowMonthFilter?: boolean; + allowDownload?: boolean; }) { return ( {allowFilter ? :
} {allowDateFilter && } + {allowDownload && } {allowMonthFilter && } - {allowFilter && } + {allowFilter && } ); } diff --git a/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx b/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx index 94022e87..a3442d1c 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx @@ -2,6 +2,7 @@ import { Button, Icon, DialogTrigger, Dialog, Modal, Text } from '@umami/react-z import { ListFilter } from '@/components/icons'; import { FilterEditForm } from '@/components/common/FilterEditForm'; import { useMessages, useNavigation, useFilters } from '@/components/hooks'; +import { filtersArrayToObject } from '@/lib/params'; export function WebsiteFilterButton({ websiteId, @@ -21,16 +22,7 @@ export function WebsiteFilterButton({ const { filters } = useFilters(); const handleChange = ({ filters, segment }) => { - const params = filters.reduce( - (obj: { [x: string]: string }, filter: { name: any; operator: any; value: any }) => { - const { name, operator, value } = filter; - - obj[name] = `${operator}.${value}`; - - return obj; - }, - {}, - ); + const params = filtersArrayToObject(filters); const url = replaceParams({ ...params, segment }); diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentAddButton.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentAddButton.tsx new file mode 100644 index 00000000..3c198fd4 --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentAddButton.tsx @@ -0,0 +1,26 @@ +import { Button, DialogTrigger, Modal, Text, Icon, Dialog } from '@umami/react-zen'; +import { useMessages } from '@/components/hooks'; +import { Plus } from '@/components/icons'; +import { SegmentEditForm } from '@/app/(main)/websites/[websiteId]/segments/SegmentEditForm'; + +export function SegmentAddButton({ websiteId }: { websiteId: string }) { + const { formatMessage, labels } = useMessages(); + + return ( + + + + + {({ close }) => { + return ; + }} + + + + ); +} diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx new file mode 100644 index 00000000..15133e8e --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx @@ -0,0 +1,79 @@ +import { + Button, + Form, + FormButtons, + FormField, + FormSubmitButton, + TextField, + Label, +} from '@umami/react-zen'; +import { subMonths, endOfDay } from 'date-fns'; +import { FieldFilters } from '@/components/input/FieldFilters'; +import { useState } from 'react'; +import { useApi, useMessages, useModified } from '@/components/hooks'; +import { filtersArrayToObject } from '@/lib/params'; + +export function SegmentEditForm({ + websiteId, + filters = [], + onSave, + onClose, +}: { + websiteId: string; + filters?: any[]; + onSave?: () => void; + onClose?: () => void; +}) { + const { formatMessage, labels } = useMessages(); + const [currentFilters, setCurrentFilters] = useState(filters); + const { touch } = useModified(); + const startDate = subMonths(endOfDay(new Date()), 6); + const endDate = endOfDay(new Date()); + + const { post, useMutation } = useApi(); + const { mutate, error, isPending } = useMutation({ + mutationFn: (data: any) => + post(`/websites/${websiteId}/segments`, { ...data, type: 'segment' }), + }); + + const handleSubmit = async (data: any) => { + mutate( + { ...data, parameters: filtersArrayToObject(currentFilters) }, + { + onSuccess: async () => { + touch('segments'); + onSave?.(); + onClose?.(); + }, + }, + ); + }; + + return ( + + + + + + + + + + {formatMessage(labels.save)} + + + + ); +} diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentsDataTable.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentsDataTable.tsx new file mode 100644 index 00000000..d98bad02 --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentsDataTable.tsx @@ -0,0 +1,24 @@ +import { SegmentAddButton } from './SegmentAddButton'; +import { useWebsiteSegmentsQuery } from '@/components/hooks'; +import { SegmentsTable } from './SegmentsTable'; +import { DataGrid } from '@/components/common/DataGrid'; + +export function SegmentsDataTable({ websiteId }: { websiteId?: string }) { + const query = useWebsiteSegmentsQuery(websiteId, { type: 'segment' }); + + const renderActions = () => { + return ; + }; + + return ( + + {({ data }) => } + + ); +} diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentsPage.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentsPage.tsx new file mode 100644 index 00000000..9f2d8097 --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentsPage.tsx @@ -0,0 +1,16 @@ +'use client'; +import { Column } from '@umami/react-zen'; +import { SegmentsDataTable } from './SegmentsDataTable'; +import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls'; +import { Panel } from '@/components/common/Panel'; + +export function SegmentsPage({ websiteId }) { + return ( + + + + + + + ); +} diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentsTable.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentsTable.tsx new file mode 100644 index 00000000..0231db87 --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentsTable.tsx @@ -0,0 +1,49 @@ +import { DataTable, DataColumn, Icon, Row, Text, MenuItem } from '@umami/react-zen'; +import { useMessages } from '@/components/hooks'; +import { Empty } from '@/components/common/Empty'; +import { Edit, Trash } from '@/components/icons'; +import { DateDistance } from '@/components/common/DateDistance'; +import { MenuButton } from '@/components/input/MenuButton'; + +export function SegmentsTable({ data = [] }) { + const { formatMessage, labels } = useMessages(); + + if (data.length === 0) { + return ; + } + + return ( + + + + {(row: any) => } + + + {(row: any) => { + const { id } = row; + + return ( + + + + + + + {formatMessage(labels.edit)} + + + + + + + + {formatMessage(labels.delete)} + + + + ); + }} + + + ); +} diff --git a/src/app/(main)/websites/[websiteId]/segments/page.tsx b/src/app/(main)/websites/[websiteId]/segments/page.tsx new file mode 100644 index 00000000..9f406b16 --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/segments/page.tsx @@ -0,0 +1,12 @@ +import { Metadata } from 'next'; +import { SegmentsPage } from './SegmentsPage'; + +export default async function ({ params }: { params: Promise<{ websiteId: string }> }) { + const { websiteId } = await params; + + return ; +} + +export const metadata: Metadata = { + title: 'Segments', +}; diff --git a/src/app/api/websites/[websiteId]/segments/route.ts b/src/app/api/websites/[websiteId]/segments/route.ts index 2cf8388f..5bbcceed 100644 --- a/src/app/api/websites/[websiteId]/segments/route.ts +++ b/src/app/api/websites/[websiteId]/segments/route.ts @@ -2,7 +2,7 @@ import { canUpdateWebsite, canViewWebsite } from '@/lib/auth'; import { uuid } from '@/lib/crypto'; import { parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; -import { segmentTypeParam } from '@/lib/schema'; +import { segmentTypeParam, searchParams } from '@/lib/schema'; import { createSegment, getWebsiteSegments } from '@/queries'; import { z } from 'zod'; @@ -12,6 +12,7 @@ export async function GET( ) { const schema = z.object({ type: segmentTypeParam, + ...searchParams, }); const { auth, query, error } = await parseRequest(request, schema); diff --git a/src/components/common/FilterEditForm.tsx b/src/components/common/FilterEditForm.tsx index 45c402d2..b253b780 100644 --- a/src/components/common/FilterEditForm.tsx +++ b/src/components/common/FilterEditForm.tsx @@ -1,6 +1,6 @@ import { useState } from 'react'; import { Column, Tabs, TabList, Tab, TabPanel, Row, Button } from '@umami/react-zen'; -import { useMessages } from '@/components/hooks'; +import { useDateRange, useMessages } from '@/components/hooks'; import { FieldFilters } from '@/components/input/FieldFilters'; import { SegmentFilters } from '@/components/input/SegmentFilters'; @@ -23,6 +23,10 @@ export function FilterEditForm({ const [currentFilters, setCurrentFilters] = useState(filters); const [currentSegment, setCurrentSegment] = useState(segmentId); + const { + dateRange: { startDate, endDate }, + } = useDateRange(websiteId); + const handleReset = () => { setCurrentFilters([]); setCurrentSegment(null); @@ -45,7 +49,13 @@ export function FilterEditForm({ {formatMessage(labels.segments)} - + , +) { + const { get, useQuery } = useApi(); + const { modified } = useModified(`segments`); + + return useQuery({ + queryKey: ['website:segments', { websiteId, segmentId, modified }], + queryFn: () => get(`/websites/${websiteId}/segments/${segmentId}`), + enabled: !!(websiteId && segmentId), + placeholderData: keepPreviousData, + ...options, + }); +} diff --git a/src/components/hooks/queries/useWebsiteSegementsQuery.ts b/src/components/hooks/queries/useWebsiteSegmentsQuery.ts similarity index 58% rename from src/components/hooks/queries/useWebsiteSegementsQuery.ts rename to src/components/hooks/queries/useWebsiteSegmentsQuery.ts index aecf1d52..f64b6c2f 100644 --- a/src/components/hooks/queries/useWebsiteSegementsQuery.ts +++ b/src/components/hooks/queries/useWebsiteSegmentsQuery.ts @@ -2,6 +2,7 @@ import { useApi } from '../useApi'; import { useModified } from '@/components/hooks'; import { keepPreviousData } from '@tanstack/react-query'; import { ReactQueryOptions } from '@/lib/types'; +import { useFilterParameters } from '@/components/hooks/useFilterParameters'; export function useWebsiteSegmentsQuery( websiteId: string, @@ -9,11 +10,12 @@ export function useWebsiteSegmentsQuery( options?: ReactQueryOptions, ) { const { get, useQuery } = useApi(); - const { modified } = useModified(`website:${websiteId}`); + const { modified } = useModified(`segments`); + const filters = useFilterParameters(); return useQuery({ - queryKey: ['website:segments', { websiteId, modified, ...params }], - queryFn: () => get(`/websites/${websiteId}/segments`, { ...params }), + queryKey: ['website:segments', { websiteId, modified, ...filters, ...params }], + queryFn: () => get(`/websites/${websiteId}/segments`, { ...filters, ...params }), enabled: !!websiteId, placeholderData: keepPreviousData, ...options, diff --git a/src/components/input/FieldFilters.tsx b/src/components/input/FieldFilters.tsx index d37f8850..88d7b822 100644 --- a/src/components/input/FieldFilters.tsx +++ b/src/components/input/FieldFilters.tsx @@ -1,21 +1,26 @@ import { Key } from 'react'; import { Grid, Column, List, ListItem } from '@umami/react-zen'; -import { useDateRange, useFields, useMessages } from '@/components/hooks'; +import { useFields, useMessages } from '@/components/hooks'; import { FilterRecord } from '@/components/common/FilterRecord'; import { Empty } from '@/components/common/Empty'; export interface FieldFiltersProps { websiteId: string; filters: { name: string; operator: string; value: string }[]; + startDate: Date; + endDate: Date; onSave?: (data: any) => void; } -export function FieldFilters({ websiteId, filters, onSave }: FieldFiltersProps) { +export function FieldFilters({ + websiteId, + filters, + startDate, + endDate, + onSave, +}: FieldFiltersProps) { const { formatMessage, messages } = useMessages(); const { fields } = useFields(); - const { - dateRange: { startDate, endDate }, - } = useDateRange(websiteId); const updateFilter = (name: string, props: Record) => { onSave(filters.map(filter => (filter.name === name ? { ...filter, ...props } : filter))); diff --git a/src/components/input/FilterBar.tsx b/src/components/input/FilterBar.tsx index 51409b26..445db323 100644 --- a/src/components/input/FilterBar.tsx +++ b/src/components/input/FilterBar.tsx @@ -1,9 +1,15 @@ import { Button, Icon, Text, Row, TooltipTrigger, Tooltip } from '@umami/react-zen'; -import { useNavigation, useMessages, useFormat, useFilters } from '@/components/hooks'; +import { + useNavigation, + useMessages, + useFormat, + useFilters, + useWebsiteSegmentQuery, +} from '@/components/hooks'; import { Close } from '@/components/icons'; import { isSearchOperator } from '@/lib/params'; -export function FilterBar() { +export function FilterBar({ websiteId }: { websiteId: string }) { const { formatMessage, labels } = useMessages(); const { formatValue } = useFormat(); const { @@ -13,6 +19,7 @@ export function FilterBar() { query: { segment }, } = useNavigation(); const { filters, operatorLabels } = useFilters(); + const { data, isLoading } = useWebsiteSegmentQuery(websiteId, segment); const handleCloseFilter = (param: string) => { router.push(updateParams({ [param]: undefined })); @@ -33,11 +40,11 @@ export function FilterBar() { return ( - {segment && ( + {segment && !isLoading && ( diff --git a/src/components/input/SegmentFilters.tsx b/src/components/input/SegmentFilters.tsx index 6d1936ee..3cf8ce46 100644 --- a/src/components/input/SegmentFilters.tsx +++ b/src/components/input/SegmentFilters.tsx @@ -19,7 +19,7 @@ export function SegmentFilters({ websiteId, segmentId, onSave }: SegmentFiltersP handleChange(id[0])}> - {data?.map(item => { + {data?.data?.map(item => { return ( {item.name} diff --git a/src/components/input/WebsiteDateFilter.tsx b/src/components/input/WebsiteDateFilter.tsx index 0bf74846..e78bcd8d 100644 --- a/src/components/input/WebsiteDateFilter.tsx +++ b/src/components/input/WebsiteDateFilter.tsx @@ -12,7 +12,6 @@ import { isAfter } from 'date-fns'; import { Chevron, Close, Compare } from '@/components/icons'; import { useDateRange, useMessages, useNavigation } from '@/components/hooks'; import { DateFilter } from './DateFilter'; -import { ExportButton } from '@/components/input/ExportButton'; export function WebsiteDateFilter({ websiteId, @@ -102,7 +101,6 @@ export function WebsiteDateFilter({ {formatMessage(compare ? labels.cancel : labels.compareDates)} )} - ); } diff --git a/src/lib/clickhouse.ts b/src/lib/clickhouse.ts index bb184d6b..233a78bf 100644 --- a/src/lib/clickhouse.ts +++ b/src/lib/clickhouse.ts @@ -3,7 +3,7 @@ import { formatInTimeZone } from 'date-fns-tz'; import debug from 'debug'; import { CLICKHOUSE } from '@/lib/db'; import { DEFAULT_PAGE_SIZE, OPERATORS } from './constants'; -import { filtersToArray } from './params'; +import { filtersObjectToArray } from './params'; import { QueryFilters, QueryOptions } from './types'; export const CLICKHOUSE_DATE_FORMATS = { @@ -88,7 +88,7 @@ function mapFilter(column: string, operator: string, name: string, type: string } function getFilterQuery(filters: Record, options: QueryOptions = {}) { - const query = filtersToArray(filters, options).reduce((arr, { name, column, operator }) => { + const query = filtersObjectToArray(filters, options).reduce((arr, { name, column, operator }) => { if (column) { arr.push(`and ${mapFilter(column, operator, name)}`); @@ -144,7 +144,7 @@ function getDateQuery(filters: Record) { function getQueryParams(filters: Record) { return { ...filters, - ...filtersToArray(filters).reduce((obj, { name, value }) => { + ...filtersObjectToArray(filters).reduce((obj, { name, value }) => { if (name && value !== undefined) { obj[name] = value; } diff --git a/src/lib/params.ts b/src/lib/params.ts index 9b3abf58..e136542b 100644 --- a/src/lib/params.ts +++ b/src/lib/params.ts @@ -1,7 +1,7 @@ import { FILTER_COLUMNS, OPERATORS } from '@/lib/constants'; -import { QueryFilters, QueryOptions } from '@/lib/types'; +import { Filter, QueryFilters, QueryOptions } from '@/lib/types'; -export function parseParameterValue(param: any) { +export function parseFilterValue(param: any) { if (typeof param === 'string') { const [, operator, value] = param.match(/^([a-z]+)\.(.*)/) || []; @@ -18,7 +18,7 @@ export function isSearchOperator(operator: any) { return [OPERATORS.contains, OPERATORS.doesNotContain].includes(operator); } -export function filtersToArray(filters: QueryFilters, options: QueryOptions = {}) { +export function filtersObjectToArray(filters: QueryFilters, options: QueryOptions = {}) { return Object.keys(filters).reduce((arr, key) => { const filter = filters[key]; @@ -30,7 +30,7 @@ export function filtersToArray(filters: QueryFilters, options: QueryOptions = {} return arr.concat({ ...filter, column: options?.columns?.[key] ?? FILTER_COLUMNS[key] }); } - const { operator, value } = parseParameterValue(filter); + const { operator, value } = parseFilterValue(filter); return arr.concat({ name: key, @@ -41,3 +41,13 @@ export function filtersToArray(filters: QueryFilters, options: QueryOptions = {} }); }, []); } + +export function filtersArrayToObject(filters: Filter[]) { + return filters.reduce((obj, filter: Filter) => { + const { name, operator, value } = filter; + + obj[name] = `${operator}.${value}`; + + return obj; + }, {}); +} diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index ab97b7d6..560361f8 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -4,7 +4,7 @@ import { PrismaPg } from '@prisma/adapter-pg'; import { readReplicas } from '@prisma/extension-read-replicas'; import { SESSION_COLUMNS, OPERATORS, DEFAULT_PAGE_SIZE } from './constants'; import { QueryOptions, QueryFilters } from './types'; -import { filtersToArray } from './params'; +import { filtersObjectToArray } from './params'; const log = debug('umami:prisma'); @@ -95,7 +95,7 @@ function mapCohortFilter(column: string, operator: string, value: string) { } function getFilterQuery(filters: Record, options: QueryOptions = {}): string { - const query = filtersToArray(filters, options).reduce( + const query = filtersObjectToArray(filters, options).reduce( (arr, { name, column, operator, prefix = '' }) => { if (column) { arr.push(`and ${mapFilter(`${prefix}${column}`, operator, name)}`); @@ -116,7 +116,7 @@ function getFilterQuery(filters: Record, options: QueryOptions = {} } function getCohortQuery(websiteId: string, filters: QueryFilters = {}, options: QueryOptions = {}) { - const query = filtersToArray(filters, options).reduce( + const query = filtersObjectToArray(filters, options).reduce( (arr, { name, column, operator, value }) => { if (column) { arr.push( @@ -169,7 +169,7 @@ function getDateQuery(filters: Record) { function getQueryParams(filters: Record) { return { ...filters, - ...filtersToArray(filters).reduce((obj, { name, operator, value }) => { + ...filtersObjectToArray(filters).reduce((obj, { name, operator, value }) => { obj[name] = [OPERATORS.contains, OPERATORS.doesNotContain].includes(operator) ? `%${value}%` : value; diff --git a/src/lib/types.ts b/src/lib/types.ts index 81627458..53bdaea5 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -24,6 +24,13 @@ export interface Auth { }; } +export interface Filter { + name: string; + operator: string; + value: string; + type?: string; +} + export interface DateRange { startDate: Date; endDate: Date; diff --git a/src/queries/prisma/segment.ts b/src/queries/prisma/segment.ts index 01b82e9b..311eccd4 100644 --- a/src/queries/prisma/segment.ts +++ b/src/queries/prisma/segment.ts @@ -20,7 +20,7 @@ export async function getWebsiteSegment(websiteId: string, segmentId: string): P } export async function getWebsiteSegments(websiteId: string, type: string): Promise { - return prisma.client.Segment.findMany({ + return prisma.pagedQuery('segment', { where: { websiteId, type }, }); } From c1cad16cb9453d3e2de95a2c9c29494e8e6c1dbd Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Mon, 4 Aug 2025 18:27:31 -0700 Subject: [PATCH 144/399] implement sessions metric expanded queries --- src/app/(main)/App.tsx | 2 +- .../[websiteId]/WebsiteExpandedView.tsx | 1 + .../[websiteId]/metrics/expanded/route.ts | 87 ++++++++++++ src/components/hooks/index.ts | 1 + .../queries/useWebsiteExpandedMetricsQuery.ts | 45 +++++++ src/components/metrics/ListExpandedTable.tsx | 47 +++++++ src/components/metrics/MetricsTable.tsx | 47 +++++-- src/queries/index.ts | 1 + .../sql/sessions/getSessionDataValues.ts | 8 +- .../sql/sessions/getSessionExpandedMetrics.ts | 126 ++++++++++++++++++ 10 files changed, 352 insertions(+), 13 deletions(-) create mode 100644 src/app/api/websites/[websiteId]/metrics/expanded/route.ts create mode 100644 src/components/hooks/queries/useWebsiteExpandedMetricsQuery.ts create mode 100644 src/components/metrics/ListExpandedTable.tsx create mode 100644 src/queries/sql/sessions/getSessionExpandedMetrics.ts diff --git a/src/app/(main)/App.tsx b/src/app/(main)/App.tsx index e3602d5a..ee453941 100644 --- a/src/app/(main)/App.tsx +++ b/src/app/(main)/App.tsx @@ -30,7 +30,7 @@ export function App({ children }) { - + {children} diff --git a/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx b/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx index acd72ab9..e6788ae9 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx @@ -156,6 +156,7 @@ export function WebsiteExpandedView({ itemCount={25} allowFilter={true} allowSearch={true} + expanded={true} /> diff --git a/src/app/api/websites/[websiteId]/metrics/expanded/route.ts b/src/app/api/websites/[websiteId]/metrics/expanded/route.ts new file mode 100644 index 00000000..395971b6 --- /dev/null +++ b/src/app/api/websites/[websiteId]/metrics/expanded/route.ts @@ -0,0 +1,87 @@ +import { canViewWebsite } from '@/lib/auth'; +import { EVENT_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; +import { getQueryFilters, parseRequest } from '@/lib/request'; +import { badRequest, json, unauthorized } from '@/lib/response'; +import { dateRangeParams, filterParams, searchParams } from '@/lib/schema'; +import { + getChannelMetrics, + getEventMetrics, + getPageviewMetrics, + getSessionExpandedMetrics, +} from '@/queries'; +import { z } from 'zod'; + +export async function GET( + request: Request, + { params }: { params: Promise<{ websiteId: string }> }, +) { + const schema = z.object({ + type: z.string(), + limit: z.coerce.number().optional(), + offset: z.coerce.number().optional(), + ...dateRangeParams, + ...searchParams, + ...filterParams, + }); + + const { auth, query, error } = await parseRequest(request, schema); + + if (error) { + return error(); + } + + const { websiteId } = await params; + + if (!(await canViewWebsite(auth, websiteId))) { + return unauthorized(); + } + + const { type, limit, offset, search } = query; + const filters = await getQueryFilters(query, websiteId); + + if (search) { + filters[type] = `c.${search}`; + } + + if (SESSION_COLUMNS.includes(type)) { + const data = await getSessionExpandedMetrics(websiteId, { type, limit, offset }, filters); + + // if (type === 'language') { + // const combined = {}; + + // for (const { x, y } of data) { + // const key = String(x).toLowerCase().split('-')[0]; + + // if (combined[key] === undefined) { + // combined[key] = { x: key, y }; + // } else { + // combined[key].y += y; + // } + // } + + // return json(Object.values(combined)); + // } + + return json(data); + } + + if (EVENT_COLUMNS.includes(type)) { + let data; + + if (type === 'event') { + data = await getEventMetrics(websiteId, { type, limit, offset }, filters); + } else { + data = await getPageviewMetrics(websiteId, { type, limit, offset }, filters); + } + + return json(data); + } + + if (type === 'channel') { + const data = await getChannelMetrics(websiteId, filters); + + return json(data); + } + + return badRequest(); +} diff --git a/src/components/hooks/index.ts b/src/components/hooks/index.ts index 5c0d8d6b..e62479fb 100644 --- a/src/components/hooks/index.ts +++ b/src/components/hooks/index.ts @@ -31,6 +31,7 @@ export * from './queries/useWebsitesQuery'; export * from './queries/useWebsiteEventsQuery'; export * from './queries/useWebsiteEventsSeriesQuery'; export * from './queries/useWebsiteMetricsQuery'; +export * from './queries/useWebsiteExpandedMetricsQuery'; export * from './queries/useWebsiteValuesQuery'; export * from './useApi'; export * from './useConfig'; diff --git a/src/components/hooks/queries/useWebsiteExpandedMetricsQuery.ts b/src/components/hooks/queries/useWebsiteExpandedMetricsQuery.ts new file mode 100644 index 00000000..0443fd5f --- /dev/null +++ b/src/components/hooks/queries/useWebsiteExpandedMetricsQuery.ts @@ -0,0 +1,45 @@ +import { keepPreviousData } from '@tanstack/react-query'; +import { useApi } from '../useApi'; +import { useFilterParameters } from '../useFilterParameters'; +import { useDateParameters } from '../useDateParameters'; +import { ReactQueryOptions } from '@/lib/types'; + +export type WebsiteExpandedMetricsData = { + label: string; + pageviews: number; + visitors: number; + visits: number; + bounces: number; + totaltime: number; +}[]; + +export function useWebsiteExpandedMetricsQuery( + websiteId: string, + params: { type: string; limit?: number; search?: string }, + options?: ReactQueryOptions, +) { + const { get, useQuery } = useApi(); + const date = useDateParameters(websiteId); + const filters = useFilterParameters(); + + return useQuery({ + queryKey: [ + 'websites:metrics:expanded', + { + websiteId, + ...date, + ...filters, + ...params, + }, + ], + queryFn: async () => + get(`/websites/${websiteId}/metrics/expanded`, { + ...date, + ...filters, + ...params, + }), + enabled: !!websiteId, + placeholderData: keepPreviousData, + ...options, + }); +} diff --git a/src/components/metrics/ListExpandedTable.tsx b/src/components/metrics/ListExpandedTable.tsx new file mode 100644 index 00000000..fb3efdb5 --- /dev/null +++ b/src/components/metrics/ListExpandedTable.tsx @@ -0,0 +1,47 @@ +import { useMessages } from '@/components/hooks'; +import { formatShortTime } from '@/lib/format'; +import { DataColumn, DataTable } from '@umami/react-zen'; +import { ReactNode } from 'react'; + +export interface ListExpandedTableProps { + data?: any[]; + title?: string; + renderLabel?: (row: any, index: number) => ReactNode; +} + +export function ListExpandedTable({ data = [], title, renderLabel }: ListExpandedTableProps) { + const { formatMessage, labels } = useMessages(); + + return ( + + + {row => + renderLabel + ? renderLabel({ x: row?.label, country: row?.['country'] }, Number(row.id)) + : (row.label ?? formatMessage(labels.unknown)) + } + + + {row => row?.['visitors']?.toLocaleString()} + + + {row => row?.['visits']?.toLocaleString()} + + + {row => row?.['pageviews']?.toLocaleString()} + + + {row => { + const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100; + return Math.round(+n) + '%'; + }} + + + {row => { + const n = (row?.['totaltime'] / row?.['visits']) * 100; + return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`; + }} + + + ); +} diff --git a/src/components/metrics/MetricsTable.tsx b/src/components/metrics/MetricsTable.tsx index c229b00c..760a0da6 100644 --- a/src/components/metrics/MetricsTable.tsx +++ b/src/components/metrics/MetricsTable.tsx @@ -1,13 +1,20 @@ -import { ReactNode, useMemo, useState } from 'react'; -import { Icon, Text, SearchField, Row, Column } from '@umami/react-zen'; import { LinkButton } from '@/components/common/LinkButton'; +import { LoadingPanel } from '@/components/common/LoadingPanel'; +import { + useFormat, + useMessages, + useNavigation, + useWebsiteExpandedMetricsQuery, + useWebsiteMetricsQuery, +} from '@/components/hooks'; +import { Arrow } from '@/components/icons'; +import { DownloadButton } from '@/components/input/DownloadButton'; import { DEFAULT_ANIMATION_DURATION } from '@/lib/constants'; import { percentFilter } from '@/lib/filters'; -import { useNavigation, useWebsiteMetricsQuery, useMessages, useFormat } from '@/components/hooks'; -import { Arrow } from '@/components/icons'; +import { Column, Icon, Row, SearchField, Text } from '@umami/react-zen'; +import { ReactNode, useMemo, useState } from 'react'; +import { ListExpandedTable, ListExpandedTableProps } from './ListExpandedTable'; import { ListTable, ListTableProps } from './ListTable'; -import { LoadingPanel } from '@/components/common/LoadingPanel'; -import { DownloadButton } from '@/components/input/DownloadButton'; export interface MetricsTableProps extends ListTableProps { websiteId: string; @@ -21,6 +28,7 @@ export interface MetricsTableProps extends ListTableProps { showMore?: boolean; params?: { [key: string]: any }; allowDownload?: boolean; + expanded?: boolean; children?: ReactNode; } @@ -35,6 +43,7 @@ export function MetricsTable({ showMore = true, params, allowDownload = true, + expanded = false, children, ...props }: MetricsTableProps) { @@ -43,7 +52,21 @@ export function MetricsTable({ const { updateParams } = useNavigation(); const { formatMessage, labels } = useMessages(); - const { data, isLoading, isFetching, error } = useWebsiteMetricsQuery( + const expandedQuery = useWebsiteExpandedMetricsQuery( + websiteId, + { + type, + limit: 30, + search: searchFormattedValues ? undefined : search, + ...params, + }, + { + retryDelay: delay || DEFAULT_ANIMATION_DURATION, + enabled: expanded, + }, + ); + + const query = useWebsiteMetricsQuery( websiteId, { type, @@ -53,9 +76,12 @@ export function MetricsTable({ }, { retryDelay: delay || DEFAULT_ANIMATION_DURATION, + enabled: !expanded, }, ); + const { data, isLoading, isFetching, error } = expanded ? expandedQuery : query; + const filteredData = useMemo(() => { if (data) { let items = data as any[]; @@ -95,7 +121,12 @@ export function MetricsTable({ {allowDownload && } - {data && } + {data && + (expanded ? ( + + ) : ( + + ))} {showMore && data && !error && limit && ( diff --git a/src/queries/index.ts b/src/queries/index.ts index fba7e548..52ca6513 100644 --- a/src/queries/index.ts +++ b/src/queries/index.ts @@ -28,6 +28,7 @@ export * from '@/queries/sql/sessions/getSessionData'; export * from '@/queries/sql/sessions/getSessionDataProperties'; export * from '@/queries/sql/sessions/getSessionDataValues'; export * from '@/queries/sql/sessions/getSessionMetrics'; +export * from '@/queries/sql/sessions/getSessionExpandedMetrics'; export * from '@/queries/sql/sessions/getWebsiteSessions'; export * from '@/queries/sql/sessions/getWebsiteSessionStats'; export * from '@/queries/sql/sessions/getWebsiteSessionsWeekly'; diff --git a/src/queries/sql/sessions/getSessionDataValues.ts b/src/queries/sql/sessions/getSessionDataValues.ts index 682bfe4f..e4d04f1a 100644 --- a/src/queries/sql/sessions/getSessionDataValues.ts +++ b/src/queries/sql/sessions/getSessionDataValues.ts @@ -28,9 +28,9 @@ async function relationalQuery( else string_value end as "value", count(distinct session_data.session_id) as "total" - from website_event e + from website_event ${cohortQuery} - join session_data d + join session_data on session_data.session_id = website_event.session_id where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} @@ -58,9 +58,9 @@ async function clickhouseQuery( data_type = 4, toString(date_trunc('hour', date_value)), string_value) as "value", uniq(session_data.session_id) as "total" - from website_event e + from website_event ${cohortQuery} - join session_data d final + join session_data final on session_data.session_id = website_event.session_id where website_event.website_id = {websiteId:UUID} and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} diff --git a/src/queries/sql/sessions/getSessionExpandedMetrics.ts b/src/queries/sql/sessions/getSessionExpandedMetrics.ts new file mode 100644 index 00000000..ba0841dc --- /dev/null +++ b/src/queries/sql/sessions/getSessionExpandedMetrics.ts @@ -0,0 +1,126 @@ +import clickhouse from '@/lib/clickhouse'; +import { EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; +import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; +import prisma from '@/lib/prisma'; +import { QueryFilters } from '@/lib/types'; + +export interface SessionExpandedMetricsParameters { + type: string; + limit?: number | string; + offset?: number | string; +} + +export interface SessionExpandedMetricsData { + label: string; + pageviews: number; + visitors: number; + visits: number; + bounces: number; + totaltime: number; +} + +export async function getSessionExpandedMetrics( + ...args: [websiteId: string, parameters: SessionExpandedMetricsParameters, filters: QueryFilters] +): Promise { + return runQuery({ + [PRISMA]: () => relationalQuery(...args), + [CLICKHOUSE]: () => clickhouseQuery(...args), + }); +} + +async function relationalQuery( + websiteId: string, + parameters: SessionExpandedMetricsParameters, + filters: QueryFilters, +): Promise { + const { type, limit = 500, offset = 0 } = parameters; + const column = FILTER_COLUMNS[type] || type; + const { parseFilters, rawQuery } = prisma; + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters( + { + ...filters, + websiteId, + eventType: EVENT_TYPE.pageView, + }, + { + joinSession: SESSION_COLUMNS.includes(type), + }, + ); + const includeCountry = column === 'city' || column === 'region'; + + return rawQuery( + ` + select + ${column} x, + count(distinct website_event.session_id) y + ${includeCountry ? ', country' : ''} + from website_event + ${cohortQuery} + ${joinSessionQuery} + where website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + and website_event.event_type = {{eventType}} + ${filterQuery} + group by 1 + ${includeCountry ? ', 3' : ''} + order by 2 desc + limit ${limit} + offset ${offset} + `, + { ...queryParams, ...parameters }, + ); +} + +async function clickhouseQuery( + websiteId: string, + parameters: SessionExpandedMetricsParameters, + filters: QueryFilters, +): Promise { + const { type, limit = 500, offset = 0 } = parameters; + const column = FILTER_COLUMNS[type] || type; + const { parseFilters, rawQuery } = clickhouse; + const { filterQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + eventType: EVENT_TYPE.pageView, + }); + const includeCountry = column === 'city' || column === 'region'; + + return rawQuery( + ` + select + label, + ${includeCountry ? 'country,' : ''} + sum(t.c) as "pageviews", + uniq(t.session_id) as "visitors", + uniq(t.visit_id) as "visits", + sum(if(t.c = 1, 1, 0)) as "bounces", + sum(max_time-min_time) as "totaltime" + from ( + select + ${column} label, + ${includeCountry ? 'country,' : ''} + session_id, + visit_id, + count(*) c, + min(created_at) min_time, + max(created_at) max_time + from website_event + ${cohortQuery} + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and event_type = {eventType:UInt32} + and label != '' + ${filterQuery} + group by label, session_id, visit_id + ${includeCountry ? ', country' : ''} + ) as t + group by label + ${includeCountry ? ', country' : ''} + order by visitors desc, visits desc + limit ${limit} + offset ${offset} + `, + { ...queryParams, ...parameters }, + ); +} From 0a0c1f27c6b7ec9ad5c9933a0d06cfdb0cbfc427 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Tue, 5 Aug 2025 00:37:44 -0700 Subject: [PATCH 145/399] implement pageviews, events, and channels queries --- .../[websiteId]/metrics/expanded/route.ts | 28 +-- .../api/websites/[websiteId]/metrics/route.ts | 16 -- .../queries/useWebsiteExpandedMetricsQuery.ts | 2 +- .../metrics/ListExpandedTable.module.css | 7 + src/components/metrics/ListExpandedTable.tsx | 42 +++-- src/components/metrics/MetricsTable.tsx | 7 +- .../metrics/QueryParametersTable.tsx | 1 + src/lib/clickhouse.ts | 6 +- src/lib/constants.ts | 2 +- src/queries/index.ts | 3 + .../sql/events/getEventExpandedMetrics.ts | 113 ++++++++++++ src/queries/sql/events/getEventMetrics.ts | 1 - src/queries/sql/events/getEventStats.ts | 1 - src/queries/sql/getChannelExpandedMetrics.ts | 162 +++++++++++++++++ src/queries/sql/getChannelMetrics.ts | 1 - src/queries/sql/getWebsiteStats.ts | 2 - .../pageviews/getPageviewExpandedMetrics.ts | 166 ++++++++++++++++++ .../sql/pageviews/getPageviewMetrics.ts | 2 - src/queries/sql/pageviews/getPageviewStats.ts | 2 - src/queries/sql/reports/getAttribution.ts | 1 - src/queries/sql/reports/getBreakdown.ts | 1 - .../sql/sessions/getSessionExpandedMetrics.ts | 25 ++- src/queries/sql/sessions/getSessionMetrics.ts | 14 +- src/queries/sql/sessions/getSessionStats.ts | 2 - 24 files changed, 521 insertions(+), 86 deletions(-) create mode 100644 src/components/metrics/ListExpandedTable.module.css create mode 100644 src/queries/sql/events/getEventExpandedMetrics.ts create mode 100644 src/queries/sql/getChannelExpandedMetrics.ts create mode 100644 src/queries/sql/pageviews/getPageviewExpandedMetrics.ts diff --git a/src/app/api/websites/[websiteId]/metrics/expanded/route.ts b/src/app/api/websites/[websiteId]/metrics/expanded/route.ts index 395971b6..a327bd0b 100644 --- a/src/app/api/websites/[websiteId]/metrics/expanded/route.ts +++ b/src/app/api/websites/[websiteId]/metrics/expanded/route.ts @@ -4,9 +4,9 @@ import { getQueryFilters, parseRequest } from '@/lib/request'; import { badRequest, json, unauthorized } from '@/lib/response'; import { dateRangeParams, filterParams, searchParams } from '@/lib/schema'; import { - getChannelMetrics, - getEventMetrics, - getPageviewMetrics, + getChannelExpandedMetrics, + getEventExpandedMetrics, + getPageviewExpandedMetrics, getSessionExpandedMetrics, } from '@/queries'; import { z } from 'zod'; @@ -46,22 +46,6 @@ export async function GET( if (SESSION_COLUMNS.includes(type)) { const data = await getSessionExpandedMetrics(websiteId, { type, limit, offset }, filters); - // if (type === 'language') { - // const combined = {}; - - // for (const { x, y } of data) { - // const key = String(x).toLowerCase().split('-')[0]; - - // if (combined[key] === undefined) { - // combined[key] = { x: key, y }; - // } else { - // combined[key].y += y; - // } - // } - - // return json(Object.values(combined)); - // } - return json(data); } @@ -69,16 +53,16 @@ export async function GET( let data; if (type === 'event') { - data = await getEventMetrics(websiteId, { type, limit, offset }, filters); + data = await getEventExpandedMetrics(websiteId, { type, limit, offset }, filters); } else { - data = await getPageviewMetrics(websiteId, { type, limit, offset }, filters); + data = await getPageviewExpandedMetrics(websiteId, { type, limit, offset }, filters); } return json(data); } if (type === 'channel') { - const data = await getChannelMetrics(websiteId, filters); + const data = await getChannelExpandedMetrics(websiteId, { limit, offset }, filters); return json(data); } diff --git a/src/app/api/websites/[websiteId]/metrics/route.ts b/src/app/api/websites/[websiteId]/metrics/route.ts index 49592a0e..bc295d79 100644 --- a/src/app/api/websites/[websiteId]/metrics/route.ts +++ b/src/app/api/websites/[websiteId]/metrics/route.ts @@ -46,22 +46,6 @@ export async function GET( if (SESSION_COLUMNS.includes(type)) { const data = await getSessionMetrics(websiteId, { type, limit, offset }, filters); - if (type === 'language') { - const combined = {}; - - for (const { x, y } of data) { - const key = String(x).toLowerCase().split('-')[0]; - - if (combined[key] === undefined) { - combined[key] = { x: key, y }; - } else { - combined[key].y += y; - } - } - - return json(Object.values(combined)); - } - return json(data); } diff --git a/src/components/hooks/queries/useWebsiteExpandedMetricsQuery.ts b/src/components/hooks/queries/useWebsiteExpandedMetricsQuery.ts index 0443fd5f..9718dfe1 100644 --- a/src/components/hooks/queries/useWebsiteExpandedMetricsQuery.ts +++ b/src/components/hooks/queries/useWebsiteExpandedMetricsQuery.ts @@ -5,7 +5,7 @@ import { useDateParameters } from '../useDateParameters'; import { ReactQueryOptions } from '@/lib/types'; export type WebsiteExpandedMetricsData = { - label: string; + name: string; pageviews: number; visitors: number; visits: number; diff --git a/src/components/metrics/ListExpandedTable.module.css b/src/components/metrics/ListExpandedTable.module.css new file mode 100644 index 00000000..4bd287c4 --- /dev/null +++ b/src/components/metrics/ListExpandedTable.module.css @@ -0,0 +1,7 @@ +.truncate { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 300px; + display: block; +} diff --git a/src/components/metrics/ListExpandedTable.tsx b/src/components/metrics/ListExpandedTable.tsx index fb3efdb5..dc27b17f 100644 --- a/src/components/metrics/ListExpandedTable.tsx +++ b/src/components/metrics/ListExpandedTable.tsx @@ -2,23 +2,25 @@ import { useMessages } from '@/components/hooks'; import { formatShortTime } from '@/lib/format'; import { DataColumn, DataTable } from '@umami/react-zen'; import { ReactNode } from 'react'; +import styles from './ListExpandedTable.module.css'; export interface ListExpandedTableProps { data?: any[]; title?: string; + type?: string; renderLabel?: (row: any, index: number) => ReactNode; } -export function ListExpandedTable({ data = [], title, renderLabel }: ListExpandedTableProps) { +export function ListExpandedTable({ data = [], title, type, renderLabel }: ListExpandedTableProps) { const { formatMessage, labels } = useMessages(); return ( - + {row => renderLabel - ? renderLabel({ x: row?.label, country: row?.['country'] }, Number(row.id)) - : (row.label ?? formatMessage(labels.unknown)) + ? renderLabel({ x: row?.['name'], country: row?.['country'] }, Number(row.id)) + : (row?.['name'] ?? formatMessage(labels.unknown)) } @@ -30,18 +32,26 @@ export function ListExpandedTable({ data = [], title, renderLabel }: ListExpande {row => row?.['pageviews']?.toLocaleString()} - - {row => { - const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100; - return Math.round(+n) + '%'; - }} - - - {row => { - const n = (row?.['totaltime'] / row?.['visits']) * 100; - return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`; - }} - + {type !== 'exit' && type !== 'entry' ? ( + + {row => { + const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100; + return Math.round(+n) + '%'; + }} + + ) : ( + <> + )} + {type !== 'exit' && type !== 'entry' ? ( + + {row => { + const n = (row?.['totaltime'] / row?.['visits']) * 100; + return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`; + }} + + ) : ( + <> + )} ); } diff --git a/src/components/metrics/MetricsTable.tsx b/src/components/metrics/MetricsTable.tsx index 760a0da6..fb97f8db 100644 --- a/src/components/metrics/MetricsTable.tsx +++ b/src/components/metrics/MetricsTable.tsx @@ -56,7 +56,6 @@ export function MetricsTable({ websiteId, { type, - limit: 30, search: searchFormattedValues ? undefined : search, ...params, }, @@ -111,6 +110,8 @@ export function MetricsTable({ return []; }, [data, dataFilter, search, limit, formatValue, type]); + const downloadData = expanded ? data : filteredData; + return ( @@ -118,12 +119,12 @@ export function MetricsTable({ {allowSearch && } {children} - {allowDownload && } + {allowDownload && } {data && (expanded ? ( - + ) : ( ))} diff --git a/src/components/metrics/QueryParametersTable.tsx b/src/components/metrics/QueryParametersTable.tsx index e6d85495..c33c23cf 100644 --- a/src/components/metrics/QueryParametersTable.tsx +++ b/src/components/metrics/QueryParametersTable.tsx @@ -58,6 +58,7 @@ export function QueryParametersTable({ dataFilter={filters[filter]} renderLabel={renderLabel} delay={0} + expanded={false} > {allowFilter && } diff --git a/src/lib/clickhouse.ts b/src/lib/clickhouse.ts index bb184d6b..bcb02d0d 100644 --- a/src/lib/clickhouse.ts +++ b/src/lib/clickhouse.ts @@ -90,7 +90,11 @@ function mapFilter(column: string, operator: string, name: string, type: string function getFilterQuery(filters: Record, options: QueryOptions = {}) { const query = filtersToArray(filters, options).reduce((arr, { name, column, operator }) => { if (column) { - arr.push(`and ${mapFilter(column, operator, name)}`); + if (name === 'eventType') { + arr.push(`and ${mapFilter(column, operator, name, 'UInt32')}`); + } else { + arr.push(`and ${mapFilter(column, operator, name)}`); + } if (name === 'referrer') { arr.push(`and referrer_domain != hostname`); diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 1564458d..16bb71af 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -35,7 +35,7 @@ export const EVENT_COLUMNS = [ 'query', 'event', 'tag', - 'host', + 'hostname', ]; export const SESSION_COLUMNS = [ diff --git a/src/queries/index.ts b/src/queries/index.ts index 52ca6513..707dc874 100644 --- a/src/queries/index.ts +++ b/src/queries/index.ts @@ -11,6 +11,7 @@ export * from '@/queries/sql/events/getEventDataValues'; export * from '@/queries/sql/events/getEventDataStats'; export * from '@/queries/sql/events/getEventDataUsage'; export * from '@/queries/sql/events/getEventMetrics'; +export * from '@/queries/sql/events/getEventExpandedMetrics'; export * from '@/queries/sql/events/getEventStats'; export * from '@/queries/sql/events/getWebsiteEvents'; export * from '@/queries/sql/events/getEventUsage'; @@ -21,6 +22,7 @@ export * from '@/queries/sql/reports/getRetention'; export * from '@/queries/sql/reports/getBreakdown'; export * from '@/queries/sql/reports/getUTM'; export * from '@/queries/sql/pageviews/getPageviewMetrics'; +export * from '@/queries/sql/pageviews/getPageviewExpandedMetrics'; export * from '@/queries/sql/pageviews/getPageviewStats'; export * from '@/queries/sql/sessions/createSession'; export * from '@/queries/sql/sessions/getWebsiteSession'; @@ -37,6 +39,7 @@ export * from '@/queries/sql/sessions/getSessionStats'; export * from '@/queries/sql/sessions/saveSessionData'; export * from '@/queries/sql/getActiveVisitors'; export * from '@/queries/sql/getChannelMetrics'; +export * from '@/queries/sql/getChannelExpandedMetrics'; export * from '@/queries/sql/getRealtimeActivity'; export * from '@/queries/sql/getRealtimeData'; export * from '@/queries/sql/getValues'; diff --git a/src/queries/sql/events/getEventExpandedMetrics.ts b/src/queries/sql/events/getEventExpandedMetrics.ts new file mode 100644 index 00000000..235822b8 --- /dev/null +++ b/src/queries/sql/events/getEventExpandedMetrics.ts @@ -0,0 +1,113 @@ +import clickhouse from '@/lib/clickhouse'; +import { EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; +import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; +import prisma from '@/lib/prisma'; +import { QueryFilters } from '@/lib/types'; + +export interface EventExpandedMetricParameters { + type: string; + limit?: string; + offset?: string; +} + +export interface EventExpandedMetricData { + name: string; + pageviews: number; + visitors: number; + visits: number; + bounces: number; + totaltime: number; +} + +export async function getEventExpandedMetrics( + ...args: [websiteId: string, parameters: EventExpandedMetricParameters, filters: QueryFilters] +): Promise { + return runQuery({ + [PRISMA]: () => relationalQuery(...args), + [CLICKHOUSE]: () => clickhouseQuery(...args), + }); +} + +async function relationalQuery( + websiteId: string, + parameters: EventExpandedMetricParameters, + filters: QueryFilters, +) { + const { type, limit = 500, offset = 0 } = parameters; + const column = FILTER_COLUMNS[type] || type; + const { rawQuery, parseFilters } = prisma; + const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters( + { + ...filters, + websiteId, + eventType: EVENT_TYPE.customEvent, + }, + { joinSession: SESSION_COLUMNS.includes(type) }, + ); + + return rawQuery( + ` + select ${column} x, + count(*) as y + from website_event + ${cohortQuery} + ${joinSessionQuery} + where website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + and event_type = {{eventType}} + ${filterQuery} + group by 1 + order by 2 desc + limit ${limit} + offset ${offset} + `, + queryParams, + ); +} + +async function clickhouseQuery( + websiteId: string, + parameters: EventExpandedMetricParameters, + filters: QueryFilters, +): Promise { + const { type, limit = 500, offset = 0 } = parameters; + const column = FILTER_COLUMNS[type] || type; + const { rawQuery, parseFilters } = clickhouse; + const { filterQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + }); + + return rawQuery( + ` + select + name, + sum(t.c) as "pageviews", + uniq(t.session_id) as "visitors", + uniq(t.visit_id) as "visits", + sum(if(t.c = 1, 1, 0)) as "bounces", + sum(max_time-min_time) as "totaltime" + from ( + select + ${column} name, + session_id, + visit_id, + count(*) c, + min(created_at) min_time, + max(created_at) max_time + from website_event + ${cohortQuery} + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and name != '' + ${filterQuery} + group by name, session_id, visit_id + ) as t + group by name + order by visitors desc, visits desc + limit ${limit} + offset ${offset} + `, + { ...queryParams, ...parameters }, + ); +} diff --git a/src/queries/sql/events/getEventMetrics.ts b/src/queries/sql/events/getEventMetrics.ts index 73af2278..3d148edf 100644 --- a/src/queries/sql/events/getEventMetrics.ts +++ b/src/queries/sql/events/getEventMetrics.ts @@ -83,7 +83,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by x order by y desc diff --git a/src/queries/sql/events/getEventStats.ts b/src/queries/sql/events/getEventStats.ts index ad6b155d..8d26dcfc 100644 --- a/src/queries/sql/events/getEventStats.ts +++ b/src/queries/sql/events/getEventStats.ts @@ -72,7 +72,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by x, t order by t diff --git a/src/queries/sql/getChannelExpandedMetrics.ts b/src/queries/sql/getChannelExpandedMetrics.ts new file mode 100644 index 00000000..d8fce3d2 --- /dev/null +++ b/src/queries/sql/getChannelExpandedMetrics.ts @@ -0,0 +1,162 @@ +import clickhouse from '@/lib/clickhouse'; +import { + EMAIL_DOMAINS, + EVENT_TYPE, + PAID_AD_PARAMS, + SEARCH_DOMAINS, + SHOPPING_DOMAINS, + SOCIAL_DOMAINS, + VIDEO_DOMAINS, +} from '@/lib/constants'; +import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; +import prisma from '@/lib/prisma'; +import { QueryFilters } from '@/lib/types'; + +export interface ChannelExpandedMetricsParameters { + limit?: number | string; + offset?: number | string; +} + +export interface ChannelExpandedMetricsData { + name: string; + pageviews: number; + visitors: number; + visits: number; + bounces: number; + totaltime: number; +} + +export async function getChannelExpandedMetrics( + ...args: [websiteId: string, parameters: ChannelExpandedMetricsParameters, filters?: QueryFilters] +): Promise { + return runQuery({ + [PRISMA]: () => relationalQuery(...args), + [CLICKHOUSE]: () => clickhouseQuery(...args), + }); +} + +async function relationalQuery( + websiteId: string, + parameters: ChannelExpandedMetricsParameters, + filters: QueryFilters, +): Promise { + const { rawQuery, parseFilters } = prisma; + const { queryParams, filterQuery, cohortQuery, dateQuery } = parseFilters({ + ...filters, + websiteId, + eventType: EVENT_TYPE.pageView, + }); + + return rawQuery( + ` + WITH channels as ( + select case when ${toPostgresPositionClause('utm_medium', ['cp', 'ppc', 'retargeting', 'paid'])} then 'paid' else 'organic' end prefix, + case + when referrer_domain = '' and url_query = '' then 'direct' + when ${toPostgresPositionClause('url_query', PAID_AD_PARAMS)} then 'paidAds' + when ${toPostgresPositionClause('utm_medium', ['referral', 'app', 'link'])} then 'referral' + when position(utm_medium, 'affiliate') > 0 then 'affiliate' + when position(utm_medium, 'sms') > 0 or position(utm_source, 'sms') > 0 then 'sms' + when ${toPostgresPositionClause('referrer_domain', SEARCH_DOMAINS)} or position(utm_medium, 'organic') > 0 then concat(prefix, 'Search') + when ${toPostgresPositionClause('referrer_domain', SOCIAL_DOMAINS)} then concat(prefix, 'Social') + when ${toPostgresPositionClause('referrer_domain', EMAIL_DOMAINS)} or position(utm_medium, 'mail') > 0 then 'email' + when ${toPostgresPositionClause('referrer_domain', SHOPPING_DOMAINS)} or position(utm_medium, 'shop') > 0 then concat(prefix, 'Shopping') + when ${toPostgresPositionClause('referrer_domain', VIDEO_DOMAINS)} or position(utm_medium, 'video') > 0 then concat(prefix, 'Video') + else '' end AS x, + count(distinct session_id) y + from website_event + ${cohortQuery} + where website_id = {{websiteId::uuid}} + and event_type = {{eventType}} + ${dateQuery} + ${filterQuery} + group by 1, 2 + order by y desc) + + select x, sum(y) y + from channels + where x != '' + group by x + order by y desc; + `, + { ...queryParams, ...parameters }, + ); +} + +async function clickhouseQuery( + websiteId: string, + parameters: ChannelExpandedMetricsParameters, + filters: QueryFilters, +): Promise { + const { limit = 500, offset = 0 } = parameters; + const { rawQuery, parseFilters } = clickhouse; + const { queryParams, filterQuery, cohortQuery } = parseFilters({ + ...filters, + websiteId, + eventType: EVENT_TYPE.pageView, + }); + + return rawQuery( + ` + select + name, + sum(t.c) as "pageviews", + uniq(t.session_id) as "visitors", + uniq(t.visit_id) as "visits", + sum(if(t.c = 1, 1, 0)) as "bounces", + sum(max_time-min_time) as "totaltime" + from ( + select case when multiSearchAny(utm_medium, ['cp', 'ppc', 'retargeting', 'paid']) != 0 then 'paid' else 'organic' end prefix, + case + when referrer_domain = '' and url_query = '' then 'direct' + when multiSearchAny(url_query, [${toClickHouseStringArray( + PAID_AD_PARAMS, + )}]) != 0 then 'paidAds' + when multiSearchAny(utm_medium, ['referral', 'app','link']) != 0 then 'referral' + when position(utm_medium, 'affiliate') > 0 then 'affiliate' + when position(utm_medium, 'sms') > 0 or position(utm_source, 'sms') > 0 then 'sms' + when multiSearchAny(referrer_domain, [${toClickHouseStringArray( + SEARCH_DOMAINS, + )}]) != 0 or position(utm_medium, 'organic') > 0 then concat(prefix, 'Search') + when multiSearchAny(referrer_domain, [${toClickHouseStringArray( + SOCIAL_DOMAINS, + )}]) != 0 then concat(prefix, 'Social') + when multiSearchAny(referrer_domain, [${toClickHouseStringArray( + EMAIL_DOMAINS, + )}]) != 0 or position(utm_medium, 'mail') > 0 then 'email' + when multiSearchAny(referrer_domain, [${toClickHouseStringArray( + SHOPPING_DOMAINS, + )}]) != 0 or position(utm_medium, 'shop') > 0 then concat(prefix, 'Shopping') + when multiSearchAny(referrer_domain, [${toClickHouseStringArray( + VIDEO_DOMAINS, + )}]) != 0 or position(utm_medium, 'video') > 0 then concat(prefix, 'Video') + else '' end AS name, + session_id, + visit_id, + count(*) c, + min(created_at) min_time, + max(created_at) max_time + from website_event + ${cohortQuery} + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and name != '' + ${filterQuery} + group by prefix, name, session_id, visit_id + ) as t + group by name + order by visitors desc, visits desc + limit ${limit} + offset ${offset} + `, + { ...queryParams, ...parameters }, + ); +} + +function toClickHouseStringArray(arr: string[]): string { + return arr.map(p => `'${p.replace(/'/g, "\\'")}'`).join(', '); +} + +function toPostgresPositionClause(column: string, arr: string[]) { + return arr.map(val => `position(${column}, '${val.replace(/'/g, "''")}') > 0`).join(' OR\n '); +} diff --git a/src/queries/sql/getChannelMetrics.ts b/src/queries/sql/getChannelMetrics.ts index c240cc86..9e6ba82c 100644 --- a/src/queries/sql/getChannelMetrics.ts +++ b/src/queries/sql/getChannelMetrics.ts @@ -105,7 +105,6 @@ async function clickhouseQuery( from website_event ${cohortQuery} where website_id = {websiteId:UUID} - and event_type = {eventType:UInt32} ${dateQuery} ${filterQuery} group by 1, 2 diff --git a/src/queries/sql/getWebsiteStats.ts b/src/queries/sql/getWebsiteStats.ts index 24242ad6..4fa15a3c 100644 --- a/src/queries/sql/getWebsiteStats.ts +++ b/src/queries/sql/getWebsiteStats.ts @@ -94,7 +94,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by session_id, visit_id ) as t; @@ -117,7 +116,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by session_id, visit_id ) as t; diff --git a/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts b/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts new file mode 100644 index 00000000..ebe31d7b --- /dev/null +++ b/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts @@ -0,0 +1,166 @@ +import clickhouse from '@/lib/clickhouse'; +import { EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; +import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; +import prisma from '@/lib/prisma'; +import { QueryFilters } from '@/lib/types'; + +export interface PageviewExpandedMetricsParameters { + type: string; + limit?: number | string; + offset?: number | string; +} + +export interface PageviewExpandedMetricsData { + name: string; + pageviews: number; + visitors: number; + visits: number; + bounces: number; + totaltime: number; +} + +export async function getPageviewExpandedMetrics( + ...args: [websiteId: string, parameters: PageviewExpandedMetricsParameters, filters: QueryFilters] +) { + return runQuery({ + [PRISMA]: () => relationalQuery(...args), + [CLICKHOUSE]: () => clickhouseQuery(...args), + }); +} + +async function relationalQuery( + websiteId: string, + parameters: PageviewExpandedMetricsParameters, + filters: QueryFilters, +): Promise { + const { type, limit = 500, offset = 0 } = parameters; + const column = FILTER_COLUMNS[type] || type; + const { rawQuery, parseFilters } = prisma; + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters( + { + ...filters, + websiteId, + eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView, + }, + { joinSession: SESSION_COLUMNS.includes(type) }, + ); + + let entryExitQuery = ''; + let excludeDomain = ''; + + if (column === 'referrer_domain') { + excludeDomain = `and website_event.referrer_domain != website_event.hostname + and website_event.referrer_domain != ''`; + } + + if (type === 'entry' || type === 'exit') { + const aggregrate = type === 'entry' ? 'min' : 'max'; + + entryExitQuery = ` + join ( + select visit_id, + ${aggregrate}(created_at) target_created_at + from website_event + where website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + and event_type = {{eventType}} + group by visit_id + ) x + on x.visit_id = website_event.visit_id + and x.target_created_at = website_event.created_at + `; + } + + return rawQuery( + ` + select ${column} x, + count(distinct website_event.session_id) as y + from website_event + ${joinSessionQuery} + ${cohortQuery} + ${entryExitQuery} + where website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + and event_type = {{eventType}} + ${excludeDomain} + ${filterQuery} + group by 1 + order by 2 desc + limit ${limit} + offset ${offset} + `, + queryParams, + ); +} + +async function clickhouseQuery( + websiteId: string, + parameters: PageviewExpandedMetricsParameters, + filters: QueryFilters, +): Promise<{ x: string; y: number }[]> { + const { type, limit = 500, offset = 0 } = parameters; + const column = FILTER_COLUMNS[type] || type; + const { rawQuery, parseFilters } = clickhouse; + const { filterQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView, + }); + + let excludeDomain = ''; + let entryExitQuery = ''; + + if (column === 'referrer_domain') { + excludeDomain = `and referrer_domain != hostname and referrer_domain != ''`; + } + + if (type === 'entry' || type === 'exit') { + const aggregrate = type === 'entry' ? 'min' : 'max'; + + entryExitQuery = ` + JOIN (select visit_id, + ${aggregrate}(created_at) target_created_at + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and event_type = {eventType:UInt32} + group by visit_id) x + ON x.visit_id = website_event.visit_id + and x.target_created_at = website_event.created_at`; + } + + return rawQuery( + ` + select + name, + sum(t.c) as "pageviews", + uniq(t.session_id) as "visitors", + uniq(t.visit_id) as "visits", + sum(if(t.c = 1, 1, 0)) as "bounces", + sum(max_time-min_time) as "totaltime" + from ( + select + ${column} name, + session_id, + visit_id, + count(*) c, + min(created_at) min_time, + max(created_at) max_time + from website_event + ${cohortQuery} + ${entryExitQuery} + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and name != '' + ${excludeDomain} + ${filterQuery} + group by name, session_id, visit_id + ) as t + group by name + order by visitors desc, visits desc + limit ${limit} + offset ${offset} + `, + { ...queryParams, ...parameters }, + ); +} diff --git a/src/queries/sql/pageviews/getPageviewMetrics.ts b/src/queries/sql/pageviews/getPageviewMetrics.ts index fd485685..4ebd4cd9 100644 --- a/src/queries/sql/pageviews/getPageviewMetrics.ts +++ b/src/queries/sql/pageviews/getPageviewMetrics.ts @@ -136,7 +136,6 @@ async function clickhouseQuery( ${entryExitQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${excludeDomain} ${filterQuery} group by x @@ -174,7 +173,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${excludeDomain} ${filterQuery} ${groupByQuery}) as g diff --git a/src/queries/sql/pageviews/getPageviewStats.ts b/src/queries/sql/pageviews/getPageviewStats.ts index 704dea1e..e9e763e8 100644 --- a/src/queries/sql/pageviews/getPageviewStats.ts +++ b/src/queries/sql/pageviews/getPageviewStats.ts @@ -66,7 +66,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by t ) as g @@ -85,7 +84,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by t ) as g diff --git a/src/queries/sql/reports/getAttribution.ts b/src/queries/sql/reports/getAttribution.ts index df452343..0bfbd58b 100644 --- a/src/queries/sql/reports/getAttribution.ts +++ b/src/queries/sql/reports/getAttribution.ts @@ -477,7 +477,6 @@ async function clickhouseQuery( where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} and ${column} = {step:String} - and event_type = {eventType:UInt32} ${filterQuery} `, queryParams, diff --git a/src/queries/sql/reports/getBreakdown.ts b/src/queries/sql/reports/getBreakdown.ts index a39c49ef..7cae67a1 100644 --- a/src/queries/sql/reports/getBreakdown.ts +++ b/src/queries/sql/reports/getBreakdown.ts @@ -115,7 +115,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by ${parseFieldsByName(fields)}, session_id, visit_id diff --git a/src/queries/sql/sessions/getSessionExpandedMetrics.ts b/src/queries/sql/sessions/getSessionExpandedMetrics.ts index ba0841dc..7c6d98f6 100644 --- a/src/queries/sql/sessions/getSessionExpandedMetrics.ts +++ b/src/queries/sql/sessions/getSessionExpandedMetrics.ts @@ -11,7 +11,7 @@ export interface SessionExpandedMetricsParameters { } export interface SessionExpandedMetricsData { - label: string; + name: string; pageviews: number; visitors: number; visits: number; @@ -34,7 +34,7 @@ async function relationalQuery( filters: QueryFilters, ): Promise { const { type, limit = 500, offset = 0 } = parameters; - const column = FILTER_COLUMNS[type] || type; + let column = FILTER_COLUMNS[type] || type; const { parseFilters, rawQuery } = prisma; const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters( { @@ -48,6 +48,10 @@ async function relationalQuery( ); const includeCountry = column === 'city' || column === 'region'; + if (type === 'language') { + column = `lower(left(${type}, 2))`; + } + return rawQuery( ` select @@ -77,7 +81,7 @@ async function clickhouseQuery( filters: QueryFilters, ): Promise { const { type, limit = 500, offset = 0 } = parameters; - const column = FILTER_COLUMNS[type] || type; + let column = FILTER_COLUMNS[type] || type; const { parseFilters, rawQuery } = clickhouse; const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, @@ -86,10 +90,14 @@ async function clickhouseQuery( }); const includeCountry = column === 'city' || column === 'region'; + if (type === 'language') { + column = `lower(left(${type}, 2))`; + } + return rawQuery( ` select - label, + name, ${includeCountry ? 'country,' : ''} sum(t.c) as "pageviews", uniq(t.session_id) as "visitors", @@ -98,7 +106,7 @@ async function clickhouseQuery( sum(max_time-min_time) as "totaltime" from ( select - ${column} label, + ${column} name, ${includeCountry ? 'country,' : ''} session_id, visit_id, @@ -109,13 +117,12 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} - and label != '' + and name != '' ${filterQuery} - group by label, session_id, visit_id + group by name, session_id, visit_id ${includeCountry ? ', country' : ''} ) as t - group by label + group by name ${includeCountry ? ', country' : ''} order by visitors desc, visits desc limit ${limit} diff --git a/src/queries/sql/sessions/getSessionMetrics.ts b/src/queries/sql/sessions/getSessionMetrics.ts index 55962310..725c7379 100644 --- a/src/queries/sql/sessions/getSessionMetrics.ts +++ b/src/queries/sql/sessions/getSessionMetrics.ts @@ -25,7 +25,7 @@ async function relationalQuery( filters: QueryFilters, ) { const { type, limit = 500, offset = 0 } = parameters; - const column = FILTER_COLUMNS[type] || type; + let column = FILTER_COLUMNS[type] || type; const { parseFilters, rawQuery } = prisma; const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters( { @@ -39,6 +39,10 @@ async function relationalQuery( ); const includeCountry = column === 'city' || column === 'region'; + if (type === 'language') { + column = `lower(left(${type}, 2))`; + } + return rawQuery( ` select @@ -68,7 +72,7 @@ async function clickhouseQuery( filters: QueryFilters, ): Promise<{ x: string; y: number }[]> { const { type, limit = 500, offset = 0 } = parameters; - const column = FILTER_COLUMNS[type] || type; + let column = FILTER_COLUMNS[type] || type; const { parseFilters, rawQuery } = clickhouse; const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, @@ -77,6 +81,10 @@ async function clickhouseQuery( }); const includeCountry = column === 'city' || column === 'region'; + if (type === 'language') { + column = `lower(left(${type}, 2))`; + } + let sql = ''; if (EVENT_COLUMNS.some(item => Object.keys(filters).includes(item))) { @@ -89,7 +97,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by x ${includeCountry ? ', country' : ''} @@ -107,7 +114,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by x ${includeCountry ? ', country' : ''} diff --git a/src/queries/sql/sessions/getSessionStats.ts b/src/queries/sql/sessions/getSessionStats.ts index 258de290..97a8755e 100644 --- a/src/queries/sql/sessions/getSessionStats.ts +++ b/src/queries/sql/sessions/getSessionStats.ts @@ -66,7 +66,6 @@ async function clickhouseQuery( ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by t ) as g @@ -84,7 +83,6 @@ async function clickhouseQuery( from website_event_stats_hourly as website_event where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = {eventType:UInt32} ${filterQuery} group by t ) as g From eb7b6978d35e997c5494d023a5af7e2fdbb90fce Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 7 Aug 2025 05:14:35 -0700 Subject: [PATCH 146/399] New settings layouts. Segment management screen. --- next.config.ts | 7 +- package.json | 2 +- pnpm-lock.yaml | 18 ++--- src/app/(main)/App.tsx | 2 - src/app/(main)/SideNav.tsx | 36 ++++----- src/app/(main)/admin/AdminLayout.tsx | 63 ++++++++------- src/app/(main)/admin/teams/AdminTeamsPage.tsx | 11 ++- .../(main)/admin/teams/AdminTeamsTable.tsx | 4 +- .../admin/teams/[teamId]/AdminTeamPage.tsx | 2 +- src/app/(main)/admin/users/UsersPage.tsx | 13 ++-- .../admin/users/[userId]/UserHeader.tsx | 10 +++ .../(main)/admin/users/[userId]/UserPage.tsx | 10 ++- .../admin/users/[userId]/UserSettings.tsx | 12 +-- .../admin/websites/AdminWebsitesPage.tsx | 11 ++- .../admin/websites/AdminWebsitesTable.tsx | 2 +- .../websites/[websiteId]/AdminWebsitePage.tsx | 5 +- .../admin/websites/[websiteId]/page.tsx | 4 +- src/app/(main)/settings/SettingsLayout.tsx | 64 +++++++++------ .../preferences/PreferenceSettings.tsx | 11 +-- .../settings/preferences/PreferencesPage.tsx | 11 ++- .../(main)/settings/profile/ProfilePage.tsx | 11 ++- .../settings/profile/ProfileSettings.tsx | 2 - src/app/(main)/settings/teams/TeamsHeader.tsx | 6 +- .../settings/teams/TeamsSettingsPage.tsx | 7 +- src/app/(main)/settings/teams/TeamsTable.tsx | 6 +- .../settings/teams/[teamId]/TeamDetails.tsx | 54 +++++++------ .../settings/teams/[teamId]/TeamEditForm.tsx | 2 +- .../teams/[teamId]/TeamMemberEditButton.tsx | 38 ++++----- .../teams/[teamId]/TeamMemberRemoveButton.tsx | 44 +++++------ .../teams/[teamId]/TeamProvider.tsx | 0 .../teams/[teamId]/TeamSettingsPage.tsx | 2 +- .../teams/[teamId]/TeamWebsitesTable.tsx | 47 +---------- .../settings/websites/WebsitesTable.tsx | 2 +- .../websites/[websiteId]/WebsiteData.tsx | 37 ++++----- .../websites/[websiteId]/WebsiteSettings.tsx | 63 ++++++--------- .../[websiteId]/WebsiteSettingsHeader.tsx | 10 +++ .../[websiteId]/WebsiteSettingsPage.tsx | 10 ++- src/app/(main)/teams/[teamId]/layout.tsx | 18 ----- .../[websiteId]/WebsiteFilterButton.tsx | 2 +- .../websites/[websiteId]/WebsiteHeader.tsx | 10 ++- .../websites/[websiteId]/WebsiteLayout.tsx | 16 ++-- .../websites/[websiteId]/WebsiteNav.tsx | 75 +++++++----------- .../[websiteId]/events/EventsDataTable.tsx | 2 +- .../[websiteId]/realtime/RealtimeLog.tsx | 2 +- .../[websiteId]/realtime/RealtimeUrls.tsx | 2 +- .../[websiteId]/segments/SegmentAddButton.tsx | 2 +- .../segments/SegmentDeleteButton.tsx | 55 +++++++++++++ .../segments/SegmentEditButton.tsx | 34 ++++++++ .../[websiteId]/segments/SegmentEditForm.tsx | 47 +++++++---- .../[websiteId]/segments/SegmentsTable.tsx | 38 ++++----- .../[websiteId]/settings/SettingsPage.tsx | 25 ++++++ .../websites/[websiteId]/settings/page.tsx | 12 +++ src/components/common/PageHeader.tsx | 2 +- src/components/common/SideMenu.tsx | 77 ++++++++++++++----- src/components/icons.ts | 1 + src/components/input/ActionButton.tsx | 26 +++++++ src/components/input/DeleteButton.tsx | 0 src/components/input/FilterBar.tsx | 56 +++++++++++--- .../{common => input}/FilterButtons.tsx | 0 .../{common => input}/FilterEditForm.tsx | 4 +- src/components/input/ProfileButton.tsx | 31 +++++--- src/components/input/SegmentFilters.tsx | 28 ++++--- src/components/input/SegmentSaveButton.tsx | 26 +++++++ src/components/input/TeamsButton.tsx | 13 +++- src/components/input/WebsiteSelect.tsx | 4 +- src/components/messages.ts | 4 + src/components/metrics/PagesTable.tsx | 2 +- .../metrics/QueryParametersTable.tsx | 2 +- src/components/metrics/ReferrersTable.tsx | 2 +- src/index.ts | 4 +- 70 files changed, 762 insertions(+), 499 deletions(-) create mode 100644 src/app/(main)/admin/users/[userId]/UserHeader.tsx rename src/app/(main)/{ => settings}/teams/[teamId]/TeamProvider.tsx (100%) create mode 100644 src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsHeader.tsx delete mode 100644 src/app/(main)/teams/[teamId]/layout.tsx create mode 100644 src/app/(main)/websites/[websiteId]/segments/SegmentDeleteButton.tsx create mode 100644 src/app/(main)/websites/[websiteId]/segments/SegmentEditButton.tsx create mode 100644 src/app/(main)/websites/[websiteId]/settings/SettingsPage.tsx create mode 100644 src/app/(main)/websites/[websiteId]/settings/page.tsx create mode 100644 src/components/input/ActionButton.tsx delete mode 100644 src/components/input/DeleteButton.tsx rename src/components/{common => input}/FilterButtons.tsx (100%) rename src/components/{common => input}/FilterEditForm.tsx (96%) create mode 100644 src/components/input/SegmentSaveButton.tsx diff --git a/next.config.ts b/next.config.ts index 77a0c1c6..278e7a6d 100644 --- a/next.config.ts +++ b/next.config.ts @@ -97,7 +97,12 @@ const headers = [ }, ]; -const rewrites = []; +const rewrites = [ + { + source: '/teams/:id/settings/:path*', + destination: '/settings/:path*', + }, +]; if (trackerScriptURL) { rewrites.push({ diff --git a/package.json b/package.json index bf0bad76..c2c9b3cc 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "@react-spring/web": "^9.7.3", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.83.0", - "@umami/react-zen": "^0.154.0", + "@umami/react-zen": "^0.157.0", "@umami/redis-client": "^0.27.0", "bcryptjs": "^3.0.2", "chalk": "^5.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cd379179..fce70ca0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^5.83.0 version: 5.83.0(react@19.1.0) '@umami/react-zen': - specifier: ^0.154.0 - version: 0.154.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) + specifier: ^0.157.0 + version: 0.157.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) '@umami/redis-client': specifier: ^0.27.0 version: 0.27.0 @@ -2544,8 +2544,8 @@ packages: resolution: {integrity: sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@umami/react-zen@0.154.0': - resolution: {integrity: sha512-waVMJNwGPSDereFWTnbtdJjQGQhJIi1n7Hs2EnuS9OSMUbj9THgA1A9722zyO3w46KmbIBMqmIxur4ykpHOYlg==} + '@umami/react-zen@0.157.0': + resolution: {integrity: sha512-QZqZcah1t6KniDvFTF+GxBDkaEYUuQOyj1olao5p5rtZBMW1/v4GaVcL+8UAzWyWIUnsrRI3e5HoytapJg6VfQ==} '@umami/redis-client@0.27.0': resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==} @@ -5984,8 +5984,8 @@ packages: peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-hook-form@7.61.1: - resolution: {integrity: sha512-2vbXUFDYgqEgM2RcXcAT2PwDW/80QARi+PKmHy5q2KhuKvOlG8iIYgf7eIlIANR5trW9fJbP4r5aub3a4egsew==} + react-hook-form@7.62.0: + resolution: {integrity: sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -9751,7 +9751,7 @@ snapshots: '@typescript-eslint/types': 8.38.0 eslint-visitor-keys: 4.2.1 - '@umami/react-zen@0.154.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': + '@umami/react-zen@0.157.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': dependencies: '@fontsource/jetbrains-mono': 5.2.6 '@internationalized/date': 3.8.2 @@ -9765,7 +9765,7 @@ snapshots: react: 19.1.0 react-aria-components: 1.9.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-dom: 19.1.0(react@19.1.0) - react-hook-form: 7.61.1(react@19.1.0) + react-hook-form: 7.62.0(react@19.1.0) react-icons: 5.5.0(react@19.1.0) thenby: 1.3.4 zustand: 5.0.6(@types/react@19.1.8)(immer@9.0.21)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)) @@ -13763,7 +13763,7 @@ snapshots: dependencies: react: 19.1.0 - react-hook-form@7.61.1(react@19.1.0): + react-hook-form@7.62.0(react@19.1.0): dependencies: react: 19.1.0 diff --git a/src/app/(main)/App.tsx b/src/app/(main)/App.tsx index e3602d5a..bb33dc87 100644 --- a/src/app/(main)/App.tsx +++ b/src/app/(main)/App.tsx @@ -4,7 +4,6 @@ import Script from 'next/script'; import { usePathname } from 'next/navigation'; import { UpdateNotice } from './UpdateNotice'; import { SideNav } from '@/app/(main)/SideNav'; -import { TopNav } from '@/app/(main)/TopNav'; import { useLoginQuery, useConfig } from '@/components/hooks'; export function App({ children }) { @@ -31,7 +30,6 @@ export function App({ children }) { - {children} diff --git a/src/app/(main)/SideNav.tsx b/src/app/(main)/SideNav.tsx index 25f5a4ab..06b0abc9 100644 --- a/src/app/(main)/SideNav.tsx +++ b/src/app/(main)/SideNav.tsx @@ -17,15 +17,20 @@ import { LockKeyhole, } from '@/components/icons'; import { useMessages, useNavigation, useGlobalState } from '@/components/hooks'; -import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav'; import { TeamsButton } from '@/components/input/TeamsButton'; import { PanelButton } from '@/components/input/PanelButton'; export function SideNav(props: SidebarProps) { const { formatMessage, labels } = useMessages(); - const { pathname, renderUrl, websiteId, teamId } = useNavigation(); + const { pathname, renderUrl, websiteId } = useNavigation(); const [isCollapsed] = useGlobalState('sidenav-collapsed'); - const isWebsite = websiteId && !pathname.includes('/settings'); + + const hasNav = !!( + websiteId || + pathname.startsWith('/admin') || + pathname.startsWith('/settings') || + pathname.endsWith('/settings') + ); const links = [ { @@ -71,12 +76,7 @@ export function SideNav(props: SidebarProps) { return ( - + } /> @@ -90,23 +90,21 @@ export function SideNav(props: SidebarProps) { })} - {!teamId && - bottomLinks.map(({ id, path, label, icon }) => { - return ( - - - - ); - })} + {bottomLinks.map(({ id, path, label, icon }) => { + return ( + + + + ); + })} - + - {isWebsite && } ); } diff --git a/src/app/(main)/admin/AdminLayout.tsx b/src/app/(main)/admin/AdminLayout.tsx index 9dfc118c..87abd77b 100644 --- a/src/app/(main)/admin/AdminLayout.tsx +++ b/src/app/(main)/admin/AdminLayout.tsx @@ -2,9 +2,8 @@ import { ReactNode } from 'react'; import { Grid, Column } from '@umami/react-zen'; import { useLoginQuery, useMessages, useNavigation } from '@/components/hooks'; +import { User, Users, Globe } from '@/components/icons'; import { SideMenu } from '@/components/common/SideMenu'; -import { PageHeader } from '@/components/common/PageHeader'; -import { Panel } from '@/components/common/Panel'; import { PageBody } from '@/components/common/PageBody'; export function AdminLayout({ children }: { children: ReactNode }) { @@ -18,37 +17,45 @@ export function AdminLayout({ children }: { children: ReactNode }) { const items = [ { - id: 'users', - label: formatMessage(labels.users), - url: '/admin/users', - }, - { - id: 'websites', - label: formatMessage(labels.websites), - url: '/admin/websites', - }, - { - id: 'teams', - label: formatMessage(labels.teams), - url: '/admin/teams', + label: formatMessage(labels.application), + items: [ + { + id: 'users', + label: formatMessage(labels.users), + path: '/admin/users', + icon: , + }, + { + id: 'websites', + label: formatMessage(labels.websites), + path: '/admin/websites', + icon: , + }, + { + id: 'teams', + label: formatMessage(labels.teams), + path: '/admin/teams', + icon: , + }, + ], }, ]; - const value = items.find(({ url }) => pathname.includes(url))?.id; + const selectedKey = items + .flatMap(e => e.items) + ?.find(({ path }) => path && pathname.startsWith(path))?.id; return ( - - - - - - - - - {children} - - + + + - + {children} + ); } diff --git a/src/app/(main)/admin/teams/AdminTeamsPage.tsx b/src/app/(main)/admin/teams/AdminTeamsPage.tsx index 37f43c94..1d4984e8 100644 --- a/src/app/(main)/admin/teams/AdminTeamsPage.tsx +++ b/src/app/(main)/admin/teams/AdminTeamsPage.tsx @@ -1,16 +1,19 @@ 'use client'; import { AdminTeamsDataTable } from './AdminTeamsDataTable'; import { Column } from '@umami/react-zen'; -import { SectionHeader } from '@/components/common/SectionHeader'; import { useMessages } from '@/components/hooks'; +import { PageHeader } from '@/components/common/PageHeader'; +import { Panel } from '@/components/common/Panel'; export function AdminTeamsPage() { const { formatMessage, labels } = useMessages(); return ( - - - + + + + + ); } diff --git a/src/app/(main)/admin/teams/AdminTeamsTable.tsx b/src/app/(main)/admin/teams/AdminTeamsTable.tsx index da72955d..bacb7de8 100644 --- a/src/app/(main)/admin/teams/AdminTeamsTable.tsx +++ b/src/app/(main)/admin/teams/AdminTeamsTable.tsx @@ -32,7 +32,9 @@ export function AdminTeamsTable({ {(row: any) => ( - {row?.teamUser?.[0]?.user?.username} + + {row?.teamUser?.[0]?.user?.username} + )} diff --git a/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx b/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx index 7f680a91..a7c5b0e2 100644 --- a/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx +++ b/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx @@ -1,6 +1,6 @@ 'use client'; import { TeamDetails } from '@/app/(main)/settings/teams/[teamId]/TeamDetails'; -import { TeamProvider } from '@/app/(main)/teams/[teamId]/TeamProvider'; +import { TeamProvider } from '@/app/(main)/settings/teams/[teamId]/TeamProvider'; export function AdminTeamPage({ teamId }: { teamId: string }) { return ( diff --git a/src/app/(main)/admin/users/UsersPage.tsx b/src/app/(main)/admin/users/UsersPage.tsx index 5c8a1ae3..47ac5512 100644 --- a/src/app/(main)/admin/users/UsersPage.tsx +++ b/src/app/(main)/admin/users/UsersPage.tsx @@ -1,9 +1,10 @@ 'use client'; import { UsersDataTable } from './UsersDataTable'; import { Column } from '@umami/react-zen'; -import { SectionHeader } from '@/components/common/SectionHeader'; import { useMessages } from '@/components/hooks'; import { UserAddButton } from './UserAddButton'; +import { PageHeader } from '@/components/common/PageHeader'; +import { Panel } from '@/components/common/Panel'; export function UsersPage() { const { formatMessage, labels } = useMessages(); @@ -11,11 +12,13 @@ export function UsersPage() { const handleSave = () => {}; return ( - - + + - - + + + + ); } diff --git a/src/app/(main)/admin/users/[userId]/UserHeader.tsx b/src/app/(main)/admin/users/[userId]/UserHeader.tsx new file mode 100644 index 00000000..f9fcdd64 --- /dev/null +++ b/src/app/(main)/admin/users/[userId]/UserHeader.tsx @@ -0,0 +1,10 @@ +import { useContext } from 'react'; +import { User } from '@/components/icons'; +import { PageHeader } from '@/components/common/PageHeader'; +import { UserContext } from '@/app/(main)/admin/users/[userId]/UserProvider'; + +export function UserHeader() { + const user = useContext(UserContext); + + return } />; +} diff --git a/src/app/(main)/admin/users/[userId]/UserPage.tsx b/src/app/(main)/admin/users/[userId]/UserPage.tsx index 56812c0c..0ae65855 100644 --- a/src/app/(main)/admin/users/[userId]/UserPage.tsx +++ b/src/app/(main)/admin/users/[userId]/UserPage.tsx @@ -1,11 +1,19 @@ 'use client'; +import { Column } from '@umami/react-zen'; import { UserSettings } from './UserSettings'; import { UserProvider } from './UserProvider'; +import { UserHeader } from '@/app/(main)/admin/users/[userId]/UserHeader'; +import { Panel } from '@/components/common/Panel'; export function UserPage({ userId }: { userId: string }) { return ( - + + + + + + ); } diff --git a/src/app/(main)/admin/users/[userId]/UserSettings.tsx b/src/app/(main)/admin/users/[userId]/UserSettings.tsx index 8369c3f4..3d699ebe 100644 --- a/src/app/(main)/admin/users/[userId]/UserSettings.tsx +++ b/src/app/(main)/admin/users/[userId]/UserSettings.tsx @@ -1,19 +1,13 @@ -import { useContext } from 'react'; -import { Tabs, Tab, TabList, TabPanel } from '@umami/react-zen'; -import { User } from '@/components/icons'; +import { Column, Tabs, Tab, TabList, TabPanel } from '@umami/react-zen'; import { UserEditForm } from './UserEditForm'; -import { SectionHeader } from '@/components/common/SectionHeader'; import { useMessages } from '@/components/hooks'; import { UserWebsites } from './UserWebsites'; -import { UserContext } from './UserProvider'; export function UserSettings({ userId }: { userId: string }) { const { formatMessage, labels } = useMessages(); - const user = useContext(UserContext); return ( - <> - } /> + {formatMessage(labels.details)} @@ -26,6 +20,6 @@ export function UserSettings({ userId }: { userId: string }) { - + ); } diff --git a/src/app/(main)/admin/websites/AdminWebsitesPage.tsx b/src/app/(main)/admin/websites/AdminWebsitesPage.tsx index 07a73a40..3ca61f78 100644 --- a/src/app/(main)/admin/websites/AdminWebsitesPage.tsx +++ b/src/app/(main)/admin/websites/AdminWebsitesPage.tsx @@ -1,16 +1,19 @@ 'use client'; import { AdminWebsitesDataTable } from './AdminWebsitesDataTable'; import { Column } from '@umami/react-zen'; -import { SectionHeader } from '@/components/common/SectionHeader'; import { useMessages } from '@/components/hooks'; +import { PageHeader } from '@/components/common/PageHeader'; +import { Panel } from '@/components/common/Panel'; export function AdminWebsitesPage() { const { formatMessage, labels } = useMessages(); return ( - - - + + + + + ); } diff --git a/src/app/(main)/admin/websites/AdminWebsitesTable.tsx b/src/app/(main)/admin/websites/AdminWebsitesTable.tsx index 7b970e7f..81a6aacf 100644 --- a/src/app/(main)/admin/websites/AdminWebsitesTable.tsx +++ b/src/app/(main)/admin/websites/AdminWebsitesTable.tsx @@ -55,7 +55,7 @@ export function AdminWebsitesTable({ data = [] }: { data: any[] }) { return ( - + diff --git a/src/app/(main)/admin/websites/[websiteId]/AdminWebsitePage.tsx b/src/app/(main)/admin/websites/[websiteId]/AdminWebsitePage.tsx index 637da839..da79026b 100644 --- a/src/app/(main)/admin/websites/[websiteId]/AdminWebsitePage.tsx +++ b/src/app/(main)/admin/websites/[websiteId]/AdminWebsitePage.tsx @@ -1,11 +1,14 @@ 'use client'; import { WebsiteSettings } from '@/app/(main)/settings/websites/[websiteId]/WebsiteSettings'; import { WebsiteProvider } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; +import { Panel } from '@/components/common/Panel'; export function AdminWebsitePage({ websiteId }: { websiteId: string }) { return ( - + + + ); } diff --git a/src/app/(main)/admin/websites/[websiteId]/page.tsx b/src/app/(main)/admin/websites/[websiteId]/page.tsx index ed10ec43..e1c92276 100644 --- a/src/app/(main)/admin/websites/[websiteId]/page.tsx +++ b/src/app/(main)/admin/websites/[websiteId]/page.tsx @@ -1,10 +1,10 @@ -import { AdminWebsitePage } from './AdminWebsitePage'; import { Metadata } from 'next'; +import { WebsiteSettingsPage } from '@/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage'; export default async function ({ params }: { params: Promise<{ websiteId: string }> }) { const { websiteId } = await params; - return ; + return ; } export const metadata: Metadata = { diff --git a/src/app/(main)/settings/SettingsLayout.tsx b/src/app/(main)/settings/SettingsLayout.tsx index e12246e3..9617049f 100644 --- a/src/app/(main)/settings/SettingsLayout.tsx +++ b/src/app/(main)/settings/SettingsLayout.tsx @@ -2,44 +2,60 @@ import { ReactNode } from 'react'; import { Grid, Column } from '@umami/react-zen'; import { useMessages, useNavigation } from '@/components/hooks'; -import { SideMenu } from '@/components/common/SideMenu'; -import { PageHeader } from '@/components/common/PageHeader'; -import { Panel } from '@/components/common/Panel'; import { PageBody } from '@/components/common/PageBody'; +import { SideMenu } from '@/components/common/SideMenu'; +import { UserCircle, Users, Knobs } from '@/components/icons'; export function SettingsLayout({ children }: { children: ReactNode }) { const { formatMessage, labels } = useMessages(); - const { pathname } = useNavigation(); + const { renderUrl, pathname } = useNavigation(); const items = [ { - id: 'preferences', - label: formatMessage(labels.preferences), - url: '/settings/preferences', + label: formatMessage(labels.application), + items: [ + { + id: 'preferences', + label: formatMessage(labels.preferences), + path: renderUrl('/settings/preferences'), + icon: , + }, + { + id: 'teams', + label: formatMessage(labels.teams), + path: renderUrl('/settings/teams'), + icon: , + }, + ], }, { - id: 'profile', - label: formatMessage(labels.profile), - url: '/settings/profile', + label: formatMessage(labels.account), + items: [ + { + id: 'profile', + label: formatMessage(labels.profile), + path: renderUrl('/settings/profile'), + icon: , + }, + ], }, - { id: 'teams', label: formatMessage(labels.teams), url: '/settings/teams' }, ]; - const value = items.find(({ url }) => pathname.includes(url))?.id; + const selectedKey = + items.flatMap(e => e.items)?.find(({ path }) => path && pathname.endsWith(path))?.id || + 'overview'; return ( - - - - - - - - - {children} - - + + + - + {children} + ); } diff --git a/src/app/(main)/settings/preferences/PreferenceSettings.tsx b/src/app/(main)/settings/preferences/PreferenceSettings.tsx index c956ebad..9192a905 100644 --- a/src/app/(main)/settings/preferences/PreferenceSettings.tsx +++ b/src/app/(main)/settings/preferences/PreferenceSettings.tsx @@ -19,17 +19,14 @@ export function PreferenceSettings() { - - - - - - - + + + + diff --git a/src/app/(main)/settings/preferences/PreferencesPage.tsx b/src/app/(main)/settings/preferences/PreferencesPage.tsx index 62d7f882..99289956 100644 --- a/src/app/(main)/settings/preferences/PreferencesPage.tsx +++ b/src/app/(main)/settings/preferences/PreferencesPage.tsx @@ -1,16 +1,19 @@ 'use client'; import { Column } from '@umami/react-zen'; import { useMessages } from '@/components/hooks'; -import { SectionHeader } from '@/components/common/SectionHeader'; +import { Panel } from '@/components/common/Panel'; import { PreferenceSettings } from './PreferenceSettings'; +import { PageHeader } from '@/components/common/PageHeader'; export function PreferencesPage() { const { formatMessage, labels } = useMessages(); return ( - - - + + + + + ); } diff --git a/src/app/(main)/settings/profile/ProfilePage.tsx b/src/app/(main)/settings/profile/ProfilePage.tsx index aaec3f58..2d1ce0d3 100644 --- a/src/app/(main)/settings/profile/ProfilePage.tsx +++ b/src/app/(main)/settings/profile/ProfilePage.tsx @@ -1,16 +1,19 @@ 'use client'; import { ProfileSettings } from './ProfileSettings'; import { useMessages } from '@/components/hooks'; -import { SectionHeader } from '@/components/common/SectionHeader'; +import { Panel } from '@/components/common/Panel'; import { Column } from '@umami/react-zen'; +import { PageHeader } from '@/components/common/PageHeader'; export function ProfilePage() { const { formatMessage, labels } = useMessages(); return ( - - - + + + + + ); } diff --git a/src/app/(main)/settings/profile/ProfileSettings.tsx b/src/app/(main)/settings/profile/ProfileSettings.tsx index 72ae7d91..b580d686 100644 --- a/src/app/(main)/settings/profile/ProfileSettings.tsx +++ b/src/app/(main)/settings/profile/ProfileSettings.tsx @@ -34,12 +34,10 @@ export function ProfileSettings() { {username} - {renderRole(role)} - {!cloudMode && ( diff --git a/src/app/(main)/settings/teams/TeamsHeader.tsx b/src/app/(main)/settings/teams/TeamsHeader.tsx index 96774f5e..61244033 100644 --- a/src/app/(main)/settings/teams/TeamsHeader.tsx +++ b/src/app/(main)/settings/teams/TeamsHeader.tsx @@ -1,5 +1,5 @@ import { Row } from '@umami/react-zen'; -import { SectionHeader } from '@/components/common/SectionHeader'; +import { PageHeader } from '@/components/common/PageHeader'; import { ROLES } from '@/lib/constants'; import { useLoginQuery, useMessages } from '@/components/hooks'; import { TeamsJoinButton } from './TeamsJoinButton'; @@ -11,11 +11,11 @@ export function TeamsHeader({ allowCreate = true }: { allowCreate?: boolean }) { const cloudMode = !!process.env.cloudMode; return ( - + {!cloudMode && } {allowCreate && user.role !== ROLES.viewOnly && } - + ); } diff --git a/src/app/(main)/settings/teams/TeamsSettingsPage.tsx b/src/app/(main)/settings/teams/TeamsSettingsPage.tsx index e64461c0..57e4aad8 100644 --- a/src/app/(main)/settings/teams/TeamsSettingsPage.tsx +++ b/src/app/(main)/settings/teams/TeamsSettingsPage.tsx @@ -2,12 +2,15 @@ import { TeamsDataTable } from './TeamsDataTable'; import { TeamsHeader } from './TeamsHeader'; import { Column } from '@umami/react-zen'; +import { Panel } from '@/components/common/Panel'; export function TeamsSettingsPage() { return ( - + - + + + ); } diff --git a/src/app/(main)/settings/teams/TeamsTable.tsx b/src/app/(main)/settings/teams/TeamsTable.tsx index bfe6b332..a2599251 100644 --- a/src/app/(main)/settings/teams/TeamsTable.tsx +++ b/src/app/(main)/settings/teams/TeamsTable.tsx @@ -7,7 +7,7 @@ import Link from 'next/link'; export function TeamsTable({ data = [], - showActions = true, + showActions = false, }: { data: any[]; allowEdit?: boolean; @@ -29,7 +29,7 @@ export function TeamsTable({ {(row: any) => row._count.teamUser} - {showActions && ( + {showActions ? ( {(row: any) => { const { id } = row; @@ -56,7 +56,7 @@ export function TeamsTable({ ); }} - )} + ) : null} ); } diff --git a/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx b/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx index 071c56a8..e4900004 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamDetails.tsx @@ -1,8 +1,8 @@ import { useContext, useState } from 'react'; import { Column, Tabs, TabList, Tab, TabPanel } from '@umami/react-zen'; -import { TeamContext } from '@/app/(main)/teams/[teamId]/TeamProvider'; +import { TeamContext } from '@/app/(main)/settings/teams/[teamId]/TeamProvider'; import { useLoginQuery, useMessages, useNavigation } from '@/components/hooks'; -import { SectionHeader } from '@/components/common/SectionHeader'; + import { ROLES } from '@/lib/constants'; import { Users } from '@/components/icons'; import { TeamLeaveButton } from '@/app/(main)/settings/teams/TeamLeaveButton'; @@ -10,6 +10,8 @@ import { TeamManage } from './TeamManage'; import { TeamEditForm } from './TeamEditForm'; import { TeamWebsitesDataTable } from './TeamWebsitesDataTable'; import { TeamMembersDataTable } from './TeamMembersDataTable'; +import { PageHeader } from '@/components/common/PageHeader'; +import { Panel } from '@/components/common/Panel'; export function TeamDetails({ teamId }: { teamId: string }) { const team = useContext(TeamContext); @@ -33,30 +35,32 @@ export function TeamDetails({ teamId }: { teamId: string }) { user.role !== ROLES.viewOnly); return ( - - }> + + }> {!isTeamOwner && !isAdmin && } - - setTab(value)}> - - {formatMessage(labels.details)} - {formatMessage(labels.members)} - {formatMessage(labels.websites)} - {isTeamOwner && {formatMessage(labels.manage)}} - - - - - - - - - - - - - - + + + setTab(value)}> + + {formatMessage(labels.details)} + {formatMessage(labels.members)} + {formatMessage(labels.websites)} + {isTeamOwner && {formatMessage(labels.manage)}} + + + + + + + + + + + + + + + ); } diff --git a/src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx b/src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx index 9c053ac8..ce206169 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamEditForm.tsx @@ -10,7 +10,7 @@ import { import { getRandomChars } from '@/lib/crypto'; import { useContext } from 'react'; import { useApi, useMessages, useModified } from '@/components/hooks'; -import { TeamContext } from '@/app/(main)/teams/[teamId]/TeamProvider'; +import { TeamContext } from '@/app/(main)/settings/teams/[teamId]/TeamProvider'; const generateId = () => `team_${getRandomChars(16)}`; diff --git a/src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx b/src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx index c8056146..a9216439 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamMemberEditButton.tsx @@ -1,6 +1,7 @@ import { useMessages, useModified } from '@/components/hooks'; -import { Row, Button, Icon, Modal, DialogTrigger, Dialog, useToast } from '@umami/react-zen'; +import { Dialog, useToast } from '@umami/react-zen'; import { TeamMemberEditForm } from './TeamMemberEditForm'; +import { ActionButton } from '@/components/input/ActionButton'; import { Edit } from '@/components/icons'; export function TeamMemberEditButton({ @@ -25,27 +26,18 @@ export function TeamMemberEditButton({ }; return ( - - - - - {({ close }) => ( - - )} - - - + }> + + {({ close }) => ( + + )} + + ); } diff --git a/src/app/(main)/settings/teams/[teamId]/TeamMemberRemoveButton.tsx b/src/app/(main)/settings/teams/[teamId]/TeamMemberRemoveButton.tsx index be1a11cc..5b1d323f 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamMemberRemoveButton.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamMemberRemoveButton.tsx @@ -2,7 +2,8 @@ import { ConfirmationForm } from '@/components/common/ConfirmationForm'; import { useApi, useMessages, useModified } from '@/components/hooks'; import { messages } from '@/components/messages'; import { Trash } from '@/components/icons'; -import { Button, Icon, Modal, DialogTrigger, Dialog } from '@umami/react-zen'; +import { Dialog } from '@umami/react-zen'; +import { ActionButton } from '@/components/input/ActionButton'; export function TeamMemberRemoveButton({ teamId, @@ -34,29 +35,22 @@ export function TeamMemberRemoveButton({ }; return ( - - - - - {({ close }) => ( - - )} - - - + }> + + {({ close }) => ( + + )} + + ); } diff --git a/src/app/(main)/teams/[teamId]/TeamProvider.tsx b/src/app/(main)/settings/teams/[teamId]/TeamProvider.tsx similarity index 100% rename from src/app/(main)/teams/[teamId]/TeamProvider.tsx rename to src/app/(main)/settings/teams/[teamId]/TeamProvider.tsx diff --git a/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx b/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx index 88ec9b40..d172c3aa 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx @@ -1,5 +1,5 @@ 'use client'; -import { TeamProvider } from '@/app/(main)/teams/[teamId]/TeamProvider'; +import { TeamProvider } from '@/app/(main)/settings/teams/[teamId]/TeamProvider'; import { TeamDetails } from '@/app/(main)/settings/teams/[teamId]/TeamDetails'; export function TeamSettingsPage({ teamId }: { teamId: string }) { diff --git a/src/app/(main)/settings/teams/[teamId]/TeamWebsitesTable.tsx b/src/app/(main)/settings/teams/[teamId]/TeamWebsitesTable.tsx index f04f1f85..da97fc51 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamWebsitesTable.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamWebsitesTable.tsx @@ -1,58 +1,19 @@ -import { DataColumn, DataTable, Icon, MenuItem, Text, Row } from '@umami/react-zen'; -import { useLoginQuery, useMessages } from '@/components/hooks'; -import { Eye, Edit } from '@/components/icons'; -import { MenuButton } from '@/components/input/MenuButton'; +import { DataColumn, DataTable } from '@umami/react-zen'; +import { useMessages } from '@/components/hooks'; import Link from 'next/link'; -export function TeamWebsitesTable({ - teamId, - data = [], - allowEdit = false, -}: { - teamId: string; - data: any[]; - allowEdit?: boolean; -}) { - const { user } = useLoginQuery(); +export function TeamWebsitesTable({ teamId, data = [] }: { teamId: string; data: any[] }) { const { formatMessage, labels } = useMessages(); return ( - {(row: any) => {row.name}} + {(row: any) => {row.name}} {(row: any) => row?.createUser?.username} - - {(row: any) => { - const { id: websiteId } = row; - - return ( - - - - - - - {formatMessage(labels.view)} - - - {allowEdit && (teamId || user?.isAdmin) && ( - - - - - - {formatMessage(labels.edit)} - - - )} - - ); - }} - ); } diff --git a/src/app/(main)/settings/websites/WebsitesTable.tsx b/src/app/(main)/settings/websites/WebsitesTable.tsx index a7948781..2d285c75 100644 --- a/src/app/(main)/settings/websites/WebsitesTable.tsx +++ b/src/app/(main)/settings/websites/WebsitesTable.tsx @@ -57,7 +57,7 @@ export function WebsitesTable({ )} {allowEdit && ( - + diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx index fce82f50..1c1f4a9e 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteData.tsx @@ -1,5 +1,4 @@ import { Button, Modal, DialogTrigger, Dialog, Column } from '@umami/react-zen'; -import { useRouter } from 'next/navigation'; import { useLoginQuery, useMessages, @@ -17,9 +16,9 @@ export function WebsiteData({ websiteId, onSave }: { websiteId: string; onSave?: const { formatMessage, labels, messages } = useMessages(); const { user } = useLoginQuery(); const { touch } = useModified(); - const { teamId, renderUrl } = useNavigation(); - const router = useRouter(); + const { router, pathname, teamId, renderUrl } = useNavigation(); const { data: teams } = useUserTeamsQuery(user.id); + const isAdmin = pathname.startsWith('/admin'); const canTransferWebsite = ( @@ -49,21 +48,23 @@ export function WebsiteData({ websiteId, onSave }: { websiteId: string; onSave?: return ( - - - - - - {({ close }) => ( - - )} - - - - + {!isAdmin && ( + + + + + + {({ close }) => ( + + )} + + + + + )} - }> - - - - - {formatMessage(labels.view)} - - - - - {formatMessage(labels.details)} - {formatMessage(labels.trackingCode)} - {formatMessage(labels.shareUrl)} - {formatMessage(labels.manage)} - - - - - - - - - - - - - - - + + + {formatMessage(labels.details)} + {formatMessage(labels.trackingCode)} + {formatMessage(labels.shareUrl)} + {formatMessage(labels.manage)} + + + + + + + + + + + + + + ); } diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsHeader.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsHeader.tsx new file mode 100644 index 00000000..ee542f2f --- /dev/null +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsHeader.tsx @@ -0,0 +1,10 @@ +import { useContext } from 'react'; +import { WebsiteContext } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; +import { PageHeader } from '@/components/common/PageHeader'; +import { Globe } from '@/components/icons'; + +export function WebsiteSettingsHeader() { + const website = useContext(WebsiteContext); + + return } />; +} diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage.tsx index 5df7a819..1aff4e7e 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage.tsx @@ -1,11 +1,19 @@ 'use client'; +import { Column } from '@umami/react-zen'; import { WebsiteProvider } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; import { WebsiteSettings } from './WebsiteSettings'; +import { WebsiteSettingsHeader } from '@/app/(main)/settings/websites/[websiteId]/WebsiteSettingsHeader'; +import { Panel } from '@/components/common/Panel'; export function WebsiteSettingsPage({ websiteId }: { websiteId: string }) { return ( - + + + + + + ); } diff --git a/src/app/(main)/teams/[teamId]/layout.tsx b/src/app/(main)/teams/[teamId]/layout.tsx deleted file mode 100644 index 1dfdd243..00000000 --- a/src/app/(main)/teams/[teamId]/layout.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { TeamProvider } from './TeamProvider'; -import { Metadata } from 'next'; - -export default async function ({ - children, - params, -}: { - children: any; - params: Promise<{ teamId: string }>; -}) { - const { teamId } = await params; - - return {children}; -} - -export const metadata: Metadata = { - title: 'Teams', -}; diff --git a/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx b/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx index a3442d1c..f8617225 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx @@ -1,6 +1,6 @@ import { Button, Icon, DialogTrigger, Dialog, Modal, Text } from '@umami/react-zen'; import { ListFilter } from '@/components/icons'; -import { FilterEditForm } from '@/components/common/FilterEditForm'; +import { FilterEditForm } from '@/components/input/FilterEditForm'; import { useMessages, useNavigation, useFilters } from '@/components/hooks'; import { filtersArrayToObject } from '@/lib/params'; diff --git a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx index ae2cf1bb..1935fe07 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx @@ -5,11 +5,17 @@ import { Share, Edit } from '@/components/icons'; import { Favicon } from '@/components/common/Favicon'; import { ActiveUsers } from '@/components/metrics/ActiveUsers'; import { WebsiteShareForm } from '@/app/(main)/settings/websites/[websiteId]/WebsiteShareForm'; -import { useMessages } from '@/components/hooks'; +import { useMessages, useNavigation } from '@/components/hooks'; import { LinkButton } from '@/components/common/LinkButton'; export function WebsiteHeader() { const website = useWebsite(); + const { renderUrl, pathname } = useNavigation(); + const isSettings = pathname.endsWith('/settings'); + + if (isSettings) { + return null; + } return ( } marginBottom="3"> @@ -17,7 +23,7 @@ export function WebsiteHeader() { - + diff --git a/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx b/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx index 14374904..b095afdb 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx @@ -1,17 +1,23 @@ 'use client'; import { ReactNode } from 'react'; -import { Column } from '@umami/react-zen'; +import { Column, Grid } from '@umami/react-zen'; import { WebsiteProvider } from './WebsiteProvider'; import { PageBody } from '@/components/common/PageBody'; import { WebsiteHeader } from './WebsiteHeader'; +import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav'; export function WebsiteLayout({ websiteId, children }: { websiteId: string; children: ReactNode }) { return ( - - - {children} - + + + + + + + {children} + + ); } diff --git a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx index 9ba78662..54cfe0bb 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx @@ -1,4 +1,3 @@ -import { Icon, Text, Row, NavMenu, NavMenuItem, NavMenuGroup, Column } from '@umami/react-zen'; import { Eye, Lightning, @@ -16,14 +15,16 @@ import { ChartPie, } from '@/components/icons'; import { useMessages, useNavigation } from '@/components/hooks'; -import Link from 'next/link'; +import { SideMenu } from '@/components/common/SideMenu'; import { WebsiteSelect } from '@/components/input/WebsiteSelect'; export function WebsiteNav({ websiteId }: { websiteId: string }) { const { formatMessage, labels } = useMessages(); const { pathname, renderUrl, teamId } = useNavigation(); - const links = [ + const renderPath = (path: string) => renderUrl(`/websites/${websiteId}${path}`); + + const items = [ { label: formatMessage(labels.traffic), items: [ @@ -31,25 +32,31 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) { id: 'overview', label: formatMessage(labels.overview), icon: , - path: '', + path: renderPath(''), }, { id: 'events', label: formatMessage(labels.events), icon: , - path: '/events', + path: renderPath('/events'), }, { id: 'sessions', label: formatMessage(labels.sessions), icon: , - path: '/sessions', + path: renderPath('/sessions'), }, { id: 'realtime', label: formatMessage(labels.realtime), icon: , - path: '/realtime', + path: renderPath('/realtime'), + }, + { + id: 'breakdown', + label: formatMessage(labels.breakdown), + icon: , + path: renderPath('/breakdown'), }, ], }, @@ -60,48 +67,42 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) { id: 'goals', label: formatMessage(labels.goals), icon: , - path: '/goals', + path: renderPath('/goals'), }, { id: 'funnel', label: formatMessage(labels.funnels), icon: , - path: '/funnels', + path: renderPath('/funnels'), }, { id: 'journeys', label: formatMessage(labels.journeys), icon: , - path: '/journeys', + path: renderPath('/journeys'), }, { id: 'retention', label: formatMessage(labels.retention), icon: , - path: '/retention', + path: renderPath('/retention'), }, ], }, { label: formatMessage(labels.segments), items: [ - { - id: 'breakdown', - label: formatMessage(labels.breakdown), - icon: , - path: '/breakdown', - }, { id: 'segments', label: formatMessage(labels.segments), icon: , - path: '/segments', + path: renderPath('/segments'), }, { id: 'cohorts', label: formatMessage(labels.cohorts), icon: , - path: '/cohorts', + path: renderPath('/cohorts'), }, ], }, @@ -112,53 +113,31 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) { id: 'utm', label: formatMessage(labels.utm), icon: , - path: '/utm', + path: renderPath('/utm'), }, { id: 'revenue', label: formatMessage(labels.revenue), icon: , - path: '/revenue', + path: renderPath('/revenue'), }, { id: 'attribution', label: formatMessage(labels.attribution), icon: , - path: '/attribution', + path: renderPath('/attribution'), }, ], }, ]; - const selected = - links.flatMap(e => e.items).find(({ path }) => path && pathname.endsWith(path))?.id || + const selectedKey = + items.flatMap(e => e.items).find(({ path }) => path && pathname.endsWith(path))?.id || 'overview'; return ( - + - - {links.map(({ label, items }) => { - return ( - - {items.map(({ id, label, icon, path }) => { - const isSelected = selected === id; - - return ( - - - - {icon} - {label} - - - - ); - })} - - ); - })} - - + ); } diff --git a/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx b/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx index d93c7d8c..805f1252 100644 --- a/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx +++ b/src/app/(main)/websites/[websiteId]/events/EventsDataTable.tsx @@ -3,7 +3,7 @@ import { useMessages, useWebsiteEventsQuery } from '@/components/hooks'; import { EventsTable } from './EventsTable'; import { DataGrid } from '@/components/common/DataGrid'; import { ReactNode } from 'react'; -import { FilterButtons } from '@/components/common/FilterButtons'; +import { FilterButtons } from '@/components/input/FilterButtons'; export function EventsDataTable({ websiteId, diff --git a/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx b/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx index 8e965528..a706242a 100644 --- a/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx +++ b/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx @@ -1,6 +1,6 @@ import { useFormat } from '@/components//hooks/useFormat'; import { Empty } from '@/components/common/Empty'; -import { FilterButtons } from '@/components/common/FilterButtons'; +import { FilterButtons } from '@/components/input/FilterButtons'; import { useCountryNames, useLocale, useMessages, useTimezone } from '@/components/hooks'; import { Eye, Visitor, Bolt } from '@/components/icons'; import { BROWSERS, OS_NAMES } from '@/lib/constants'; diff --git a/src/app/(main)/websites/[websiteId]/realtime/RealtimeUrls.tsx b/src/app/(main)/websites/[websiteId]/realtime/RealtimeUrls.tsx index e6b493bf..15e53a6b 100644 --- a/src/app/(main)/websites/[websiteId]/realtime/RealtimeUrls.tsx +++ b/src/app/(main)/websites/[websiteId]/realtime/RealtimeUrls.tsx @@ -6,7 +6,7 @@ import { ListTable } from '@/components/metrics/ListTable'; import { useMessages } from '@/components/hooks'; import { RealtimeData } from '@/lib/types'; import { WebsiteContext } from '../WebsiteProvider'; -import { FilterButtons } from '@/components/common/FilterButtons'; +import { FilterButtons } from '@/components/input/FilterButtons'; const FILTER_REFERRERS = 'filter-referrers'; const FILTER_PAGES = 'filter-pages'; diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentAddButton.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentAddButton.tsx index 3c198fd4..d8539406 100644 --- a/src/app/(main)/websites/[websiteId]/segments/SegmentAddButton.tsx +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentAddButton.tsx @@ -1,7 +1,7 @@ import { Button, DialogTrigger, Modal, Text, Icon, Dialog } from '@umami/react-zen'; import { useMessages } from '@/components/hooks'; import { Plus } from '@/components/icons'; -import { SegmentEditForm } from '@/app/(main)/websites/[websiteId]/segments/SegmentEditForm'; +import { SegmentEditForm } from './SegmentEditForm'; export function SegmentAddButton({ websiteId }: { websiteId: string }) { const { formatMessage, labels } = useMessages(); diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentDeleteButton.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentDeleteButton.tsx new file mode 100644 index 00000000..fc86e78f --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentDeleteButton.tsx @@ -0,0 +1,55 @@ +import { Dialog } from '@umami/react-zen'; +import { ActionButton } from '@/components/input/ActionButton'; +import { Trash } from '@/components/icons'; +import { ConfirmationForm } from '@/components/common/ConfirmationForm'; +import { messages } from '@/components/messages'; +import { useApi, useMessages, useModified } from '@/components/hooks'; + +export function SegmentDeleteButton({ + segmentId, + websiteId, + name, + onSave, +}: { + segmentId: string; + websiteId: string; + name: string; + onSave?: () => void; +}) { + const { formatMessage, labels } = useMessages(); + const { del, useMutation } = useApi(); + const { mutate, isPending, error } = useMutation({ + mutationFn: () => del(`/websites/${websiteId}/segments/${segmentId}`), + }); + const { touch } = useModified(); + + const handleConfirm = (close: () => void) => { + mutate(null, { + onSuccess: () => { + touch('segments'); + onSave?.(); + close(); + }, + }); + }; + + return ( + }> + + {({ close }) => ( + + )} + + + ); +} diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentEditButton.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentEditButton.tsx new file mode 100644 index 00000000..c7041f7a --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentEditButton.tsx @@ -0,0 +1,34 @@ +import { ActionButton } from '@/components/input/ActionButton'; +import { Edit } from '@/components/icons'; +import { Dialog } from '@umami/react-zen'; +import { SegmentEditForm } from '@/app/(main)/websites/[websiteId]/segments/SegmentEditForm'; +import { useMessages } from '@/components/hooks'; + +export function SegmentEditButton({ + segmentId, + websiteId, + filters, +}: { + segmentId: string; + websiteId: string; + filters: any[]; +}) { + const { formatMessage, labels } = useMessages(); + + return ( + }> + + {({ close }) => { + return ( + + ); + }} + + + ); +} diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx index 15133e8e..b19785a5 100644 --- a/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx @@ -6,24 +6,30 @@ import { FormSubmitButton, TextField, Label, + Loading, } from '@umami/react-zen'; import { subMonths, endOfDay } from 'date-fns'; import { FieldFilters } from '@/components/input/FieldFilters'; import { useState } from 'react'; -import { useApi, useMessages, useModified } from '@/components/hooks'; +import { useApi, useMessages, useModified, useWebsiteSegmentQuery } from '@/components/hooks'; import { filtersArrayToObject } from '@/lib/params'; export function SegmentEditForm({ + segmentId, websiteId, filters = [], + showFilters = true, onSave, onClose, }: { + segmentId: string; websiteId: string; filters?: any[]; + showFilters?: boolean; onSave?: () => void; onClose?: () => void; }) { + const { data } = useWebsiteSegmentQuery(websiteId, segmentId); const { formatMessage, labels } = useMessages(); const [currentFilters, setCurrentFilters] = useState(filters); const { touch } = useModified(); @@ -33,7 +39,10 @@ export function SegmentEditForm({ const { post, useMutation } = useApi(); const { mutate, error, isPending } = useMutation({ mutationFn: (data: any) => - post(`/websites/${websiteId}/segments`, { ...data, type: 'segment' }), + post(`/websites/${websiteId}/segments${segmentId ? `/${segmentId}` : ''}`, { + ...data, + type: 'segment', + }), }); const handleSubmit = async (data: any) => { @@ -49,28 +58,40 @@ export function SegmentEditForm({ ); }; + if (segmentId && !data) { + return ; + } + return ( -
+ - + - - + {showFilters && ( + <> + + + + )} - + {formatMessage(labels.save)} diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentsTable.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentsTable.tsx index 0231db87..fe8317ce 100644 --- a/src/app/(main)/websites/[websiteId]/segments/SegmentsTable.tsx +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentsTable.tsx @@ -1,12 +1,14 @@ -import { DataTable, DataColumn, Icon, Row, Text, MenuItem } from '@umami/react-zen'; -import { useMessages } from '@/components/hooks'; +import { DataTable, DataColumn, Row } from '@umami/react-zen'; +import { useMessages, useNavigation } from '@/components/hooks'; import { Empty } from '@/components/common/Empty'; -import { Edit, Trash } from '@/components/icons'; import { DateDistance } from '@/components/common/DateDistance'; -import { MenuButton } from '@/components/input/MenuButton'; +import { filtersObjectToArray } from '@/lib/params'; +import { SegmentEditButton } from '@/app/(main)/websites/[websiteId]/segments/SegmentEditButton'; +import { SegmentDeleteButton } from '@/app/(main)/websites/[websiteId]/segments/SegmentDeleteButton'; export function SegmentsTable({ data = [] }) { const { formatMessage, labels } = useMessages(); + const { websiteId } = useNavigation(); if (data.length === 0) { return ; @@ -20,27 +22,17 @@ export function SegmentsTable({ data = [] }) { {(row: any) => { - const { id } = row; + const { id, name, parameters } = row; return ( - - - - - - - {formatMessage(labels.edit)} - - - - - - - - {formatMessage(labels.delete)} - - - + + + + ); }} diff --git a/src/app/(main)/websites/[websiteId]/settings/SettingsPage.tsx b/src/app/(main)/websites/[websiteId]/settings/SettingsPage.tsx new file mode 100644 index 00000000..84bd0f4e --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/settings/SettingsPage.tsx @@ -0,0 +1,25 @@ +'use client'; +import { Column, Icon, Row, Text } from '@umami/react-zen'; +import { WebsiteSettingsPage } from '@/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage'; +import { LinkButton } from '@/components/common/LinkButton'; +import { Arrow } from '@/components/icons'; +import { useNavigation } from '@/components/hooks'; + +export function SettingsPage({ websiteId }: { websiteId: string }) { + const { pathname } = useNavigation(); + return ( + + + + + + + + Back + + + + + + ); +} diff --git a/src/app/(main)/websites/[websiteId]/settings/page.tsx b/src/app/(main)/websites/[websiteId]/settings/page.tsx new file mode 100644 index 00000000..a3aed621 --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/settings/page.tsx @@ -0,0 +1,12 @@ +import { SettingsPage } from './SettingsPage'; +import { Metadata } from 'next'; + +export default async function ({ params }: { params: Promise<{ websiteId: string }> }) { + const { websiteId } = await params; + + return ; +} + +export const metadata: Metadata = { + title: 'Settings', +}; diff --git a/src/components/common/PageHeader.tsx b/src/components/common/PageHeader.tsx index 9f3365ad..92f8af0c 100644 --- a/src/components/common/PageHeader.tsx +++ b/src/components/common/PageHeader.tsx @@ -27,7 +27,7 @@ export function PageHeader({ {...props} > - {icon && {icon}} + {icon && {icon}} {title && {title}} {description && {description}} diff --git a/src/components/common/SideMenu.tsx b/src/components/common/SideMenu.tsx index ad167116..4daa4909 100644 --- a/src/components/common/SideMenu.tsx +++ b/src/components/common/SideMenu.tsx @@ -1,27 +1,68 @@ -import { ReactNode } from 'react'; -import { Text, NavMenu, NavMenuItem, Icon, Row } from '@umami/react-zen'; +import { + Text, + Heading, + NavMenu, + NavMenuItem, + Icon, + Row, + Column, + NavMenuGroup, +} from '@umami/react-zen'; import Link from 'next/link'; export interface SideMenuProps { - items: { id: string; label: string; url: string; icon?: ReactNode }[]; + items: { label: string; items: { id: string; label: string; icon?: any; path: string }[] }[]; + title?: string; selectedKey?: string; + allowMinimize?: boolean; } -export function SideMenu({ items, selectedKey }: SideMenuProps) { +export function SideMenu({ items, title, selectedKey, allowMinimize, children }: SideMenuProps) { return ( - - {items.map(({ id, label, url, icon }) => { - return ( - - - - {icon && {icon}} - {label} - - - - ); - })} - + + {children} + {title && ( + + {title} + + )} + + {items.map(({ label, items }) => { + return ( + + {items.map(({ id, label, icon, path }) => { + const isSelected = selectedKey === id; + + return ( + + + + {icon} + {label} + + + + ); + })} + + ); + })} + + ); } diff --git a/src/components/icons.ts b/src/components/icons.ts index 95094acb..c25aa003 100644 --- a/src/components/icons.ts +++ b/src/components/icons.ts @@ -35,6 +35,7 @@ export { Plus, RefreshCw as Refresh, Settings, + Settings2 as Knobs, Share, Sheet, Slash, diff --git a/src/components/input/ActionButton.tsx b/src/components/input/ActionButton.tsx new file mode 100644 index 00000000..7798aa48 --- /dev/null +++ b/src/components/input/ActionButton.tsx @@ -0,0 +1,26 @@ +import { ReactNode } from 'react'; +import { Button, Icon, Modal, DialogTrigger, TooltipTrigger, Tooltip } from '@umami/react-zen'; + +export function ActionButton({ + onClick, + icon, + tooltip, + children, +}: { + onSave?: () => void; + icon?: ReactNode; + tooltip?: string; + children?: React.ReactNode; +}) { + return ( + + + + {tooltip} + + {children} + + ); +} diff --git a/src/components/input/DeleteButton.tsx b/src/components/input/DeleteButton.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/input/FilterBar.tsx b/src/components/input/FilterBar.tsx index 445db323..3ce30294 100644 --- a/src/components/input/FilterBar.tsx +++ b/src/components/input/FilterBar.tsx @@ -1,4 +1,14 @@ -import { Button, Icon, Text, Row, TooltipTrigger, Tooltip } from '@umami/react-zen'; +import { + Button, + Icon, + Text, + Row, + TooltipTrigger, + Tooltip, + Modal, + Dialog, + DialogTrigger, +} from '@umami/react-zen'; import { useNavigation, useMessages, @@ -6,8 +16,9 @@ import { useFilters, useWebsiteSegmentQuery, } from '@/components/hooks'; -import { Close } from '@/components/icons'; +import { Close, Bookmark } from '@/components/icons'; import { isSearchOperator } from '@/lib/params'; +import { SegmentEditForm } from '@/app/(main)/websites/[websiteId]/segments/SegmentEditForm'; export function FilterBar({ websiteId }: { websiteId: string }) { const { formatMessage, labels } = useMessages(); @@ -65,16 +76,37 @@ export function FilterBar({ websiteId }: { websiteId: string }) { ); })} - - - - {formatMessage(labels.clearAll)} - - + + + + + + {formatMessage(labels.saveSegment)} + + + + + {({ close }) => { + return ; + }} + + + + + + + {formatMessage(labels.clearAll)} + + + ); } diff --git a/src/components/common/FilterButtons.tsx b/src/components/input/FilterButtons.tsx similarity index 100% rename from src/components/common/FilterButtons.tsx rename to src/components/input/FilterButtons.tsx diff --git a/src/components/common/FilterEditForm.tsx b/src/components/input/FilterEditForm.tsx similarity index 96% rename from src/components/common/FilterEditForm.tsx rename to src/components/input/FilterEditForm.tsx index b253b780..33846575 100644 --- a/src/components/common/FilterEditForm.tsx +++ b/src/components/input/FilterEditForm.tsx @@ -57,7 +57,7 @@ export function FilterEditForm({ onSave={setCurrentFilters} /> - + - + diff --git a/src/components/input/ProfileButton.tsx b/src/components/input/ProfileButton.tsx index e30557f1..5b890095 100644 --- a/src/components/input/ProfileButton.tsx +++ b/src/components/input/ProfileButton.tsx @@ -9,6 +9,7 @@ import { MenuSeparator, MenuSection, Text, + Row, } from '@umami/react-zen'; import { useRouter } from 'next/navigation'; import { useMessages, useLoginQuery } from '@/components/hooks'; @@ -36,25 +37,31 @@ export function ProfileButton() { - - - - {formatMessage(labels.settings)} + + + + + {formatMessage(labels.settings)} + {user.isAdmin && ( - - - - {formatMessage(labels.admin)} + + + + + {formatMessage(labels.admin)} + )} {!cloudMode && ( - - - - {formatMessage(labels.logout)} + + + + + {formatMessage(labels.logout)} + )} diff --git a/src/components/input/SegmentFilters.tsx b/src/components/input/SegmentFilters.tsx index 3cf8ce46..1406d7a3 100644 --- a/src/components/input/SegmentFilters.tsx +++ b/src/components/input/SegmentFilters.tsx @@ -1,4 +1,4 @@ -import { List, Column, ListItem } from '@umami/react-zen'; +import { List, ListItem } from '@umami/react-zen'; import { useWebsiteSegmentsQuery } from '@/components/hooks'; import { LoadingPanel } from '@/components/common/LoadingPanel'; @@ -9,25 +9,23 @@ export interface SegmentFiltersProps { } export function SegmentFilters({ websiteId, segmentId, onSave }: SegmentFiltersProps) { - const { data, isLoading } = useWebsiteSegmentsQuery(websiteId, { type: 'segment' }); + const { data, isLoading, isFetching } = useWebsiteSegmentsQuery(websiteId, { type: 'segment' }); const handleChange = (id: string) => { onSave?.(id); }; return ( - - - handleChange(id[0])}> - {data?.data?.map(item => { - return ( - - {item.name} - - ); - })} - - - + + handleChange(id[0])}> + {data?.data?.map(item => { + return ( + + {item.name} + + ); + })} + + ); } diff --git a/src/components/input/SegmentSaveButton.tsx b/src/components/input/SegmentSaveButton.tsx new file mode 100644 index 00000000..f6cee0e1 --- /dev/null +++ b/src/components/input/SegmentSaveButton.tsx @@ -0,0 +1,26 @@ +import { Button, DialogTrigger, Modal, Text, Icon, Dialog } from '@umami/react-zen'; +import { useMessages } from '@/components/hooks'; +import { Plus } from '@/components/icons'; +import { SegmentEditForm } from '@/app/(main)/websites/[websiteId]/segments/SegmentEditForm'; + +export function SegmentSaveButton({ websiteId }: { websiteId: string }) { + const { formatMessage, labels } = useMessages(); + + return ( + + + + + {({ close }) => { + return ; + }} + + + + ); +} diff --git a/src/components/input/TeamsButton.tsx b/src/components/input/TeamsButton.tsx index d9fd5e08..6c84493a 100644 --- a/src/components/input/TeamsButton.tsx +++ b/src/components/input/TeamsButton.tsx @@ -15,7 +15,7 @@ import { Pressable, } from '@umami/react-zen'; import { useLoginQuery, useMessages, useUserTeamsQuery, useNavigation } from '@/components/hooks'; -import { Chevron, User, Users } from '@/components/icons'; +import { Chevron, User, Users, LogOut } from '@/components/icons'; export function TeamsButton({ showText = true }: { showText?: boolean }) { const { user } = useLoginQuery(); @@ -81,6 +81,17 @@ export function TeamsButton({ showText = true }: { showText?: boolean }) { ))} + + + + + + + + {formatMessage(labels.logout)} + + +
diff --git a/src/components/input/WebsiteSelect.tsx b/src/components/input/WebsiteSelect.tsx index 18a1e4a7..40e31a2f 100644 --- a/src/components/input/WebsiteSelect.tsx +++ b/src/components/input/WebsiteSelect.tsx @@ -33,13 +33,13 @@ export function WebsiteSelect({ items={data?.['data'] || []} value={websiteId} isLoading={isLoading} - buttonProps={buttonProps} + buttonProps={{ ...buttonProps }} allowSearch={true} searchValue={search} onSearch={handleSearch} onChange={handleSelect} renderValue={() => ( - + {website?.name} )} diff --git a/src/components/messages.ts b/src/components/messages.ts index e0e8413e..c06f4a02 100644 --- a/src/components/messages.ts +++ b/src/components/messages.ts @@ -342,6 +342,10 @@ export const labels = defineMessages({ traffic: { id: 'label.traffic', defaultMessage: 'Traffic' }, behavior: { id: 'label.behavior', defaultMessage: 'Behavior' }, growth: { id: 'label.growth', defaultMessage: 'Growth' }, + account: { id: 'label.account', defaultMessage: 'Account' }, + application: { id: 'label.application', defaultMessage: 'Application' }, + saveSegment: { id: 'label.save-segment', defaultMessage: 'Save segment' }, + saveCohort: { id: 'label.save-cohort', defaultMessage: 'Save cohort' }, }); export const messages = defineMessages({ diff --git a/src/components/metrics/PagesTable.tsx b/src/components/metrics/PagesTable.tsx index 5fd43fef..086d3dc7 100644 --- a/src/components/metrics/PagesTable.tsx +++ b/src/components/metrics/PagesTable.tsx @@ -1,5 +1,5 @@ import { WebsiteContext } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; -import { FilterButtons } from '@/components/common/FilterButtons'; +import { FilterButtons } from '@/components/input/FilterButtons'; import { FilterLink } from '@/components/common/FilterLink'; import { useMessages, useNavigation } from '@/components/hooks'; import { emptyFilter } from '@/lib/filters'; diff --git a/src/components/metrics/QueryParametersTable.tsx b/src/components/metrics/QueryParametersTable.tsx index e6d85495..e98f9134 100644 --- a/src/components/metrics/QueryParametersTable.tsx +++ b/src/components/metrics/QueryParametersTable.tsx @@ -1,6 +1,6 @@ import { useState } from 'react'; import { Row, Text } from '@umami/react-zen'; -import { FilterButtons } from '@/components/common/FilterButtons'; +import { FilterButtons } from '@/components/input/FilterButtons'; import { emptyFilter, paramFilter } from '@/lib/filters'; import { MetricsTable, MetricsTableProps } from './MetricsTable'; import { useMessages } from '@/components/hooks'; diff --git a/src/components/metrics/ReferrersTable.tsx b/src/components/metrics/ReferrersTable.tsx index 0b3f1ee3..8990db1a 100644 --- a/src/components/metrics/ReferrersTable.tsx +++ b/src/components/metrics/ReferrersTable.tsx @@ -1,7 +1,7 @@ import { Row } from '@umami/react-zen'; import { FilterLink } from '@/components/common/FilterLink'; import { Favicon } from '@/components/common/Favicon'; -import { FilterButtons } from '@/components/common/FilterButtons'; +import { FilterButtons } from '@/components/input/FilterButtons'; import { useMessages, useNavigation } from '@/components/hooks'; import { MetricsTable, MetricsTableProps } from './MetricsTable'; import thenby from 'thenby'; diff --git a/src/index.ts b/src/index.ts index 243d5ea7..0f89b6fb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,6 +17,7 @@ export * from '@/app/(main)/settings/teams/TeamAddForm'; export * from '@/app/(main)/settings/teams/TeamJoinForm'; export * from '@/app/(main)/settings/teams/TeamLeaveButton'; export * from '@/app/(main)/settings/teams/TeamLeaveForm'; +export * from '@/app/(main)/settings/teams/[teamId]/TeamProvider'; export * from '@/app/(main)/settings/teams/TeamsAddButton'; export * from '@/app/(main)/settings/teams/TeamsDataTable'; export * from '@/app/(main)/settings/teams/TeamsHeader'; @@ -37,7 +38,6 @@ export * from '@/app/(main)/settings/websites/WebsitesDataTable'; export * from '@/app/(main)/settings/websites/WebsitesHeader'; export * from '@/app/(main)/settings/websites/WebsitesTable'; -export * from '@/app/(main)/teams/[teamId]/TeamProvider'; export * from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; export * from '@/components/common/ConfirmationForm'; @@ -46,7 +46,7 @@ export * from '@/components/common/Empty'; export * from '@/components/common/ErrorBoundary'; export * from '@/components/common/ErrorMessage'; export * from '@/components/common/Favicon'; -export * from '@/components/common/FilterButtons'; +export * from '@/components/input/FilterButtons'; export * from '@/components/common/FilterLink'; export * from '@/components/common/HamburgerButton'; export * from '@/components/common/LinkButton'; From 38f251ead51fbea90afdc776fe4c1c94b15655e7 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Thu, 7 Aug 2025 09:47:18 -0700 Subject: [PATCH 147/399] finish expanded queries and ui. --- db/clickhouse/schema.sql | 4 +- src/app/api/reports/utm/route.ts | 2 +- .../websites/[websiteId]/sessions/route.ts | 3 +- src/components/metrics/ListExpandedTable.tsx | 35 ++++------ src/components/metrics/MetricsTable.tsx | 4 +- src/components/metrics/ReferrersTable.tsx | 39 ++--------- src/lib/constants.ts | 6 ++ src/queries/sql/events/getWebsiteEvents.ts | 5 +- .../pageviews/getPageviewExpandedMetrics.ts | 31 +++++++-- .../sql/pageviews/getPageviewMetrics.ts | 23 +++---- src/queries/sql/reports/getUTM.ts | 64 +++++++++---------- .../sql/sessions/getWebsiteSessions.ts | 16 ++++- 12 files changed, 119 insertions(+), 113 deletions(-) diff --git a/db/clickhouse/schema.sql b/db/clickhouse/schema.sql index 41b3a1b3..be277743 100644 --- a/db/clickhouse/schema.sql +++ b/db/clickhouse/schema.sql @@ -57,7 +57,7 @@ CREATE TABLE umami.event_data event_name String, data_key String, string_value Nullable(String), - number_value Nullable(Decimal64(4)), + number_value Nullable(Decimal64(22, 4)), date_value Nullable(DateTime('UTC')), data_type UInt32, created_at DateTime('UTC'), @@ -73,7 +73,7 @@ CREATE TABLE umami.session_data session_id UUID, data_key String, string_value Nullable(String), - number_value Nullable(Decimal64(4)), + number_value Nullable(Decimal64(22, 4)), date_value Nullable(DateTime('UTC')), data_type UInt32, distinct_id String, diff --git a/src/app/api/reports/utm/route.ts b/src/app/api/reports/utm/route.ts index 17c5c1c6..150773f7 100644 --- a/src/app/api/reports/utm/route.ts +++ b/src/app/api/reports/utm/route.ts @@ -17,8 +17,8 @@ export async function POST(request: Request) { return unauthorized(); } - const parameters = await setWebsiteDate(websiteId, body.parameters); const filters = await getQueryFilters(body.filters, websiteId); + const parameters = await setWebsiteDate(websiteId, body.parameters); const data = await getUTM(websiteId, parameters as UTMParameters, filters); diff --git a/src/app/api/websites/[websiteId]/sessions/route.ts b/src/app/api/websites/[websiteId]/sessions/route.ts index bcc4b8bc..5f81e14c 100644 --- a/src/app/api/websites/[websiteId]/sessions/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/route.ts @@ -2,7 +2,7 @@ import { z } from 'zod'; import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/lib/auth'; -import { dateRangeParams, filterParams, pagingParams } from '@/lib/schema'; +import { dateRangeParams, filterParams, pagingParams, searchParams } from '@/lib/schema'; import { getWebsiteSessions } from '@/queries'; export async function GET( @@ -13,6 +13,7 @@ export async function GET( ...dateRangeParams, ...filterParams, ...pagingParams, + ...searchParams, }); const { auth, query, error } = await parseRequest(request, schema); diff --git a/src/components/metrics/ListExpandedTable.tsx b/src/components/metrics/ListExpandedTable.tsx index dc27b17f..82285237 100644 --- a/src/components/metrics/ListExpandedTable.tsx +++ b/src/components/metrics/ListExpandedTable.tsx @@ -7,11 +7,10 @@ import styles from './ListExpandedTable.module.css'; export interface ListExpandedTableProps { data?: any[]; title?: string; - type?: string; renderLabel?: (row: any, index: number) => ReactNode; } -export function ListExpandedTable({ data = [], title, type, renderLabel }: ListExpandedTableProps) { +export function ListExpandedTable({ data = [], title, renderLabel }: ListExpandedTableProps) { const { formatMessage, labels } = useMessages(); return ( @@ -32,26 +31,18 @@ export function ListExpandedTable({ data = [], title, type, renderLabel }: ListE {row => row?.['pageviews']?.toLocaleString()} - {type !== 'exit' && type !== 'entry' ? ( - - {row => { - const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100; - return Math.round(+n) + '%'; - }} - - ) : ( - <> - )} - {type !== 'exit' && type !== 'entry' ? ( - - {row => { - const n = (row?.['totaltime'] / row?.['visits']) * 100; - return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`; - }} - - ) : ( - <> - )} + + {row => { + const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100; + return Math.round(+n) + '%'; + }} + + + {row => { + const n = (row?.['totaltime'] / row?.['visits']) * 100; + return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`; + }} + ); } diff --git a/src/components/metrics/MetricsTable.tsx b/src/components/metrics/MetricsTable.tsx index fb97f8db..c18e46e4 100644 --- a/src/components/metrics/MetricsTable.tsx +++ b/src/components/metrics/MetricsTable.tsx @@ -114,7 +114,7 @@ export function MetricsTable({ return ( - + {allowSearch && } @@ -124,7 +124,7 @@ export function MetricsTable({ {data && (expanded ? ( - + ) : ( ))} diff --git a/src/components/metrics/ReferrersTable.tsx b/src/components/metrics/ReferrersTable.tsx index 0b3f1ee3..718f13ee 100644 --- a/src/components/metrics/ReferrersTable.tsx +++ b/src/components/metrics/ReferrersTable.tsx @@ -1,11 +1,11 @@ -import { Row } from '@umami/react-zen'; -import { FilterLink } from '@/components/common/FilterLink'; import { Favicon } from '@/components/common/Favicon'; import { FilterButtons } from '@/components/common/FilterButtons'; +import { FilterLink } from '@/components/common/FilterLink'; import { useMessages, useNavigation } from '@/components/hooks'; -import { MetricsTable, MetricsTableProps } from './MetricsTable'; -import thenby from 'thenby'; import { GROUPED_DOMAINS } from '@/lib/constants'; +import { emptyFilter } from '@/lib/filters'; +import { Row } from '@umami/react-zen'; +import { MetricsTable, MetricsTableProps } from './MetricsTable'; export interface ReferrersTableProps extends MetricsTableProps { allowFilter?: boolean; @@ -36,7 +36,7 @@ export function ReferrersTable({ allowFilter, ...props }: ReferrersTableProps) { const renderLink = ({ x: referrer }) => { if (view === 'grouped') { - if (referrer === '_other') { + if (referrer === 'Other') { return `(${formatMessage(labels.other)})`; } else { return ( @@ -60,38 +60,13 @@ export function ReferrersTable({ allowFilter, ...props }: ReferrersTableProps) { ); }; - const getDomain = (x: string) => { - for (const { domain, match } of GROUPED_DOMAINS) { - if (Array.isArray(match) ? match.some(str => x.includes(str)) : x.includes(match)) { - return domain; - } - } - return '_other'; - }; - - const groupedFilter = (data: any[]) => { - const groups = { _other: 0 }; - - for (const { x, y } of data) { - const domain = getDomain(x); - if (!groups[domain]) { - groups[domain] = 0; - } - groups[domain] += +y; - } - - return Object.keys(groups) - .map((key: any) => ({ x: key, y: groups[key] })) - .sort(thenby.firstBy('y', -1)); - }; - return ( {allowFilter && } diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 16bb71af..18bda293 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -26,11 +26,13 @@ export const REALTIME_RANGE = 30; export const REALTIME_INTERVAL = 10000; export const UNIT_TYPES = ['year', 'month', 'hour', 'day', 'minute']; + export const EVENT_COLUMNS = [ 'path', 'entry', 'exit', 'referrer', + 'grouped', 'title', 'query', 'event', @@ -59,6 +61,7 @@ export const FILTER_COLUMNS = { entry: 'url_path', exit: 'url_path', referrer: 'referrer_domain', + grouped: 'referrer_domain', hostname: 'hostname', title: 'page_title', query: 'url_query', @@ -386,6 +389,9 @@ export const GROUPED_DOMAINS = [ { name: 'Snapchat', domain: 'snapchat.com', match: 'snapchat.' }, { name: 'Pinterest', domain: 'pinterest.com', match: 'pinterest.' }, { name: 'ChatGPT', domain: 'chatgpt.com', match: 'chatgpt.' }, + { name: 'Yahoo', domain: 'yahoo.com', match: 'yahoo.' }, + { name: 'Yandex', domain: 'yandex.ru', match: 'yandex.' }, + { name: 'Baidu', domain: 'baidu.com', match: 'baidu.' }, ]; export const MAP_FILE = '/datamaps.world.json'; diff --git a/src/queries/sql/events/getWebsiteEvents.ts b/src/queries/sql/events/getWebsiteEvents.ts index 3b620018..579593d6 100644 --- a/src/queries/sql/events/getWebsiteEvents.ts +++ b/src/queries/sql/events/getWebsiteEvents.ts @@ -19,7 +19,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { search: `%${search}%`, }); - const searchQuery = filters.search + const searchQuery = search ? `and ((event_name ilike {{search}} and event_type = 2) or (url_path ilike {{search}} and event_type = 1))` : ''; @@ -59,12 +59,13 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { async function clickhouseQuery(websiteId: string, filters: QueryFilters) { const { pagedRawQuery, parseFilters } = clickhouse; + const { search } = filters; const { queryParams, dateQuery, cohortQuery, filterQuery } = parseFilters({ ...filters, websiteId, }); - const searchQuery = filters.search + const searchQuery = search ? `and ((positionCaseInsensitive(event_name, {search:String}) > 0 and event_type = 2) or (positionCaseInsensitive(url_path, {search:String}) > 0 and event_type = 1))` : ''; diff --git a/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts b/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts index ebe31d7b..ce1f1df9 100644 --- a/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts +++ b/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts @@ -1,5 +1,5 @@ import clickhouse from '@/lib/clickhouse'; -import { EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; +import { EVENT_TYPE, FILTER_COLUMNS, GROUPED_DOMAINS, SESSION_COLUMNS } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import { QueryFilters } from '@/lib/types'; @@ -99,7 +99,7 @@ async function clickhouseQuery( filters: QueryFilters, ): Promise<{ x: string; y: number }[]> { const { type, limit = 500, offset = 0 } = parameters; - const column = FILTER_COLUMNS[type] || type; + let column = FILTER_COLUMNS[type] || type; const { rawQuery, parseFilters } = clickhouse; const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, @@ -112,21 +112,24 @@ async function clickhouseQuery( if (column === 'referrer_domain') { excludeDomain = `and referrer_domain != hostname and referrer_domain != ''`; + if (type === 'grouped') { + column = toClickHouseGroupedReferrer(GROUPED_DOMAINS); + } } if (type === 'entry' || type === 'exit') { - const aggregrate = type === 'entry' ? 'min' : 'max'; + const aggregrate = type === 'entry' ? 'argMin' : 'argMax'; + column = `x.${column}`; entryExitQuery = ` JOIN (select visit_id, - ${aggregrate}(created_at) target_created_at + ${aggregrate}(url_path, created_at) url_path from website_event where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} and event_type = {eventType:UInt32} group by visit_id) x - ON x.visit_id = website_event.visit_id - and x.target_created_at = website_event.created_at`; + ON x.visit_id = website_event.visit_id`; } return rawQuery( @@ -164,3 +167,19 @@ async function clickhouseQuery( { ...queryParams, ...parameters }, ); } + +export function toClickHouseGroupedReferrer( + domains: any[], + column: string = 'referrer_domain', +): string { + return [ + 'CASE', + ...domains.map(group => { + const matches = Array.isArray(group.match) ? group.match : [group.match]; + const formattedArray = matches.map(m => `'${m}'`).join(', '); + return ` WHEN multiSearchAny(${column}, [${formattedArray}]) != 0 THEN '${group.domain}'`; + }), + " ELSE 'Other'", + 'END', + ].join('\n'); +} diff --git a/src/queries/sql/pageviews/getPageviewMetrics.ts b/src/queries/sql/pageviews/getPageviewMetrics.ts index 4ebd4cd9..2403a8e8 100644 --- a/src/queries/sql/pageviews/getPageviewMetrics.ts +++ b/src/queries/sql/pageviews/getPageviewMetrics.ts @@ -30,7 +30,7 @@ async function relationalQuery( filters: QueryFilters, ): Promise { const { type, limit = 500, offset = 0 } = parameters; - const column = FILTER_COLUMNS[type] || type; + let column = FILTER_COLUMNS[type] || type; const { rawQuery, parseFilters } = prisma; const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters( { @@ -50,20 +50,21 @@ async function relationalQuery( } if (type === 'entry' || type === 'exit') { - const aggregrate = type === 'entry' ? 'min' : 'max'; + const order = type === 'entry' ? 'asc' : 'desc'; + column = `x.${column}`; entryExitQuery = ` join ( - select visit_id, - ${aggregrate}(created_at) target_created_at + select distinct on (visit_id) + visit_id, + url_path from website_event where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} and event_type = {{eventType}} - group by visit_id + order by visit_id, created_at ${order} ) x on x.visit_id = website_event.visit_id - and x.target_created_at = website_event.created_at `; } @@ -95,7 +96,7 @@ async function clickhouseQuery( filters: QueryFilters, ): Promise<{ x: string; y: number }[]> { const { type, limit = 500, offset = 0 } = parameters; - const column = FILTER_COLUMNS[type] || type; + let column = FILTER_COLUMNS[type] || type; const { rawQuery, parseFilters } = clickhouse; const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, @@ -114,18 +115,18 @@ async function clickhouseQuery( } if (type === 'entry' || type === 'exit') { - const aggregrate = type === 'entry' ? 'min' : 'max'; + const aggregrate = type === 'entry' ? 'argMin' : 'argMax'; + column = `x.${column}`; entryExitQuery = ` JOIN (select visit_id, - ${aggregrate}(created_at) target_created_at + ${aggregrate}(url_path, created_at) url_path from website_event where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} and event_type = {eventType:UInt32} group by visit_id) x - ON x.visit_id = website_event.visit_id - and x.target_created_at = website_event.created_at`; + ON x.visit_id = website_event.visit_id`; } sql = ` diff --git a/src/queries/sql/reports/getUTM.ts b/src/queries/sql/reports/getUTM.ts index f96c62d3..f690be1c 100644 --- a/src/queries/sql/reports/getUTM.ts +++ b/src/queries/sql/reports/getUTM.ts @@ -1,16 +1,15 @@ import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; +import { QueryFilters } from '@/lib/types'; + +export interface UTMParameters { + startDate: Date; + endDate: Date; +} export async function getUTM( - ...args: [ - websiteId: string, - filters: { - startDate: Date; - endDate: Date; - timezone?: string; - }, - ] + ...args: [websiteId: string, parameters: UTMParameters, filters: QueryFilters] ) { return runQuery({ [PRISMA]: () => relationalQuery(...args), @@ -20,14 +19,18 @@ export async function getUTM( async function relationalQuery( websiteId: string, - filters: { - startDate: Date; - endDate: Date; - timezone?: string; - }, + parameters: UTMParameters, + filters: QueryFilters, ) { - const { startDate, endDate } = filters; - const { rawQuery } = prisma; + const { startDate, endDate } = parameters; + const { parseFilters, rawQuery } = prisma; + + const { filterQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + startDate, + endDate, + }); return rawQuery( ` @@ -37,26 +40,26 @@ async function relationalQuery( and created_at between {{startDate}} and {{endDate}} and coalesce(url_query, '') != '' and event_type = 1 + ${filterQuery} group by 1 `, - { - websiteId, - startDate, - endDate, - }, + queryParams, ); } async function clickhouseQuery( websiteId: string, - filters: { - startDate: Date; - endDate: Date; - timezone?: string; - }, + parameters: UTMParameters, + filters: QueryFilters, ) { - const { startDate, endDate } = filters; - const { rawQuery } = clickhouse; + const { startDate, endDate } = parameters; + const { parseFilters, rawQuery } = clickhouse; + const { filterQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + startDate, + endDate, + }); return rawQuery( ` @@ -66,12 +69,9 @@ async function clickhouseQuery( and created_at between {startDate:DateTime64} and {endDate:DateTime64} and url_query != '' and event_type = 1 + ${filterQuery} group by 1 `, - { - websiteId, - startDate, - endDate, - }, + queryParams, ); } diff --git a/src/queries/sql/sessions/getWebsiteSessions.ts b/src/queries/sql/sessions/getWebsiteSessions.ts index fdc1bf9c..c0942b20 100644 --- a/src/queries/sql/sessions/getWebsiteSessions.ts +++ b/src/queries/sql/sessions/getWebsiteSessions.ts @@ -20,7 +20,13 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { search: search ? `%${search}%` : undefined, }); - const searchQuery = search ? `and session.distinct_id ilike {{search}}` : ''; + const searchQuery = search + ? `and (distinct_id ilike {{search}} + or city ilike {{search}} + or browser ilike {{search}} + or os ilike {{search}} + or device ilike {{search}})` + : ''; return pagedRawQuery( ` @@ -74,7 +80,13 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) { websiteId, }); - const searchQuery = search ? `and positionCaseInsensitive(distinct_id, {search:String}) > 0` : ''; + const searchQuery = search + ? `and ((positionCaseInsensitive(distinct_id, {search:String}) > 0) + or (positionCaseInsensitive(city, {search:String}) > 0) + or (positionCaseInsensitive(browser, {search:String}) > 0) + or (positionCaseInsensitive(os, {search:String}) > 0) + or (positionCaseInsensitive(device, {search:String}) > 0))` + : ''; let sql = ''; From 0b4851125d37e76727d88a8d4317b87f8f6f380c Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 7 Aug 2025 12:36:11 -0700 Subject: [PATCH 148/399] Updated next and prisma. --- package.json | 16 +- pnpm-lock.yaml | 2328 ++++++++++++++++++++++++++---------------------- 2 files changed, 1295 insertions(+), 1049 deletions(-) diff --git a/package.json b/package.json index c2c9b3cc..d666d34e 100644 --- a/package.json +++ b/package.json @@ -76,8 +76,8 @@ "@dicebear/core": "^9.2.3", "@fontsource/inter": "^4.5.15", "@hello-pangea/dnd": "^17.0.0", - "@prisma/adapter-pg": "^6.12.0", - "@prisma/client": "^6.12.0", + "@prisma/adapter-pg": "^6.13.0", + "@prisma/client": "^6.13.0", "@prisma/extension-read-replicas": "^0.4.1", "@react-spring/web": "^9.7.3", "@svgr/cli": "^8.1.0", @@ -112,16 +112,16 @@ "lucide-react": "^0.526.0", "maxmind": "^4.3.28", "md5": "^2.3.0", - "next": "15.4.4", + "next": "15.4.6", "node-fetch": "^3.2.8", "npm-run-all": "^4.1.5", "papaparse": "^5.5.3", "pg": "^8.16.3", - "prisma": "6.12.0", + "prisma": "6.13.0", "pure-rand": "^7.0.1", - "react": "^19.0.0", + "react": "^19.1.1", "react-basics": "^0.126.0", - "react-dom": "^19.0.0", + "react-dom": "^19.1.1", "react-error-boundary": "^4.0.4", "react-intl": "^7.1.11", "react-simple-maps": "^2.3.0", @@ -146,8 +146,8 @@ "@rollup/plugin-terser": "^0.4.4", "@types/jest": "^29.5.14", "@types/node": "^22.16.5", - "@types/react": "^19.1.8", - "@types/react-dom": "^19.1.6", + "@types/react": "^19.1.9", + "@types/react-dom": "^19.1.7", "@types/react-window": "^1.8.8", "@typescript-eslint/eslint-plugin": "^8.38.0", "@typescript-eslint/parser": "^8.38.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fce70ca0..392dc12b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,28 +25,28 @@ importers: version: 4.5.15 '@hello-pangea/dnd': specifier: ^17.0.0 - version: 17.0.0(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 17.0.0(@types/react@19.1.9)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@prisma/adapter-pg': - specifier: ^6.12.0 - version: 6.12.0 + specifier: ^6.13.0 + version: 6.13.0 '@prisma/client': - specifier: ^6.12.0 - version: 6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3) + specifier: ^6.13.0 + version: 6.13.0(prisma@6.13.0(typescript@5.8.3))(typescript@5.8.3) '@prisma/extension-read-replicas': specifier: ^0.4.1 - version: 0.4.1(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3)) + version: 0.4.1(@prisma/client@6.13.0(prisma@6.13.0(typescript@5.8.3))(typescript@5.8.3)) '@react-spring/web': specifier: ^9.7.3 - version: 9.7.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 9.7.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@svgr/cli': specifier: ^8.1.0 version: 8.1.0(typescript@5.8.3) '@tanstack/react-query': specifier: ^5.83.0 - version: 5.83.0(react@19.1.0) + version: 5.83.0(react@19.1.1) '@umami/react-zen': specifier: ^0.157.0 - version: 0.157.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0)) + version: 0.157.0(@babel/core@7.27.1)(@types/react@19.1.9)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.1)) '@umami/redis-client': specifier: ^0.27.0 version: 0.27.0 @@ -127,7 +127,7 @@ importers: version: 2.2.4 lucide-react: specifier: ^0.526.0 - version: 0.526.0(react@19.1.0) + version: 0.526.0(react@19.1.1) maxmind: specifier: ^4.3.28 version: 4.3.28 @@ -135,8 +135,8 @@ importers: specifier: ^2.3.0 version: 2.3.0 next: - specifier: 15.4.4 - version: 15.4.4(@babel/core@7.27.1)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 15.4.6 + version: 15.4.6(@babel/core@7.27.1)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) node-fetch: specifier: ^3.2.8 version: 3.3.2 @@ -150,35 +150,35 @@ importers: specifier: ^8.16.3 version: 8.16.3 prisma: - specifier: 6.12.0 - version: 6.12.0(typescript@5.8.3) + specifier: 6.13.0 + version: 6.13.0(typescript@5.8.3) pure-rand: specifier: ^7.0.1 version: 7.0.1 react: - specifier: ^19.0.0 - version: 19.1.0 + specifier: ^19.1.1 + version: 19.1.1 react-basics: specifier: ^0.126.0 - version: 0.126.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 0.126.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react-dom: - specifier: ^19.0.0 - version: 19.1.0(react@19.1.0) + specifier: ^19.1.1 + version: 19.1.1(react@19.1.1) react-error-boundary: specifier: ^4.0.4 - version: 4.1.2(react@19.1.0) + version: 4.1.2(react@19.1.1) react-intl: specifier: ^7.1.11 - version: 7.1.11(react@19.1.0)(typescript@5.8.3) + version: 7.1.11(react@19.1.1)(typescript@5.8.3) react-simple-maps: specifier: ^2.3.0 - version: 2.3.0(prop-types@15.8.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 2.3.0(prop-types@15.8.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react-use-measure: specifier: ^2.0.4 - version: 2.1.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 2.1.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react-window: specifier: ^1.8.6 - version: 1.8.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.8.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) request-ip: specifier: ^3.3.0 version: 3.3.0 @@ -199,7 +199,7 @@ importers: version: 3.25.76 zustand: specifier: ^5.0.6 - version: 5.0.6(@types/react@19.1.8)(immer@9.0.21)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)) + version: 5.0.6(@types/react@19.1.9)(immer@9.0.21)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)) devDependencies: '@formatjs/cli': specifier: ^4.2.29 @@ -232,11 +232,11 @@ importers: specifier: ^22.16.5 version: 22.16.5 '@types/react': - specifier: ^19.1.8 - version: 19.1.8 + specifier: ^19.1.9 + version: 19.1.9 '@types/react-dom': - specifier: ^19.1.6 - version: 19.1.6(@types/react@19.1.8) + specifier: ^19.1.7 + version: 19.1.7(@types/react@19.1.9) '@types/react-window': specifier: ^1.8.8 version: 1.8.8 @@ -1381,56 +1381,56 @@ packages: resolution: {integrity: sha512-F+HiQaUpISBmooALpwDULoCCwUhI6MugEEBstjuxOL2rh2ROFhK4abv87f4GxVXRSmw0AtXAp2eiP8vHcZ3NKQ==} engines: {node: '>=18.0.0'} - '@next/env@15.4.4': - resolution: {integrity: sha512-SJKOOkULKENyHSYXE5+KiFU6itcIb6wSBjgM92meK0HVKpo94dNOLZVdLLuS7/BxImROkGoPsjR4EnuDucqiiA==} + '@next/env@15.4.6': + resolution: {integrity: sha512-yHDKVTcHrZy/8TWhj0B23ylKv5ypocuCwey9ZqPyv4rPdUdRzpGCkSi03t04KBPyU96kxVtUqx6O3nE1kpxASQ==} '@next/eslint-plugin-next@14.2.30': resolution: {integrity: sha512-mvVsMIutMxQ4NGZEMZ1kiBNc+la8Xmlk30bKUmCPQz2eFkmsLv54Mha8QZarMaCtSPkkFA1TMD+FIZk0l/PpzA==} - '@next/swc-darwin-arm64@15.4.4': - resolution: {integrity: sha512-eVG55dnGwfUuG+TtnUCt+mEJ+8TGgul6nHEvdb8HEH7dmJIFYOCApAaFrIrxwtEq2Cdf+0m5sG1Np8cNpw9EAw==} + '@next/swc-darwin-arm64@15.4.6': + resolution: {integrity: sha512-667R0RTP4DwxzmrqTs4Lr5dcEda9OxuZsVFsjVtxVMVhzSpo6nLclXejJVfQo2/g7/Z9qF3ETDmN3h65mTjpTQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.4.4': - resolution: {integrity: sha512-zqG+/8apsu49CltEj4NAmCGZvHcZbOOOsNoTVeIXphYWIbE4l6A/vuQHyqll0flU2o3dmYCXsBW5FmbrGDgljQ==} + '@next/swc-darwin-x64@15.4.6': + resolution: {integrity: sha512-KMSFoistFkaiQYVQQnaU9MPWtp/3m0kn2Xed1Ces5ll+ag1+rlac20sxG+MqhH2qYWX1O2GFOATQXEyxKiIscg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.4.4': - resolution: {integrity: sha512-LRD4l2lq4R+2QCHBQVC0wjxxkLlALGJCwigaJ5FSRSqnje+MRKHljQNZgDCaKUZQzO/TXxlmUdkZP/X3KNGZaw==} + '@next/swc-linux-arm64-gnu@15.4.6': + resolution: {integrity: sha512-PnOx1YdO0W7m/HWFeYd2A6JtBO8O8Eb9h6nfJia2Dw1sRHoHpNf6lN1U4GKFRzRDBi9Nq2GrHk9PF3Vmwf7XVw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.4.4': - resolution: {integrity: sha512-LsGUCTvuZ0690fFWerA4lnQvjkYg9gHo12A3wiPUR4kCxbx/d+SlwmonuTH2SWZI+RVGA9VL3N0S03WTYv6bYg==} + '@next/swc-linux-arm64-musl@15.4.6': + resolution: {integrity: sha512-XBbuQddtY1p5FGPc2naMO0kqs4YYtLYK/8aPausI5lyOjr4J77KTG9mtlU4P3NwkLI1+OjsPzKVvSJdMs3cFaw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.4.4': - resolution: {integrity: sha512-aOy5yNRpLL3wNiJVkFYl6w22hdREERNjvegE6vvtix8LHRdsTHhWTpgvcYdCK7AIDCQW5ATmzr9XkPHvSoAnvg==} + '@next/swc-linux-x64-gnu@15.4.6': + resolution: {integrity: sha512-+WTeK7Qdw82ez3U9JgD+igBAP75gqZ1vbK6R8PlEEuY0OIe5FuYXA4aTjL811kWPf7hNeslD4hHK2WoM9W0IgA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.4.4': - resolution: {integrity: sha512-FL7OAn4UkR8hKQRGBmlHiHinzOb07tsfARdGh7v0Z0jEJ3sz8/7L5bR23ble9E6DZMabSStqlATHlSxv1fuzAg==} + '@next/swc-linux-x64-musl@15.4.6': + resolution: {integrity: sha512-XP824mCbgQsK20jlXKrUpZoh/iO3vUWhMpxCz8oYeagoiZ4V0TQiKy0ASji1KK6IAe3DYGfj5RfKP6+L2020OQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.4.4': - resolution: {integrity: sha512-eEdNW/TXwjYhOulQh0pffTMMItWVwKCQpbziSBmgBNFZIIRn2GTXrhrewevs8wP8KXWYMx8Z+mNU0X+AfvtrRg==} + '@next/swc-win32-arm64-msvc@15.4.6': + resolution: {integrity: sha512-FxrsenhUz0LbgRkNWx6FRRJIPe/MI1JRA4W4EPd5leXO00AZ6YU8v5vfx4MDXTvN77lM/EqsE3+6d2CIeF5NYg==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.4.4': - resolution: {integrity: sha512-SE5pYNbn/xZKMy1RE3pAs+4xD32OI4rY6mzJa4XUkp/ItZY+OMjIgilskmErt8ls/fVJ+Ihopi2QIeW6O3TrMw==} + '@next/swc-win32-x64-msvc@15.4.6': + resolution: {integrity: sha512-T4ufqnZ4u88ZheczkBTtOF+eKaM14V8kbjud/XrAakoM5DKQWjW09vD6B9fsdsWS2T7D5EY31hRHdta7QKWOng==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1459,11 +1459,11 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@prisma/adapter-pg@6.12.0': - resolution: {integrity: sha512-lyNDD0oJntw9D6WilEUCXqaKPZWDLNwePbUZogadhIJ4qICaIoPXQuLGGe7auXdvGcfesCb1y1UKvdYj0iFgQg==} + '@prisma/adapter-pg@6.13.0': + resolution: {integrity: sha512-9jAb5F5gFDlh2jSbRRcB2W8L06WZtQWXcPtRxvoUuXubaGzCrQ/HxizwxsIjcvDSDe5YprQA2oUMM61jfSaQIg==} - '@prisma/client@6.12.0': - resolution: {integrity: sha512-wn98bJ3Cj6edlF4jjpgXwbnQIo/fQLqqQHPk2POrZPxTlhY3+n90SSIF3LMRVa8VzRFC/Gec3YKJRxRu+AIGVA==} + '@prisma/client@6.13.0': + resolution: {integrity: sha512-8m2+I3dQovkV8CkDMluiwEV1TxV9EXdT6xaCz39O6jYw7mkf5gwfmi+cL4LJsEPwz5tG7sreBwkRpEMJedGYUQ==} engines: {node: '>=18.18'} peerDependencies: prisma: '*' @@ -1474,31 +1474,31 @@ packages: typescript: optional: true - '@prisma/config@6.12.0': - resolution: {integrity: sha512-HovZWzhWEMedHxmjefQBRZa40P81N7/+74khKFz9e1AFjakcIQdXgMWKgt20HaACzY+d1LRBC+L4tiz71t9fkg==} + '@prisma/config@6.13.0': + resolution: {integrity: sha512-OYMM+pcrvj/NqNWCGESSxVG3O7kX6oWuGyvufTUNnDw740KIQvNyA4v0eILgkpuwsKIDU36beZCkUtIt0naTog==} - '@prisma/debug@6.12.0': - resolution: {integrity: sha512-plbz6z72orcqr0eeio7zgUrZj5EudZUpAeWkFTA/DDdXEj28YHDXuiakvR6S7sD6tZi+jiwQEJAPeV6J6m/tEQ==} + '@prisma/debug@6.13.0': + resolution: {integrity: sha512-um+9pfKJW0ihmM83id9FXGi5qEbVJ0Vxi1Gm0xpYsjwUBnw6s2LdPBbrsG9QXRX46K4CLWCTNvskXBup4i9hlw==} - '@prisma/driver-adapter-utils@6.12.0': - resolution: {integrity: sha512-uSUKB17Xs4pZB1UJZL6+PHV9Ab6vCWD20nXoimb5YG4vPqtBVdPKNYa35QbDgdUQbX321daUcgYTsLY/jxOG3w==} + '@prisma/driver-adapter-utils@6.13.0': + resolution: {integrity: sha512-72gQS/rz0KRV1bvi37OGu5PgMAzTQplFZuTo1kSb4hK7sm0PTvl7+V4NFHdwXEUecTq/+FnF9Ts9Ac+iKPnEow==} - '@prisma/engines-version@6.12.0-15.8047c96bbd92db98a2abc7c9323ce77c02c89dbc': - resolution: {integrity: sha512-70vhecxBJlRr06VfahDzk9ow4k1HIaSfVUT3X0/kZoHCMl9zbabut4gEXAyzJZxaCGi5igAA7SyyfBI//mmkbQ==} + '@prisma/engines-version@6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd': + resolution: {integrity: sha512-MpPyKSzBX7P/ZY9odp9TSegnS/yH3CSbchQE9f0yBg3l2QyN59I6vGXcoYcqKC9VTniS1s18AMmhyr1OWavjHg==} - '@prisma/engines@6.12.0': - resolution: {integrity: sha512-4BRZZUaAuB4p0XhTauxelvFs7IllhPmNLvmla0bO1nkECs8n/o1pUvAVbQ/VOrZR5DnF4HED0PrGai+rIOVePA==} + '@prisma/engines@6.13.0': + resolution: {integrity: sha512-D+1B79LFvtWA0KTt8ALekQ6A/glB9w10ETknH5Y9g1k2NYYQOQy93ffiuqLn3Pl6IPJG3EsK/YMROKEaq8KBrA==} '@prisma/extension-read-replicas@0.4.1': resolution: {integrity: sha512-mCMDloqUKUwx2o5uedTs1FHX3Nxdt1GdRMoeyp1JggjiwOALmIYWhxfIN08M2BZ0w8SKwvJqicJZMjkQYkkijw==} peerDependencies: '@prisma/client': ^6.5.0 - '@prisma/fetch-engine@6.12.0': - resolution: {integrity: sha512-EamoiwrK46rpWaEbLX9aqKDPOd8IyLnZAkiYXFNuq0YsU0Z8K09/rH8S7feOWAVJ3xzeSgcEJtBlVDrajM9Sag==} + '@prisma/fetch-engine@6.13.0': + resolution: {integrity: sha512-grmmq+4FeFKmaaytA8Ozc2+Tf3BC8xn/DVJos6LL022mfRlMZYjT3hZM0/xG7+5fO95zFG9CkDUs0m1S2rXs5Q==} - '@prisma/get-platform@6.12.0': - resolution: {integrity: sha512-nRerTGhTlgyvcBlyWgt8OLNIV7QgJS2XYXMJD1hysorMCuLAjuDDuoxmVt7C2nLxbuxbWPp7OuFRHC23HqD9dA==} + '@prisma/get-platform@6.13.0': + resolution: {integrity: sha512-Nii2pX50fY4QKKxQwm7/vvqT6Ku8yYJLZAFX4e2vzHwRdMqjugcOG5hOSLjxqoXb0cvOspV70TOhMzrw8kqAnw==} '@react-aria/autocomplete@3.0.0-beta.3': resolution: {integrity: sha512-8haBygHNMqVt4Ge90VOk+iVlLW+zhiOGHYz2IKCE6+Sy1dTE6mzhHjxrtwWYnSez/OQLbxjHlwLch4CDd5JkLA==} @@ -2226,6 +2226,9 @@ packages: '@sinonjs/fake-timers@10.3.0': resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@standard-schema/spec@1.0.0': + resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} + '@svgr/babel-plugin-add-jsx-attribute@8.0.0': resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} engines: {node: '>=14'} @@ -2416,16 +2419,16 @@ packages: '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/react-dom@19.1.6': - resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==} + '@types/react-dom@19.1.7': + resolution: {integrity: sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==} peerDependencies: '@types/react': ^19.0.0 '@types/react-window@1.8.8': resolution: {integrity: sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==} - '@types/react@19.1.8': - resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} + '@types/react@19.1.9': + resolution: {integrity: sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==} '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -2940,6 +2943,14 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + c12@3.1.0: + resolution: {integrity: sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==} + peerDependencies: + magicast: ^0.3.5 + peerDependenciesMeta: + magicast: + optional: true + cachedir@2.4.0: resolution: {integrity: sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==} engines: {node: '>=6'} @@ -2982,8 +2993,8 @@ packages: caniuse-lite@1.0.30001718: resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==} - caniuse-lite@1.0.30001727: - resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==} + caniuse-lite@1.0.30001731: + resolution: {integrity: sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==} caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -3025,6 +3036,10 @@ packages: resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==} engines: {node: '>= 0.8.0'} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} @@ -3037,6 +3052,9 @@ packages: resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} engines: {node: '>=8'} + citty@0.1.6: + resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + cjs-module-lexer@1.4.3: resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} @@ -3158,6 +3176,13 @@ packages: concat-with-sourcemaps@1.1.0: resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} + confbox@0.2.2: + resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -3433,6 +3458,10 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deepmerge-ts@7.1.5: + resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==} + engines: {node: '>=16.0.0'} + deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -3445,6 +3474,9 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + del@6.1.1: resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} engines: {node: '>=10'} @@ -3453,6 +3485,9 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + detect-browser@5.3.0: resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} @@ -3518,6 +3553,10 @@ packages: resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==} engines: {node: '>=10'} + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -3531,6 +3570,9 @@ packages: ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + effect@3.16.12: + resolution: {integrity: sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==} + ejs@3.1.10: resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} @@ -3846,6 +3888,9 @@ packages: resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + exsolve@1.0.7: + resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -3863,6 +3908,10 @@ packages: resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} engines: {'0': node >=0.6.0} + fast-check@3.23.2: + resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} + engines: {node: '>=8.0.0'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -3926,6 +3975,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + find-up-simple@1.0.1: + resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} + engines: {node: '>=18'} + find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -4049,6 +4102,10 @@ packages: getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + giget@2.0.0: + resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} + hasBin: true + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -4174,6 +4231,10 @@ packages: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -4261,6 +4322,10 @@ packages: resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} engines: {node: '>=12'} + index-to-position@1.1.0: + resolution: {integrity: sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==} + engines: {node: '>=18'} + inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -4668,8 +4733,8 @@ packages: node-notifier: optional: true - jiti@2.4.2: - resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + jiti@2.5.1: + resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==} hasBin: true joycon@3.1.1: @@ -5116,8 +5181,8 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - next@15.4.4: - resolution: {integrity: sha512-kNcubvJjOL9yUOfwtZF3HfDhuhp+kVD+FM2A6Tyua1eI/xfmY4r/8ZS913MMz+oWKDlbps/dQOWdDricuIkXLw==} + next@15.4.6: + resolution: {integrity: sha512-us++E/Q80/8+UekzB3SAGs71AlLDsadpFMXVNM/uQ0BMwsh9m3mr0UNQIfjKed8vpWXsASe+Qifrnu1oLIcKEQ==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -5148,6 +5213,9 @@ packages: engines: {node: '>=10.5.0'} deprecated: Use your platform's native DOMException instead + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + node-fetch@3.3.2: resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -5165,6 +5233,10 @@ packages: resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} engines: {node: '>=10'} + normalize-package-data@6.0.2: + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} + engines: {node: ^16.14.0 || >=18.0.0} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -5193,6 +5265,11 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + nypm@0.6.1: + resolution: {integrity: sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==} + engines: {node: ^14.16.0 || >=16.10.0} + hasBin: true + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -5225,6 +5302,9 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -5304,6 +5384,10 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + parse-json@8.3.0: + resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==} + engines: {node: '>=18'} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -5339,9 +5423,15 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + performance-now@2.1.0: resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} @@ -5420,6 +5510,9 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} + pkg-types@2.2.0: + resolution: {integrity: sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==} + possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -5884,8 +5977,8 @@ packages: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - prisma@6.12.0: - resolution: {integrity: sha512-pmV7NEqQej9WjizN6RSNIwf7Y+jeh9mY1JEX2WjGxJi4YZWexClhde1yz/FuvAM+cTwzchcMytu2m4I6wPkIzg==} + prisma@6.13.0: + resolution: {integrity: sha512-dfzORf0AbcEyyzxuv2lEwG8g+WRGF/qDQTpHf/6JoHsyF5MyzCEZwClVaEmw3WXcobgadosOboKUgQU0kFs9kw==} engines: {node: '>=18.18'} hasBin: true peerDependencies: @@ -5949,6 +6042,9 @@ packages: randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + rc9@2.1.2: + resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} + react-aria-components@1.9.0: resolution: {integrity: sha512-7cOYxvODDPn8PlWh7eM6/hcydM9sem9PJfL9XD90hIUGfX/f5wMu4lplpjFVzkoCPe4UcOrqC77k3vpRN+1eaw==} peerDependencies: @@ -5968,10 +6064,10 @@ packages: react: ^18.2.0 react-dom: ^18.2.0 - react-dom@19.1.0: - resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} + react-dom@19.1.1: + resolution: {integrity: sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==} peerDependencies: - react: ^19.1.0 + react: ^19.1.1 react-error-boundary@4.1.2: resolution: {integrity: sha512-GQDxZ5Jd+Aq/qUxbCm1UtzmL/s++V7zKgE8yMktJiCQXCCFZnMZh9ng+6/Ne6PjNSXH0L9CjeOEREfRnq6Duag==} @@ -6050,8 +6146,8 @@ packages: react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react@19.1.0: - resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} + react@19.1.1: + resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} engines: {node: '>=0.10.0'} read-babelrc-up@1.1.0: @@ -6061,6 +6157,10 @@ packages: read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + read-package-up@11.0.0: + resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==} + engines: {node: '>=18'} + read-pkg-up@7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} @@ -6081,9 +6181,17 @@ packages: resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==} engines: {node: '>=12'} + read-pkg@9.0.1: + resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} + engines: {node: '>=18'} + readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -6631,6 +6739,9 @@ packages: resolution: {integrity: sha512-/ShxBZOgHXDdZi7FxajcsH0MfcBqwP+t7i4T3PGjI//NUA5aCpC7cB9bbdAYrAeQLBUTJfg2rk191fzZGeo7DA==} engines: {node: '>=12'} + tinyexec@1.0.1: + resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + tinyglobby@0.2.13: resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} engines: {node: '>=12.0.0'} @@ -6813,6 +6924,10 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -7744,17 +7859,17 @@ snapshots: optionalDependencies: ts-jest: 29.4.0(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.8)(jest-util@29.7.0)(jest@29.7.0(@types/node@22.16.5)(ts-node@10.9.2(@types/node@22.16.5)(typescript@5.8.3)))(typescript@5.8.3) - '@hello-pangea/dnd@17.0.0(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@hello-pangea/dnd@17.0.0(@types/react@19.1.9)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@babel/runtime': 7.27.1 css-box-model: 1.2.1 memoize-one: 6.0.0 raf-schd: 4.0.3 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - react-redux: 9.2.0(@types/react@19.1.8)(react@19.1.0)(redux@5.0.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + react-redux: 9.2.0(@types/react@19.1.9)(react@19.1.1)(redux@5.0.1) redux: 5.0.1 - use-memo-one: 1.1.3(react@19.1.0) + use-memo-one: 1.1.3(react@19.1.1) transitivePeerDependencies: - '@types/react' @@ -8092,34 +8207,34 @@ snapshots: '@netlify/plugin-nextjs@5.11.6': {} - '@next/env@15.4.4': {} + '@next/env@15.4.6': {} '@next/eslint-plugin-next@14.2.30': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@15.4.4': + '@next/swc-darwin-arm64@15.4.6': optional: true - '@next/swc-darwin-x64@15.4.4': + '@next/swc-darwin-x64@15.4.6': optional: true - '@next/swc-linux-arm64-gnu@15.4.4': + '@next/swc-linux-arm64-gnu@15.4.6': optional: true - '@next/swc-linux-arm64-musl@15.4.4': + '@next/swc-linux-arm64-musl@15.4.6': optional: true - '@next/swc-linux-x64-gnu@15.4.4': + '@next/swc-linux-x64-gnu@15.4.6': optional: true - '@next/swc-linux-x64-musl@15.4.4': + '@next/swc-linux-x64-musl@15.4.6': optional: true - '@next/swc-win32-arm64-msvc@15.4.4': + '@next/swc-win32-arm64-msvc@15.4.6': optional: true - '@next/swc-win32-x64-msvc@15.4.4': + '@next/swc-win32-x64-msvc@15.4.6': optional: true '@nodelib/fs.scandir@2.1.5': @@ -8141,1135 +8256,1140 @@ snapshots: '@pkgr/core@0.2.9': {} - '@prisma/adapter-pg@6.12.0': + '@prisma/adapter-pg@6.13.0': dependencies: - '@prisma/driver-adapter-utils': 6.12.0 + '@prisma/driver-adapter-utils': 6.13.0 pg: 8.16.3 postgres-array: 3.0.4 transitivePeerDependencies: - pg-native - '@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3)': + '@prisma/client@6.13.0(prisma@6.13.0(typescript@5.8.3))(typescript@5.8.3)': optionalDependencies: - prisma: 6.12.0(typescript@5.8.3) + prisma: 6.13.0(typescript@5.8.3) typescript: 5.8.3 - '@prisma/config@6.12.0': + '@prisma/config@6.13.0': dependencies: - jiti: 2.4.2 + c12: 3.1.0 + deepmerge-ts: 7.1.5 + effect: 3.16.12 + read-package-up: 11.0.0 + transitivePeerDependencies: + - magicast - '@prisma/debug@6.12.0': {} + '@prisma/debug@6.13.0': {} - '@prisma/driver-adapter-utils@6.12.0': + '@prisma/driver-adapter-utils@6.13.0': dependencies: - '@prisma/debug': 6.12.0 + '@prisma/debug': 6.13.0 - '@prisma/engines-version@6.12.0-15.8047c96bbd92db98a2abc7c9323ce77c02c89dbc': {} + '@prisma/engines-version@6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd': {} - '@prisma/engines@6.12.0': + '@prisma/engines@6.13.0': dependencies: - '@prisma/debug': 6.12.0 - '@prisma/engines-version': 6.12.0-15.8047c96bbd92db98a2abc7c9323ce77c02c89dbc - '@prisma/fetch-engine': 6.12.0 - '@prisma/get-platform': 6.12.0 + '@prisma/debug': 6.13.0 + '@prisma/engines-version': 6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd + '@prisma/fetch-engine': 6.13.0 + '@prisma/get-platform': 6.13.0 - '@prisma/extension-read-replicas@0.4.1(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))': + '@prisma/extension-read-replicas@0.4.1(@prisma/client@6.13.0(prisma@6.13.0(typescript@5.8.3))(typescript@5.8.3))': dependencies: - '@prisma/client': 6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3) + '@prisma/client': 6.13.0(prisma@6.13.0(typescript@5.8.3))(typescript@5.8.3) - '@prisma/fetch-engine@6.12.0': + '@prisma/fetch-engine@6.13.0': dependencies: - '@prisma/debug': 6.12.0 - '@prisma/engines-version': 6.12.0-15.8047c96bbd92db98a2abc7c9323ce77c02c89dbc - '@prisma/get-platform': 6.12.0 + '@prisma/debug': 6.13.0 + '@prisma/engines-version': 6.13.0-35.361e86d0ea4987e9f53a565309b3eed797a6bcbd + '@prisma/get-platform': 6.13.0 - '@prisma/get-platform@6.12.0': + '@prisma/get-platform@6.13.0': dependencies: - '@prisma/debug': 6.12.0 + '@prisma/debug': 6.13.0 - '@react-aria/autocomplete@3.0.0-beta.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/autocomplete@3.0.0-beta.3(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/combobox': 3.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/listbox': 3.14.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/searchfield': 3.8.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/textfield': 3.18.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/autocomplete': 3.0.0-beta.1(react@19.1.0) - '@react-stately/combobox': 3.11.0(react@19.1.0) - '@react-types/autocomplete': 3.0.0-alpha.31(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/combobox': 3.13.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/listbox': 3.14.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/searchfield': 3.8.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/textfield': 3.18.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/autocomplete': 3.0.0-beta.1(react@19.1.1) + '@react-stately/combobox': 3.11.0(react@19.1.1) + '@react-types/autocomplete': 3.0.0-alpha.31(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/breadcrumbs@3.5.27(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/breadcrumbs@3.5.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/link': 3.8.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/breadcrumbs': 3.7.15(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/link': 3.8.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/breadcrumbs': 3.7.15(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/button@3.14.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/button@3.14.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/toolbar': 3.0.0-beta.19(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/toggle': 3.9.0(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/toolbar': 3.0.0-beta.19(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/toggle': 3.9.0(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/calendar@3.9.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/calendar@3.9.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@internationalized/date': 3.8.2 - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@react-aria/live-announcer': 3.4.4 - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/calendar': 3.8.3(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/calendar': 3.7.3(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/calendar': 3.8.3(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/calendar': 3.7.3(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/checkbox@3.16.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/checkbox@3.16.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/form': 3.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/toggle': 3.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/checkbox': 3.7.0(react@19.1.0) - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/toggle': 3.9.0(react@19.1.0) - '@react-types/checkbox': 3.10.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/form': 3.1.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/label': 3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/toggle': 3.12.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/checkbox': 3.7.0(react@19.1.1) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/toggle': 3.9.0(react@19.1.1) + '@react-types/checkbox': 3.10.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/collections@3.0.0-rc.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/collections@3.0.0-rc.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/ssr': 3.9.10(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/ssr': 3.9.10(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - use-sync-external-store: 1.5.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + use-sync-external-store: 1.5.0(react@19.1.1) - '@react-aria/color@3.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/color@3.1.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/numberfield': 3.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/slider': 3.8.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/spinbutton': 3.6.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/textfield': 3.18.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/visually-hidden': 3.8.26(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/color': 3.9.0(react@19.1.0) - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-types/color': 3.1.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/numberfield': 3.12.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/slider': 3.8.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/spinbutton': 3.6.17(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/textfield': 3.18.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/visually-hidden': 3.8.26(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/color': 3.9.0(react@19.1.1) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-types/color': 3.1.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/combobox@3.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/combobox@3.13.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/listbox': 3.14.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/listbox': 3.14.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@react-aria/live-announcer': 3.4.4 - '@react-aria/menu': 3.19.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/overlays': 3.28.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/textfield': 3.18.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/combobox': 3.11.0(react@19.1.0) - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/combobox': 3.13.7(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/menu': 3.19.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/overlays': 3.28.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/selection': 3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/textfield': 3.18.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/combobox': 3.11.0(react@19.1.1) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/combobox': 3.13.7(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/datepicker@3.15.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/datepicker@3.15.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@internationalized/date': 3.8.2 '@internationalized/number': 3.6.4 '@internationalized/string': 3.2.7 - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/form': 3.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/spinbutton': 3.6.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/datepicker': 3.15.0(react@19.1.0) - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/calendar': 3.7.3(react@19.1.0) - '@react-types/datepicker': 3.13.0(react@19.1.0) - '@react-types/dialog': 3.5.20(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/form': 3.1.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/label': 3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/spinbutton': 3.6.17(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/datepicker': 3.15.0(react@19.1.1) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/calendar': 3.7.3(react@19.1.1) + '@react-types/datepicker': 3.13.0(react@19.1.1) + '@react-types/dialog': 3.5.20(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/dialog@3.5.28(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/dialog@3.5.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/overlays': 3.28.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/dialog': 3.5.20(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/overlays': 3.28.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/dialog': 3.5.20(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/disclosure@3.0.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/disclosure@3.0.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/ssr': 3.9.10(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/disclosure': 3.0.6(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) + '@react-aria/ssr': 3.9.10(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/disclosure': 3.0.6(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/dnd@3.11.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/dnd@3.11.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@internationalized/string': 3.2.7 - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@react-aria/live-announcer': 3.4.4 - '@react-aria/overlays': 3.28.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/dnd': 3.6.1(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/overlays': 3.28.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/dnd': 3.6.1(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/focus@3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/focus@3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 clsx: 2.1.1 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/form@3.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/form@3.1.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/grid@3.14.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/grid@3.14.3(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@react-aria/live-announcer': 3.4.4 - '@react-aria/selection': 3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/grid': 3.11.4(react@19.1.0) - '@react-stately/selection': 3.20.4(react@19.1.0) - '@react-types/checkbox': 3.10.0(react@19.1.0) - '@react-types/grid': 3.3.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/selection': 3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/grid': 3.11.4(react@19.1.1) + '@react-stately/selection': 3.20.4(react@19.1.1) + '@react-types/checkbox': 3.10.0(react@19.1.1) + '@react-types/grid': 3.3.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/gridlist@3.13.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/gridlist@3.13.3(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/grid': 3.14.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/list': 3.12.4(react@19.1.0) - '@react-stately/tree': 3.9.1(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/grid': 3.14.3(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/selection': 3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/list': 3.12.4(react@19.1.1) + '@react-stately/tree': 3.9.1(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/i18n@3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/i18n@3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@internationalized/date': 3.8.2 '@internationalized/message': 3.1.8 '@internationalized/number': 3.6.4 '@internationalized/string': 3.2.7 - '@react-aria/ssr': 3.9.10(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/ssr': 3.9.10(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/interactions@3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/interactions@3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/ssr': 3.9.10(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/ssr': 3.9.10(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@react-stately/flags': 3.1.2 - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/label@3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/label@3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/landmark@3.0.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/landmark@3.0.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - use-sync-external-store: 1.5.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + use-sync-external-store: 1.5.0(react@19.1.1) - '@react-aria/link@3.8.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/link@3.8.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/link': 3.6.3(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/link': 3.6.3(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/listbox@3.14.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/listbox@3.14.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/list': 3.12.4(react@19.1.0) - '@react-types/listbox': 3.7.2(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/label': 3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/selection': 3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/list': 3.12.4(react@19.1.1) + '@react-types/listbox': 3.7.2(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) '@react-aria/live-announcer@3.4.4': dependencies: '@swc/helpers': 0.5.17 - '@react-aria/menu@3.19.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/menu@3.19.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/overlays': 3.28.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/menu': 3.9.6(react@19.1.0) - '@react-stately/selection': 3.20.4(react@19.1.0) - '@react-stately/tree': 3.9.1(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/menu': 3.10.3(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/overlays': 3.28.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/selection': 3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/menu': 3.9.6(react@19.1.1) + '@react-stately/selection': 3.20.4(react@19.1.1) + '@react-stately/tree': 3.9.1(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/menu': 3.10.3(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/meter@3.4.25(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/meter@3.4.25(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/progress': 3.4.25(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/meter': 3.4.11(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/progress': 3.4.25(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/meter': 3.4.11(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/numberfield@3.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/numberfield@3.12.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/spinbutton': 3.6.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/textfield': 3.18.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/numberfield': 3.10.0(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/numberfield': 3.8.13(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/spinbutton': 3.6.17(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/textfield': 3.18.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/numberfield': 3.10.0(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/numberfield': 3.8.13(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/overlays@3.28.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/overlays@3.28.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/ssr': 3.9.10(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/visually-hidden': 3.8.26(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/overlays': 3.6.18(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/overlays': 3.9.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/ssr': 3.9.10(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/visually-hidden': 3.8.26(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/overlays': 3.6.18(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/overlays': 3.9.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/progress@3.4.25(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/progress@3.4.25(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/progress': 3.5.14(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/label': 3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/progress': 3.5.14(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/radio@3.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/radio@3.12.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/form': 3.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/radio': 3.11.0(react@19.1.0) - '@react-types/radio': 3.9.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/form': 3.1.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/label': 3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/radio': 3.11.0(react@19.1.1) + '@react-types/radio': 3.9.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/searchfield@3.8.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/searchfield@3.8.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/textfield': 3.18.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/searchfield': 3.5.14(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/searchfield': 3.6.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/textfield': 3.18.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/searchfield': 3.5.14(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/searchfield': 3.6.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/select@3.16.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/select@3.16.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/form': 3.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/listbox': 3.14.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/menu': 3.19.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/visually-hidden': 3.8.26(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/select': 3.7.0(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/select': 3.10.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/form': 3.1.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/label': 3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/listbox': 3.14.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/menu': 3.19.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/selection': 3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/visually-hidden': 3.8.26(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/select': 3.7.0(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/select': 3.10.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/selection@3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/selection@3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/selection': 3.20.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/selection': 3.20.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/separator@3.4.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/separator@3.4.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/slider@3.8.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/slider@3.8.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/slider': 3.7.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/slider': 3.8.0(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/label': 3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/slider': 3.7.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/slider': 3.8.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/spinbutton@3.6.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/spinbutton@3.6.17(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@react-aria/live-announcer': 3.4.4 - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/ssr@3.9.10(react@19.1.0)': + '@react-aria/ssr@3.9.10(react@19.1.1)': dependencies: '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-aria/switch@3.7.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/switch@3.7.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/toggle': 3.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/toggle': 3.9.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/switch': 3.5.13(react@19.1.0) + '@react-aria/toggle': 3.12.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/toggle': 3.9.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/switch': 3.5.13(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/table@3.17.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/table@3.17.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/grid': 3.14.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/grid': 3.14.3(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@react-aria/live-announcer': 3.4.4 - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/visually-hidden': 3.8.26(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/collections': 3.12.6(react@19.1.0) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/visually-hidden': 3.8.26(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/collections': 3.12.6(react@19.1.1) '@react-stately/flags': 3.1.2 - '@react-stately/table': 3.14.4(react@19.1.0) - '@react-types/checkbox': 3.10.0(react@19.1.0) - '@react-types/grid': 3.3.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/table': 3.13.2(react@19.1.0) + '@react-stately/table': 3.14.4(react@19.1.1) + '@react-types/checkbox': 3.10.0(react@19.1.1) + '@react-types/grid': 3.3.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/table': 3.13.2(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/tabs@3.10.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/tabs@3.10.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/tabs': 3.8.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/tabs': 3.3.17(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/selection': 3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/tabs': 3.8.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/tabs': 3.3.17(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/tag@3.7.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/tag@3.7.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/gridlist': 3.13.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/list': 3.12.4(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/gridlist': 3.13.3(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/label': 3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/selection': 3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/list': 3.12.4(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/textfield@3.18.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/textfield@3.18.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/form': 3.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/textfield': 3.12.4(react@19.1.0) + '@react-aria/form': 3.1.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/label': 3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/textfield': 3.12.4(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/toast@3.0.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/toast@3.0.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/landmark': 3.0.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/toast': 3.1.2(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/landmark': 3.0.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/toast': 3.1.2(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/toggle@3.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/toggle@3.12.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/toggle': 3.9.0(react@19.1.0) - '@react-types/checkbox': 3.10.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/toggle': 3.9.0(react@19.1.1) + '@react-types/checkbox': 3.10.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/toolbar@3.0.0-beta.16(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/toolbar@3.0.0-beta.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/toolbar@3.0.0-beta.19(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/toolbar@3.0.0-beta.19(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/tooltip@3.8.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/tooltip@3.8.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/tooltip': 3.5.6(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/tooltip': 3.4.19(react@19.1.0) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/tooltip': 3.5.6(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/tooltip': 3.4.19(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/tree@3.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/tree@3.1.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/gridlist': 3.13.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/tree': 3.9.1(react@19.1.0) - '@react-types/button': 3.13.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/gridlist': 3.13.3(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/selection': 3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/tree': 3.9.1(react@19.1.1) + '@react-types/button': 3.13.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/utils@3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/utils@3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/ssr': 3.9.10(react@19.1.0) + '@react-aria/ssr': 3.9.10(react@19.1.1) '@react-stately/flags': 3.1.2 - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 clsx: 2.1.1 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/virtualizer@4.1.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/virtualizer@4.1.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/virtualizer': 4.4.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/virtualizer': 4.4.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-aria/visually-hidden@3.8.26(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-aria/visually-hidden@3.8.26(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-spring/animated@9.7.5(react@19.1.0)': + '@react-spring/animated@9.7.5(react@19.1.1)': dependencies: - '@react-spring/shared': 9.7.5(react@19.1.0) + '@react-spring/shared': 9.7.5(react@19.1.1) '@react-spring/types': 9.7.5 - react: 19.1.0 + react: 19.1.1 - '@react-spring/core@9.7.5(react@19.1.0)': + '@react-spring/core@9.7.5(react@19.1.1)': dependencies: - '@react-spring/animated': 9.7.5(react@19.1.0) - '@react-spring/shared': 9.7.5(react@19.1.0) + '@react-spring/animated': 9.7.5(react@19.1.1) + '@react-spring/shared': 9.7.5(react@19.1.1) '@react-spring/types': 9.7.5 - react: 19.1.0 + react: 19.1.1 '@react-spring/rafz@9.7.5': {} - '@react-spring/shared@9.7.5(react@19.1.0)': + '@react-spring/shared@9.7.5(react@19.1.1)': dependencies: '@react-spring/rafz': 9.7.5 '@react-spring/types': 9.7.5 - react: 19.1.0 + react: 19.1.1 '@react-spring/types@9.7.5': {} - '@react-spring/web@9.7.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-spring/web@9.7.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-spring/animated': 9.7.5(react@19.1.0) - '@react-spring/core': 9.7.5(react@19.1.0) - '@react-spring/shared': 9.7.5(react@19.1.0) + '@react-spring/animated': 9.7.5(react@19.1.1) + '@react-spring/core': 9.7.5(react@19.1.1) + '@react-spring/shared': 9.7.5(react@19.1.1) '@react-spring/types': 9.7.5 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-stately/autocomplete@3.0.0-beta.1(react@19.1.0)': + '@react-stately/autocomplete@3.0.0-beta.1(react@19.1.1)': dependencies: - '@react-stately/utils': 3.10.8(react@19.1.0) + '@react-stately/utils': 3.10.8(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/calendar@3.8.3(react@19.1.0)': + '@react-stately/calendar@3.8.3(react@19.1.1)': dependencies: '@internationalized/date': 3.8.2 - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/calendar': 3.7.3(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/calendar': 3.7.3(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/checkbox@3.7.0(react@19.1.0)': + '@react-stately/checkbox@3.7.0(react@19.1.1)': dependencies: - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/checkbox': 3.10.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/checkbox': 3.10.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/collections@3.12.6(react@19.1.0)': + '@react-stately/collections@3.12.6(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/color@3.9.0(react@19.1.0)': + '@react-stately/color@3.9.0(react@19.1.1)': dependencies: '@internationalized/number': 3.6.4 '@internationalized/string': 3.2.7 - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/numberfield': 3.10.0(react@19.1.0) - '@react-stately/slider': 3.7.0(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/color': 3.1.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/numberfield': 3.10.0(react@19.1.1) + '@react-stately/slider': 3.7.0(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/color': 3.1.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/combobox@3.11.0(react@19.1.0)': + '@react-stately/combobox@3.11.0(react@19.1.1)': dependencies: - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/list': 3.12.4(react@19.1.0) - '@react-stately/overlays': 3.6.18(react@19.1.0) - '@react-stately/select': 3.7.0(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/combobox': 3.13.7(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/list': 3.12.4(react@19.1.1) + '@react-stately/overlays': 3.6.18(react@19.1.1) + '@react-stately/select': 3.7.0(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/combobox': 3.13.7(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/data@3.13.2(react@19.1.0)': + '@react-stately/data@3.13.2(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/datepicker@3.15.0(react@19.1.0)': + '@react-stately/datepicker@3.15.0(react@19.1.1)': dependencies: '@internationalized/date': 3.8.2 '@internationalized/string': 3.2.7 - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/overlays': 3.6.18(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/datepicker': 3.13.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/overlays': 3.6.18(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/datepicker': 3.13.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/disclosure@3.0.6(react@19.1.0)': + '@react-stately/disclosure@3.0.6(react@19.1.1)': dependencies: - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/dnd@3.6.1(react@19.1.0)': + '@react-stately/dnd@3.6.1(react@19.1.1)': dependencies: - '@react-stately/selection': 3.20.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/selection': 3.20.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 '@react-stately/flags@3.1.2': dependencies: '@swc/helpers': 0.5.17 - '@react-stately/form@3.2.0(react@19.1.0)': + '@react-stately/form@3.2.0(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/grid@3.11.4(react@19.1.0)': + '@react-stately/grid@3.11.4(react@19.1.1)': dependencies: - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/selection': 3.20.4(react@19.1.0) - '@react-types/grid': 3.3.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/selection': 3.20.4(react@19.1.1) + '@react-types/grid': 3.3.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/layout@4.4.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-stately/layout@4.4.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/table': 3.14.4(react@19.1.0) - '@react-stately/virtualizer': 4.4.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/grid': 3.3.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/table': 3.13.2(react@19.1.0) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/table': 3.14.4(react@19.1.1) + '@react-stately/virtualizer': 4.4.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/grid': 3.3.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/table': 3.13.2(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-stately/list@3.12.4(react@19.1.0)': + '@react-stately/list@3.12.4(react@19.1.1)': dependencies: - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/selection': 3.20.4(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/selection': 3.20.4(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/menu@3.9.6(react@19.1.0)': + '@react-stately/menu@3.9.6(react@19.1.1)': dependencies: - '@react-stately/overlays': 3.6.18(react@19.1.0) - '@react-types/menu': 3.10.3(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/overlays': 3.6.18(react@19.1.1) + '@react-types/menu': 3.10.3(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/numberfield@3.10.0(react@19.1.0)': + '@react-stately/numberfield@3.10.0(react@19.1.1)': dependencies: '@internationalized/number': 3.6.4 - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/numberfield': 3.8.13(react@19.1.0) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/numberfield': 3.8.13(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/overlays@3.6.18(react@19.1.0)': + '@react-stately/overlays@3.6.18(react@19.1.1)': dependencies: - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/overlays': 3.9.0(react@19.1.0) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/overlays': 3.9.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/radio@3.11.0(react@19.1.0)': + '@react-stately/radio@3.11.0(react@19.1.1)': dependencies: - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/radio': 3.9.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/radio': 3.9.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/searchfield@3.5.14(react@19.1.0)': + '@react-stately/searchfield@3.5.14(react@19.1.1)': dependencies: - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/searchfield': 3.6.4(react@19.1.0) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/searchfield': 3.6.4(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/select@3.7.0(react@19.1.0)': + '@react-stately/select@3.7.0(react@19.1.1)': dependencies: - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/list': 3.12.4(react@19.1.0) - '@react-stately/overlays': 3.6.18(react@19.1.0) - '@react-types/select': 3.10.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/list': 3.12.4(react@19.1.1) + '@react-stately/overlays': 3.6.18(react@19.1.1) + '@react-types/select': 3.10.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/selection@3.20.4(react@19.1.0)': + '@react-stately/selection@3.20.4(react@19.1.1)': dependencies: - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/slider@3.7.0(react@19.1.0)': + '@react-stately/slider@3.7.0(react@19.1.1)': dependencies: - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/slider': 3.8.0(react@19.1.0) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/slider': 3.8.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/table@3.14.4(react@19.1.0)': + '@react-stately/table@3.14.4(react@19.1.1)': dependencies: - '@react-stately/collections': 3.12.6(react@19.1.0) + '@react-stately/collections': 3.12.6(react@19.1.1) '@react-stately/flags': 3.1.2 - '@react-stately/grid': 3.11.4(react@19.1.0) - '@react-stately/selection': 3.20.4(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/grid': 3.3.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/table': 3.13.2(react@19.1.0) + '@react-stately/grid': 3.11.4(react@19.1.1) + '@react-stately/selection': 3.20.4(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/grid': 3.3.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/table': 3.13.2(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/tabs@3.8.4(react@19.1.0)': + '@react-stately/tabs@3.8.4(react@19.1.1)': dependencies: - '@react-stately/list': 3.12.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/tabs': 3.3.17(react@19.1.0) + '@react-stately/list': 3.12.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/tabs': 3.3.17(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/toast@3.1.2(react@19.1.0)': + '@react-stately/toast@3.1.2(react@19.1.1)': dependencies: '@swc/helpers': 0.5.17 - react: 19.1.0 - use-sync-external-store: 1.5.0(react@19.1.0) + react: 19.1.1 + use-sync-external-store: 1.5.0(react@19.1.1) - '@react-stately/toggle@3.9.0(react@19.1.0)': + '@react-stately/toggle@3.9.0(react@19.1.1)': dependencies: - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/checkbox': 3.10.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/checkbox': 3.10.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/tooltip@3.5.6(react@19.1.0)': + '@react-stately/tooltip@3.5.6(react@19.1.1)': dependencies: - '@react-stately/overlays': 3.6.18(react@19.1.0) - '@react-types/tooltip': 3.4.19(react@19.1.0) + '@react-stately/overlays': 3.6.18(react@19.1.1) + '@react-types/tooltip': 3.4.19(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/tree@3.9.1(react@19.1.0)': + '@react-stately/tree@3.9.1(react@19.1.1)': dependencies: - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/selection': 3.20.4(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/selection': 3.20.4(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/utils@3.10.8(react@19.1.0)': + '@react-stately/utils@3.10.8(react@19.1.1)': dependencies: '@swc/helpers': 0.5.17 - react: 19.1.0 + react: 19.1.1 - '@react-stately/virtualizer@4.4.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@react-stately/virtualizer@4.4.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) '@swc/helpers': 0.5.17 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - '@react-types/autocomplete@3.0.0-alpha.31(react@19.1.0)': + '@react-types/autocomplete@3.0.0-alpha.31(react@19.1.1)': dependencies: - '@react-types/combobox': 3.13.7(react@19.1.0) - '@react-types/searchfield': 3.6.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/combobox': 3.13.7(react@19.1.1) + '@react-types/searchfield': 3.6.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/breadcrumbs@3.7.15(react@19.1.0)': + '@react-types/breadcrumbs@3.7.15(react@19.1.1)': dependencies: - '@react-types/link': 3.6.3(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/link': 3.6.3(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/button@3.13.0(react@19.1.0)': + '@react-types/button@3.13.0(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/calendar@3.7.3(react@19.1.0)': + '@react-types/calendar@3.7.3(react@19.1.1)': dependencies: '@internationalized/date': 3.8.2 - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/checkbox@3.10.0(react@19.1.0)': + '@react-types/checkbox@3.10.0(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/color@3.1.0(react@19.1.0)': + '@react-types/color@3.1.0(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/slider': 3.8.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/slider': 3.8.0(react@19.1.1) + react: 19.1.1 - '@react-types/combobox@3.13.7(react@19.1.0)': + '@react-types/combobox@3.13.7(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/datepicker@3.13.0(react@19.1.0)': + '@react-types/datepicker@3.13.0(react@19.1.1)': dependencies: '@internationalized/date': 3.8.2 - '@react-types/calendar': 3.7.3(react@19.1.0) - '@react-types/overlays': 3.9.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/calendar': 3.7.3(react@19.1.1) + '@react-types/overlays': 3.9.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/dialog@3.5.20(react@19.1.0)': + '@react-types/dialog@3.5.20(react@19.1.1)': dependencies: - '@react-types/overlays': 3.9.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/overlays': 3.9.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/form@3.7.14(react@19.1.0)': + '@react-types/form@3.7.14(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/grid@3.3.4(react@19.1.0)': + '@react-types/grid@3.3.4(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/link@3.6.3(react@19.1.0)': + '@react-types/link@3.6.3(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/listbox@3.7.2(react@19.1.0)': + '@react-types/listbox@3.7.2(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/menu@3.10.3(react@19.1.0)': + '@react-types/menu@3.10.3(react@19.1.1)': dependencies: - '@react-types/overlays': 3.9.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/overlays': 3.9.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/meter@3.4.11(react@19.1.0)': + '@react-types/meter@3.4.11(react@19.1.1)': dependencies: - '@react-types/progress': 3.5.14(react@19.1.0) - react: 19.1.0 + '@react-types/progress': 3.5.14(react@19.1.1) + react: 19.1.1 - '@react-types/numberfield@3.8.13(react@19.1.0)': + '@react-types/numberfield@3.8.13(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/overlays@3.9.0(react@19.1.0)': + '@react-types/overlays@3.9.0(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/progress@3.5.14(react@19.1.0)': + '@react-types/progress@3.5.14(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/radio@3.9.0(react@19.1.0)': + '@react-types/radio@3.9.0(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/searchfield@3.6.4(react@19.1.0)': + '@react-types/searchfield@3.6.4(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/textfield': 3.12.4(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/textfield': 3.12.4(react@19.1.1) + react: 19.1.1 - '@react-types/select@3.10.0(react@19.1.0)': + '@react-types/select@3.10.0(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/shared@3.31.0(react@19.1.0)': + '@react-types/shared@3.31.0(react@19.1.1)': dependencies: - react: 19.1.0 + react: 19.1.1 - '@react-types/slider@3.8.0(react@19.1.0)': + '@react-types/slider@3.8.0(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/switch@3.5.13(react@19.1.0)': + '@react-types/switch@3.5.13(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/table@3.13.2(react@19.1.0)': + '@react-types/table@3.13.2(react@19.1.1)': dependencies: - '@react-types/grid': 3.3.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/grid': 3.3.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/tabs@3.3.17(react@19.1.0)': + '@react-types/tabs@3.3.17(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/textfield@3.12.4(react@19.1.0)': + '@react-types/textfield@3.12.4(react@19.1.1)': dependencies: - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - '@react-types/tooltip@3.4.19(react@19.1.0)': + '@react-types/tooltip@3.4.19(react@19.1.1)': dependencies: - '@react-types/overlays': 3.9.0(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-types/overlays': 3.9.0(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 '@redis/bloom@1.2.0(@redis/client@1.6.1)': dependencies: @@ -9365,6 +9485,8 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 + '@standard-schema/spec@1.0.0': {} + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 @@ -9476,10 +9598,10 @@ snapshots: '@tanstack/query-core@5.83.0': {} - '@tanstack/react-query@5.83.0(react@19.1.0)': + '@tanstack/react-query@5.83.0(react@19.1.1)': dependencies: '@tanstack/query-core': 5.83.0 - react: 19.1.0 + react: 19.1.1 '@trysound/sax@0.2.0': {} @@ -9538,9 +9660,9 @@ snapshots: dependencies: '@types/node': 22.16.5 - '@types/hoist-non-react-statics@3.3.7(@types/react@19.1.8)': + '@types/hoist-non-react-statics@3.3.7(@types/react@19.1.9)': dependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.9 hoist-non-react-statics: 3.3.2 '@types/istanbul-lib-coverage@2.0.6': {} @@ -9578,15 +9700,15 @@ snapshots: '@types/normalize-package-data@2.4.4': {} - '@types/react-dom@19.1.6(@types/react@19.1.8)': + '@types/react-dom@19.1.7(@types/react@19.1.9)': dependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.9 '@types/react-window@1.8.8': dependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.9 - '@types/react@19.1.8': + '@types/react@19.1.9': dependencies: csstype: 3.1.3 @@ -9751,24 +9873,24 @@ snapshots: '@typescript-eslint/types': 8.38.0 eslint-visitor-keys: 4.2.1 - '@umami/react-zen@0.157.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))': + '@umami/react-zen@0.157.0(@babel/core@7.27.1)(@types/react@19.1.9)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.1))': dependencies: '@fontsource/jetbrains-mono': 5.2.6 '@internationalized/date': 3.8.2 - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-spring/web': 9.7.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-spring/web': 9.7.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1) classnames: 2.5.1 glob: 10.4.5 highlight.js: 11.11.1 - lucide-react: 0.511.0(react@19.1.0) - next: 15.4.4(@babel/core@7.27.1)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react: 19.1.0 - react-aria-components: 1.9.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react-dom: 19.1.0(react@19.1.0) - react-hook-form: 7.62.0(react@19.1.0) - react-icons: 5.5.0(react@19.1.0) + lucide-react: 0.511.0(react@19.1.1) + next: 15.4.6(@babel/core@7.27.1)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + react: 19.1.1 + react-aria-components: 1.9.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + react-dom: 19.1.1(react@19.1.1) + react-hook-form: 7.62.0(react@19.1.1) + react-icons: 5.5.0(react@19.1.1) thenby: 1.3.4 - zustand: 5.0.6(@types/react@19.1.8)(immer@9.0.21)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)) + zustand: 5.0.6(@types/react@19.1.9)(immer@9.0.21)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)) transitivePeerDependencies: - '@babel/core' - '@opentelemetry/api' @@ -10217,6 +10339,21 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + c12@3.1.0: + dependencies: + chokidar: 4.0.3 + confbox: 0.2.2 + defu: 6.1.4 + dotenv: 16.6.1 + exsolve: 1.0.7 + giget: 2.0.0 + jiti: 2.5.1 + ohash: 2.0.11 + pathe: 2.0.3 + perfect-debounce: 1.0.0 + pkg-types: 2.2.0 + rc9: 2.1.2 + cachedir@2.4.0: {} call-bind-apply-helpers@1.0.2: @@ -10258,13 +10395,13 @@ snapshots: caniuse-api@3.0.0: dependencies: browserslist: 4.24.5 - caniuse-lite: 1.0.30001727 + caniuse-lite: 1.0.30001731 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 caniuse-lite@1.0.30001718: {} - caniuse-lite@1.0.30001727: {} + caniuse-lite@1.0.30001731: {} caseless@0.12.0: {} @@ -10298,12 +10435,20 @@ snapshots: check-more-types@2.24.0: {} + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + chownr@2.0.0: {} ci-info@3.9.0: {} ci-info@4.2.0: {} + citty@0.1.6: + dependencies: + consola: 3.4.2 + cjs-module-lexer@1.4.3: {} classnames@2.5.1: {} @@ -10406,6 +10551,10 @@ snapshots: dependencies: source-map: 0.6.1 + confbox@0.2.2: {} + + consola@3.4.2: {} + convert-source-map@2.0.0: {} core-util-is@1.0.2: {} @@ -10745,6 +10894,8 @@ snapshots: deep-is@0.1.4: {} + deepmerge-ts@7.1.5: {} + deepmerge@4.3.1: {} define-data-property@1.1.4: @@ -10759,6 +10910,8 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 + defu@6.1.4: {} + del@6.1.1: dependencies: globby: 11.1.0 @@ -10772,6 +10925,8 @@ snapshots: delayed-stream@1.0.0: {} + destr@2.0.5: {} + detect-browser@5.3.0: {} detect-indent@6.1.0: {} @@ -10838,6 +10993,8 @@ snapshots: dotenv@10.0.0: {} + dotenv@16.6.1: {} + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -10855,6 +11012,11 @@ snapshots: dependencies: safe-buffer: 5.2.1 + effect@3.16.12: + dependencies: + '@standard-schema/spec': 1.0.0 + fast-check: 3.23.2 + ejs@3.1.10: dependencies: jake: 10.9.2 @@ -11388,6 +11550,8 @@ snapshots: jest-message-util: 29.7.0 jest-util: 29.7.0 + exsolve@1.0.7: {} + extend@3.0.2: {} extract-react-intl-messages@4.1.1(ts-jest@29.4.0(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.8)(jest-util@29.7.0)(jest@29.7.0(@types/node@22.16.5)(ts-node@10.9.2(@types/node@22.16.5)(typescript@5.8.3)))(typescript@5.8.3)): @@ -11423,6 +11587,10 @@ snapshots: extsprintf@1.3.0: {} + fast-check@3.23.2: + dependencies: + pure-rand: 6.1.0 + fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -11484,6 +11652,8 @@ snapshots: dependencies: to-regex-range: 5.0.1 + find-up-simple@1.0.1: {} + find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -11623,6 +11793,15 @@ snapshots: dependencies: assert-plus: 1.0.0 + giget@2.0.0: + dependencies: + citty: 0.1.6 + consola: 3.4.2 + defu: 6.1.4 + node-fetch-native: 1.6.7 + nypm: 0.6.1 + pathe: 2.0.3 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -11760,6 +11939,10 @@ snapshots: dependencies: lru-cache: 6.0.0 + hosted-git-info@7.0.2: + dependencies: + lru-cache: 10.4.3 + html-escaper@2.0.2: {} html-tags@3.3.1: {} @@ -11820,6 +12003,8 @@ snapshots: indent-string@5.0.0: {} + index-to-position@1.1.0: {} + inflight@1.0.6: dependencies: once: 1.4.0 @@ -12408,7 +12593,7 @@ snapshots: - supports-color - ts-node - jiti@2.4.2: {} + jiti@2.5.1: {} joycon@3.1.1: {} @@ -12691,13 +12876,13 @@ snapshots: dependencies: yallist: 4.0.0 - lucide-react@0.511.0(react@19.1.0): + lucide-react@0.511.0(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 - lucide-react@0.526.0(react@19.1.0): + lucide-react@0.526.0(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 magic-string@0.30.17: dependencies: @@ -12856,24 +13041,24 @@ snapshots: natural-compare@1.4.0: {} - next@15.4.4(@babel/core@7.27.1)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next@15.4.6(@babel/core@7.27.1)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: - '@next/env': 15.4.4 + '@next/env': 15.4.6 '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001727 + caniuse-lite: 1.0.30001731 postcss: 8.4.31 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - styled-jsx: 5.1.6(@babel/core@7.27.1)(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + styled-jsx: 5.1.6(@babel/core@7.27.1)(react@19.1.1) optionalDependencies: - '@next/swc-darwin-arm64': 15.4.4 - '@next/swc-darwin-x64': 15.4.4 - '@next/swc-linux-arm64-gnu': 15.4.4 - '@next/swc-linux-arm64-musl': 15.4.4 - '@next/swc-linux-x64-gnu': 15.4.4 - '@next/swc-linux-x64-musl': 15.4.4 - '@next/swc-win32-arm64-msvc': 15.4.4 - '@next/swc-win32-x64-msvc': 15.4.4 + '@next/swc-darwin-arm64': 15.4.6 + '@next/swc-darwin-x64': 15.4.6 + '@next/swc-linux-arm64-gnu': 15.4.6 + '@next/swc-linux-arm64-musl': 15.4.6 + '@next/swc-linux-x64-gnu': 15.4.6 + '@next/swc-linux-x64-musl': 15.4.6 + '@next/swc-win32-arm64-msvc': 15.4.6 + '@next/swc-win32-x64-msvc': 15.4.6 babel-plugin-react-compiler: 19.1.0-rc.2 sharp: 0.34.3 transitivePeerDependencies: @@ -12889,6 +13074,8 @@ snapshots: node-domexception@1.0.0: {} + node-fetch-native@1.6.7: {} + node-fetch@3.3.2: dependencies: data-uri-to-buffer: 4.0.1 @@ -12913,6 +13100,12 @@ snapshots: semver: 7.7.2 validate-npm-package-license: 3.0.4 + normalize-package-data@6.0.2: + dependencies: + hosted-git-info: 7.0.2 + semver: 7.7.2 + validate-npm-package-license: 3.0.4 + normalize-path@3.0.0: {} normalize-range@0.1.2: {} @@ -12943,6 +13136,14 @@ snapshots: dependencies: boolbase: 1.0.0 + nypm@0.6.1: + dependencies: + citty: 0.1.6 + consola: 3.4.2 + pathe: 2.0.3 + pkg-types: 2.2.0 + tinyexec: 1.0.1 + object-assign@4.1.1: {} object-inspect@1.13.4: {} @@ -12985,6 +13186,8 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + ohash@2.0.11: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -13069,6 +13272,12 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parse-json@8.3.0: + dependencies: + '@babel/code-frame': 7.27.1 + index-to-position: 1.1.0 + type-fest: 4.41.0 + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -13092,8 +13301,12 @@ snapshots: path-type@4.0.0: {} + pathe@2.0.3: {} + pend@1.2.0: {} + perfect-debounce@1.0.0: {} + performance-now@2.1.0: {} pg-cloudflare@1.2.7: @@ -13153,6 +13366,12 @@ snapshots: dependencies: find-up: 4.1.0 + pkg-types@2.2.0: + dependencies: + confbox: 0.2.2 + exsolve: 1.0.7 + pathe: 2.0.3 + possible-typed-array-names@1.1.0: {} postcss-attribute-case-insensitive@5.0.2(postcss@8.5.6): @@ -13606,12 +13825,14 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 - prisma@6.12.0(typescript@5.8.3): + prisma@6.13.0(typescript@5.8.3): dependencies: - '@prisma/config': 6.12.0 - '@prisma/engines': 6.12.0 + '@prisma/config': 6.13.0 + '@prisma/engines': 6.13.0 optionalDependencies: typescript: 5.8.3 + transitivePeerDependencies: + - magicast process-nextick-args@2.0.1: {} @@ -13659,128 +13880,133 @@ snapshots: dependencies: safe-buffer: 5.2.1 - react-aria-components@1.9.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + rc9@2.1.2: + dependencies: + defu: 6.1.4 + destr: 2.0.5 + + react-aria-components@1.9.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: '@internationalized/date': 3.8.2 '@internationalized/string': 3.2.7 - '@react-aria/autocomplete': 3.0.0-beta.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/collections': 3.0.0-rc.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/dnd': 3.11.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/autocomplete': 3.0.0-beta.3(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/collections': 3.0.0-rc.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/dnd': 3.11.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@react-aria/live-announcer': 3.4.4 - '@react-aria/overlays': 3.28.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/ssr': 3.9.10(react@19.1.0) - '@react-aria/toolbar': 3.0.0-beta.16(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/virtualizer': 4.1.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/autocomplete': 3.0.0-beta.1(react@19.1.0) - '@react-stately/layout': 4.4.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-stately/selection': 3.20.4(react@19.1.0) - '@react-stately/table': 3.14.4(react@19.1.0) - '@react-stately/utils': 3.10.8(react@19.1.0) - '@react-stately/virtualizer': 4.4.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/form': 3.7.14(react@19.1.0) - '@react-types/grid': 3.3.4(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - '@react-types/table': 3.13.2(react@19.1.0) + '@react-aria/overlays': 3.28.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/ssr': 3.9.10(react@19.1.1) + '@react-aria/toolbar': 3.0.0-beta.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/virtualizer': 4.1.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/autocomplete': 3.0.0-beta.1(react@19.1.1) + '@react-stately/layout': 4.4.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-stately/selection': 3.20.4(react@19.1.1) + '@react-stately/table': 3.14.4(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.1.1) + '@react-stately/virtualizer': 4.4.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/form': 3.7.14(react@19.1.1) + '@react-types/grid': 3.3.4(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + '@react-types/table': 3.13.2(react@19.1.1) '@swc/helpers': 0.5.17 client-only: 0.0.1 - react: 19.1.0 - react-aria: 3.42.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react-dom: 19.1.0(react@19.1.0) - react-stately: 3.40.0(react@19.1.0) - use-sync-external-store: 1.5.0(react@19.1.0) + react: 19.1.1 + react-aria: 3.42.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + react-dom: 19.1.1(react@19.1.1) + react-stately: 3.40.0(react@19.1.1) + use-sync-external-store: 1.5.0(react@19.1.1) - react-aria@3.42.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + react-aria@3.42.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: '@internationalized/string': 3.2.7 - '@react-aria/breadcrumbs': 3.5.27(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/button': 3.14.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/calendar': 3.9.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/checkbox': 3.16.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/color': 3.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/combobox': 3.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/datepicker': 3.15.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/dialog': 3.5.28(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/disclosure': 3.0.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/dnd': 3.11.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/focus': 3.21.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/gridlist': 3.13.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/interactions': 3.25.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.20(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/landmark': 3.0.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/link': 3.8.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/listbox': 3.14.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/menu': 3.19.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/meter': 3.4.25(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/numberfield': 3.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/overlays': 3.28.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/progress': 3.4.25(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/radio': 3.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/searchfield': 3.8.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/select': 3.16.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.25.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/separator': 3.4.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/slider': 3.8.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/ssr': 3.9.10(react@19.1.0) - '@react-aria/switch': 3.7.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/table': 3.17.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/tabs': 3.10.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/tag': 3.7.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/textfield': 3.18.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/toast': 3.0.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/tooltip': 3.8.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/tree': 3.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/utils': 3.30.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/visually-hidden': 3.8.26(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@react-aria/breadcrumbs': 3.5.27(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/button': 3.14.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/calendar': 3.9.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/checkbox': 3.16.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/color': 3.1.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/combobox': 3.13.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/datepicker': 3.15.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/dialog': 3.5.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/disclosure': 3.0.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/dnd': 3.11.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/focus': 3.21.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/gridlist': 3.13.3(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/i18n': 3.12.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/interactions': 3.25.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/label': 3.7.20(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/landmark': 3.0.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/link': 3.8.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/listbox': 3.14.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/menu': 3.19.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/meter': 3.4.25(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/numberfield': 3.12.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/overlays': 3.28.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/progress': 3.4.25(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/radio': 3.12.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/searchfield': 3.8.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/select': 3.16.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/selection': 3.25.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/separator': 3.4.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/slider': 3.8.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/ssr': 3.9.10(react@19.1.1) + '@react-aria/switch': 3.7.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/table': 3.17.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/tabs': 3.10.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/tag': 3.7.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/textfield': 3.18.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/toast': 3.0.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/tooltip': 3.8.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/tree': 3.1.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/utils': 3.30.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/visually-hidden': 3.8.26(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - react-basics@0.126.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + react-basics@0.126.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: - '@react-spring/web': 9.7.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-spring/web': 9.7.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1) classnames: 2.5.1 date-fns: 2.30.0 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - react-hook-form: 7.56.4(react@19.1.0) - react-window: 1.8.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + react-hook-form: 7.56.4(react@19.1.1) + react-window: 1.8.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - react-dom@19.1.0(react@19.1.0): + react-dom@19.1.1(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 scheduler: 0.26.0 - react-error-boundary@4.1.2(react@19.1.0): + react-error-boundary@4.1.2(react@19.1.1): dependencies: '@babel/runtime': 7.27.1 - react: 19.1.0 + react: 19.1.1 - react-hook-form@7.56.4(react@19.1.0): + react-hook-form@7.56.4(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 - react-hook-form@7.62.0(react@19.1.0): + react-hook-form@7.62.0(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 - react-icons@5.5.0(react@19.1.0): + react-icons@5.5.0(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 - react-intl@7.1.11(react@19.1.0)(typescript@5.8.3): + react-intl@7.1.11(react@19.1.1)(typescript@5.8.3): dependencies: '@formatjs/ecma402-abstract': 2.3.4 '@formatjs/icu-messageformat-parser': 2.11.2 '@formatjs/intl': 3.1.6(typescript@5.8.3) - '@types/hoist-non-react-statics': 3.3.7(@types/react@19.1.8) - '@types/react': 19.1.8 + '@types/hoist-non-react-statics': 3.3.7(@types/react@19.1.9) + '@types/react': 19.1.9 hoist-non-react-statics: 3.3.2 intl-messageformat: 10.7.16 - react: 19.1.0 + react: 19.1.1 tslib: 2.8.1 optionalDependencies: typescript: 5.8.3 @@ -13789,69 +14015,69 @@ snapshots: react-is@18.3.1: {} - react-redux@9.2.0(@types/react@19.1.8)(react@19.1.0)(redux@5.0.1): + react-redux@9.2.0(@types/react@19.1.9)(react@19.1.1)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 - react: 19.1.0 - use-sync-external-store: 1.5.0(react@19.1.0) + react: 19.1.1 + use-sync-external-store: 1.5.0(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.9 redux: 5.0.1 - react-simple-maps@2.3.0(prop-types@15.8.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + react-simple-maps@2.3.0(prop-types@15.8.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: d3-geo: 2.0.2 d3-selection: 2.0.0 d3-zoom: 2.0.0 prop-types: 15.8.1 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) topojson-client: 3.1.0 - react-stately@3.40.0(react@19.1.0): + react-stately@3.40.0(react@19.1.1): dependencies: - '@react-stately/calendar': 3.8.3(react@19.1.0) - '@react-stately/checkbox': 3.7.0(react@19.1.0) - '@react-stately/collections': 3.12.6(react@19.1.0) - '@react-stately/color': 3.9.0(react@19.1.0) - '@react-stately/combobox': 3.11.0(react@19.1.0) - '@react-stately/data': 3.13.2(react@19.1.0) - '@react-stately/datepicker': 3.15.0(react@19.1.0) - '@react-stately/disclosure': 3.0.6(react@19.1.0) - '@react-stately/dnd': 3.6.1(react@19.1.0) - '@react-stately/form': 3.2.0(react@19.1.0) - '@react-stately/list': 3.12.4(react@19.1.0) - '@react-stately/menu': 3.9.6(react@19.1.0) - '@react-stately/numberfield': 3.10.0(react@19.1.0) - '@react-stately/overlays': 3.6.18(react@19.1.0) - '@react-stately/radio': 3.11.0(react@19.1.0) - '@react-stately/searchfield': 3.5.14(react@19.1.0) - '@react-stately/select': 3.7.0(react@19.1.0) - '@react-stately/selection': 3.20.4(react@19.1.0) - '@react-stately/slider': 3.7.0(react@19.1.0) - '@react-stately/table': 3.14.4(react@19.1.0) - '@react-stately/tabs': 3.8.4(react@19.1.0) - '@react-stately/toast': 3.1.2(react@19.1.0) - '@react-stately/toggle': 3.9.0(react@19.1.0) - '@react-stately/tooltip': 3.5.6(react@19.1.0) - '@react-stately/tree': 3.9.1(react@19.1.0) - '@react-types/shared': 3.31.0(react@19.1.0) - react: 19.1.0 + '@react-stately/calendar': 3.8.3(react@19.1.1) + '@react-stately/checkbox': 3.7.0(react@19.1.1) + '@react-stately/collections': 3.12.6(react@19.1.1) + '@react-stately/color': 3.9.0(react@19.1.1) + '@react-stately/combobox': 3.11.0(react@19.1.1) + '@react-stately/data': 3.13.2(react@19.1.1) + '@react-stately/datepicker': 3.15.0(react@19.1.1) + '@react-stately/disclosure': 3.0.6(react@19.1.1) + '@react-stately/dnd': 3.6.1(react@19.1.1) + '@react-stately/form': 3.2.0(react@19.1.1) + '@react-stately/list': 3.12.4(react@19.1.1) + '@react-stately/menu': 3.9.6(react@19.1.1) + '@react-stately/numberfield': 3.10.0(react@19.1.1) + '@react-stately/overlays': 3.6.18(react@19.1.1) + '@react-stately/radio': 3.11.0(react@19.1.1) + '@react-stately/searchfield': 3.5.14(react@19.1.1) + '@react-stately/select': 3.7.0(react@19.1.1) + '@react-stately/selection': 3.20.4(react@19.1.1) + '@react-stately/slider': 3.7.0(react@19.1.1) + '@react-stately/table': 3.14.4(react@19.1.1) + '@react-stately/tabs': 3.8.4(react@19.1.1) + '@react-stately/toast': 3.1.2(react@19.1.1) + '@react-stately/toggle': 3.9.0(react@19.1.1) + '@react-stately/tooltip': 3.5.6(react@19.1.1) + '@react-stately/tree': 3.9.1(react@19.1.1) + '@react-types/shared': 3.31.0(react@19.1.1) + react: 19.1.1 - react-use-measure@2.1.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + react-use-measure@2.1.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 optionalDependencies: - react-dom: 19.1.0(react@19.1.0) + react-dom: 19.1.1(react@19.1.1) - react-window@1.8.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + react-window@1.8.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: '@babel/runtime': 7.27.1 memoize-one: 5.2.1 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - react@19.1.0: {} + react@19.1.1: {} read-babelrc-up@1.1.0: dependencies: @@ -13862,6 +14088,12 @@ snapshots: dependencies: pify: 2.3.0 + read-package-up@11.0.0: + dependencies: + find-up-simple: 1.0.1 + read-pkg: 9.0.1 + type-fest: 4.41.0 + read-pkg-up@7.0.1: dependencies: find-up: 4.1.0 @@ -13894,6 +14126,14 @@ snapshots: parse-json: 5.2.0 type-fest: 1.4.0 + read-pkg@9.0.1: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 6.0.2 + parse-json: 8.3.0 + type-fest: 4.41.0 + unicorn-magic: 0.1.0 + readable-stream@2.3.8: dependencies: core-util-is: 1.0.2 @@ -13904,6 +14144,8 @@ snapshots: string_decoder: 1.1.1 util-deprecate: 1.0.2 + readdirp@4.1.2: {} + redent@3.0.0: dependencies: indent-string: 4.0.0 @@ -14424,10 +14666,10 @@ snapshots: style-search@0.1.0: {} - styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.1.0): + styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.1.1): dependencies: client-only: 0.0.1 - react: 19.1.0 + react: 19.1.1 optionalDependencies: '@babel/core': 7.27.1 @@ -14599,6 +14841,8 @@ snapshots: tiny-lru@11.3.3: {} + tinyexec@1.0.1: {} + tinyglobby@0.2.13: dependencies: fdir: 6.4.4(picomatch@4.0.2) @@ -14767,6 +15011,8 @@ snapshots: undici-types@6.21.0: {} + unicorn-magic@0.1.0: {} + universalify@0.1.2: {} universalify@2.0.1: {} @@ -14805,13 +15051,13 @@ snapshots: dependencies: punycode: 2.3.1 - use-memo-one@1.1.3(react@19.1.0): + use-memo-one@1.1.3(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 - use-sync-external-store@1.5.0(react@19.1.0): + use-sync-external-store@1.5.0(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 util-deprecate@1.0.2: {} @@ -14995,9 +15241,9 @@ snapshots: zod@3.25.76: {} - zustand@5.0.6(@types/react@19.1.8)(immer@9.0.21)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)): + zustand@5.0.6(@types/react@19.1.9)(immer@9.0.21)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)): optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.9 immer: 9.0.21 - react: 19.1.0 - use-sync-external-store: 1.5.0(react@19.1.0) + react: 19.1.1 + use-sync-external-store: 1.5.0(react@19.1.1) From 4e25c071604a3d7fb9fecc32e4e2d3dd1fe0275f Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 7 Aug 2025 22:10:02 -0700 Subject: [PATCH 149/399] Implemented expanded view in dialog. --- .../[websiteId]/WebsiteCompareTables.tsx | 51 ++++++----- .../[websiteId]/WebsiteDetailsPage.tsx | 26 +++++- .../[websiteId]/WebsiteExpandedView.tsx | 91 +++++++++---------- .../websites/[websiteId]/WebsiteTableView.tsx | 14 +-- .../[websiteId]/segments/SegmentEditForm.tsx | 2 +- src/components/common/SideMenu.tsx | 13 ++- src/components/hooks/useNavigation.ts | 8 +- src/components/metrics/MetricsTable.tsx | 33 ++++--- .../metrics/QueryParametersTable.tsx | 2 +- 9 files changed, 136 insertions(+), 104 deletions(-) diff --git a/src/app/(main)/websites/[websiteId]/WebsiteCompareTables.tsx b/src/app/(main)/websites/[websiteId]/WebsiteCompareTables.tsx index f173717c..90386a3a 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteCompareTables.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteCompareTables.tsx @@ -1,6 +1,5 @@ -import { Grid, Heading, Column, Row } from '@umami/react-zen'; +import { Grid, Heading, Column, Row, NavMenu, NavMenuItem, Text } from '@umami/react-zen'; import { useDateRange, useMessages, useNavigation } from '@/components/hooks'; -import { SideMenu } from '@/components/common/SideMenu'; import { BrowsersTable } from '@/components/metrics/BrowsersTable'; import { ChangeLabel } from '@/components/metrics/ChangeLabel'; import { CitiesTable } from '@/components/metrics/CitiesTable'; @@ -40,7 +39,7 @@ const views = { }; export function WebsiteCompareTables({ websiteId }: { websiteId: string }) { - const [data, setData] = useState([]); + const [data] = useState([]); const { dateRange, dateCompare } = useDateRange(websiteId); const { formatMessage, labels } = useMessages(); const { @@ -53,72 +52,72 @@ export function WebsiteCompareTables({ websiteId }: { websiteId: string }) { { id: 'path', label: formatMessage(labels.pages), - url: updateParams({ view: 'path' }), + path: updateParams({ view: 'path' }), }, { id: 'referrer', label: formatMessage(labels.referrers), - url: updateParams({ view: 'referrer' }), + path: updateParams({ view: 'referrer' }), }, { id: 'browser', label: formatMessage(labels.browsers), - url: updateParams({ view: 'browser' }), + path: updateParams({ view: 'browser' }), }, { id: 'os', label: formatMessage(labels.os), - url: updateParams({ view: 'os' }), + path: updateParams({ view: 'os' }), }, { id: 'device', label: formatMessage(labels.devices), - url: updateParams({ view: 'device' }), + path: updateParams({ view: 'device' }), }, { id: 'country', label: formatMessage(labels.countries), - url: updateParams({ view: 'country' }), + path: updateParams({ view: 'country' }), }, { id: 'region', label: formatMessage(labels.regions), - url: updateParams({ view: 'region' }), + path: updateParams({ view: 'region' }), }, { id: 'city', label: formatMessage(labels.cities), - url: updateParams({ view: 'city' }), + path: updateParams({ view: 'city' }), }, { id: 'language', label: formatMessage(labels.languages), - url: updateParams({ view: 'language' }), + path: updateParams({ view: 'language' }), }, { id: 'screen', label: formatMessage(labels.screens), - url: updateParams({ view: 'screen' }), + path: updateParams({ view: 'screen' }), }, { id: 'event', label: formatMessage(labels.events), - url: updateParams({ view: 'event' }), + path: updateParams({ view: 'event' }), }, { id: 'query', label: formatMessage(labels.queryParameters), - url: updateParams({ view: 'query' }), + path: updateParams({ view: 'query' }), }, { id: 'hostname', label: formatMessage(labels.hostname), - url: updateParams({ view: 'hostname' }), + path: updateParams({ view: 'hostname' }), }, { id: 'tag', label: formatMessage(labels.tags), - url: updateParams({ view: 'tag' }), + path: updateParams({ view: 'tag' }), }, ]; @@ -150,19 +149,21 @@ export function WebsiteCompareTables({ websiteId }: { websiteId: string }) { return ( - + + {items.map(({ id, label }) => { + return ( + + {label} + + ); + })} + {formatMessage(labels.previous)} - + diff --git a/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx b/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx index bdf7ef74..99517bb5 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx @@ -1,18 +1,29 @@ 'use client'; -import { Column } from '@umami/react-zen'; +import { Column, Modal, Dialog } from '@umami/react-zen'; import { useNavigation } from '@/components/hooks'; import { Panel } from '@/components/common/Panel'; import { WebsiteChart } from './WebsiteChart'; import { WebsiteExpandedView } from './WebsiteExpandedView'; import { WebsiteMetricsBar } from './WebsiteMetricsBar'; import { WebsiteTableView } from './WebsiteTableView'; -import { WebsiteCompareTables } from './WebsiteCompareTables'; import { WebsiteControls } from './WebsiteControls'; export function WebsiteDetailsPage({ websiteId }: { websiteId: string }) { const { + router, query: { view, compare }, + updateParams, } = useNavigation(); + const handleClose = (close: () => void) => { + router.push(updateParams({ view: undefined })); + close(); + }; + + const handleOpenChange = (isOpen: boolean) => { + if (!isOpen) { + router.push(updateParams({ view: undefined })); + } + }; return ( @@ -21,9 +32,14 @@ export function WebsiteDetailsPage({ websiteId }: { websiteId: string }) { - {!view && !compare && } - {view && !compare && } - {compare && } + + + + {({ close }) => { + return handleClose(close)} />; + }} + + ); } diff --git a/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx b/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx index e6788ae9..dabb2f49 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx @@ -1,7 +1,5 @@ -import { Icon, Text, Grid, Column } from '@umami/react-zen'; -import { LinkButton } from '@/components/common/LinkButton'; +import { Grid, Column, NavMenu, NavMenuItem } from '@umami/react-zen'; import { useMessages, useNavigation } from '@/components/hooks'; -import { SideMenu } from '@/components/common/SideMenu'; import { BrowsersTable } from '@/components/metrics/BrowsersTable'; import { CitiesTable } from '@/components/metrics/CitiesTable'; import { CountriesTable } from '@/components/metrics/CountriesTable'; @@ -17,8 +15,7 @@ import { RegionsTable } from '@/components/metrics/RegionsTable'; import { ScreenTable } from '@/components/metrics/ScreenTable'; import { TagsTable } from '@/components/metrics/TagsTable'; import { ChannelsTable } from '@/components/metrics/ChannelsTable'; -import { Panel } from '@/components/common/Panel'; -import { Arrow } from '@/components/icons'; +import Link from 'next/link'; const views = { path: PagesTable, @@ -44,10 +41,10 @@ const views = { export function WebsiteExpandedView({ websiteId, - domainName, + onClose, }: { websiteId: string; - domainName?: string; + onClose?: () => void; }) { const { formatMessage, labels } = useMessages(); const { @@ -59,107 +56,107 @@ export function WebsiteExpandedView({ { id: 'path', label: formatMessage(labels.pages), - url: updateParams({ view: 'path' }), + path: updateParams({ view: 'path' }), }, { id: 'referrer', label: formatMessage(labels.referrers), - url: updateParams({ view: 'referrer' }), + path: updateParams({ view: 'referrer' }), }, { id: 'channel', label: formatMessage(labels.channels), - url: updateParams({ view: 'channel' }), + path: updateParams({ view: 'channel' }), }, { id: 'browser', label: formatMessage(labels.browsers), - url: updateParams({ view: 'browser' }), + path: updateParams({ view: 'browser' }), }, { id: 'os', label: formatMessage(labels.os), - url: updateParams({ view: 'os' }), + path: updateParams({ view: 'os' }), }, { id: 'device', label: formatMessage(labels.devices), - url: updateParams({ view: 'device' }), + path: updateParams({ view: 'device' }), }, { id: 'country', label: formatMessage(labels.countries), - url: updateParams({ view: 'country' }), + path: updateParams({ view: 'country' }), }, { id: 'region', label: formatMessage(labels.regions), - url: updateParams({ view: 'region' }), + path: updateParams({ view: 'region' }), }, { id: 'city', label: formatMessage(labels.cities), - url: updateParams({ view: 'city' }), + path: updateParams({ view: 'city' }), }, { id: 'language', label: formatMessage(labels.languages), - url: updateParams({ view: 'language' }), + path: updateParams({ view: 'language' }), }, { id: 'screen', label: formatMessage(labels.screens), - url: updateParams({ view: 'screen' }), + path: updateParams({ view: 'screen' }), }, { id: 'event', label: formatMessage(labels.events), - url: updateParams({ view: 'event' }), + path: updateParams({ view: 'event' }), }, { id: 'query', label: formatMessage(labels.queryParameters), - url: updateParams({ view: 'query' }), + path: updateParams({ view: 'query' }), }, { id: 'hostname', label: formatMessage(labels.hostname), - url: updateParams({ view: 'hostname' }), + path: updateParams({ view: 'hostname' }), }, { id: 'tag', label: formatMessage(labels.tags), - url: updateParams({ view: 'tag' }), + path: updateParams({ view: 'tag' }), }, ]; const DetailsComponent = views[view] || (() => null); return ( - - - - - - - - {formatMessage(labels.back)} - - - - - - - - + + + + {items.map(({ id, label, path }) => { + return ( + + {label} + + ); + })} + + + + + + ); } diff --git a/src/app/(main)/websites/[websiteId]/WebsiteTableView.tsx b/src/app/(main)/websites/[websiteId]/WebsiteTableView.tsx index 1eb19744..93567cc1 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteTableView.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteTableView.tsx @@ -10,25 +10,27 @@ import { WorldMap } from '@/components/metrics/WorldMap'; import { CountriesTable } from '@/components/metrics/CountriesTable'; export function WebsiteTableView({ websiteId }: { websiteId: string }) { + const props = { websiteId, limit: 10, allowDownload: false }; + return ( - + - + - + - + - + @@ -36,7 +38,7 @@ export function WebsiteTableView({ websiteId }: { websiteId: string }) { - + diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx index b19785a5..c93b1543 100644 --- a/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx @@ -22,7 +22,7 @@ export function SegmentEditForm({ onSave, onClose, }: { - segmentId: string; + segmentId?: string; websiteId: string; filters?: any[]; showFilters?: boolean; diff --git a/src/components/common/SideMenu.tsx b/src/components/common/SideMenu.tsx index 4daa4909..2ded54f8 100644 --- a/src/components/common/SideMenu.tsx +++ b/src/components/common/SideMenu.tsx @@ -15,9 +15,16 @@ export interface SideMenuProps { title?: string; selectedKey?: string; allowMinimize?: boolean; + children?: React.ReactNode; } -export function SideMenu({ items, title, selectedKey, allowMinimize, children }: SideMenuProps) { +export function SideMenu({ + items = [], + title, + selectedKey, + allowMinimize, + children, +}: SideMenuProps) { return ( )} - {items.map(({ label, items }) => { + {items?.map(({ label, items }) => { return ( - {items.map(({ id, label, icon, path }) => { + {items?.map(({ id, label, icon, path }) => { const isSelected = selectedKey === id; return ( diff --git a/src/components/hooks/useNavigation.ts b/src/components/hooks/useNavigation.ts index 4db2dfe9..cdfb1fc6 100644 --- a/src/components/hooks/useNavigation.ts +++ b/src/components/hooks/useNavigation.ts @@ -18,10 +18,6 @@ export function useNavigation() { return buildUrl(pathname, params); }; - useEffect(() => { - setQueryParams(Object.fromEntries(searchParams)); - }, [searchParams.toString()]); - const renderUrl = (path: string, params?: Record | false) => { return buildUrl( teamId ? `/teams/${teamId}${path}` : path, @@ -29,6 +25,10 @@ export function useNavigation() { ); }; + useEffect(() => { + setQueryParams(Object.fromEntries(searchParams)); + }, [searchParams.toString()]); + return { router, pathname, diff --git a/src/components/metrics/MetricsTable.tsx b/src/components/metrics/MetricsTable.tsx index c18e46e4..8bac8f93 100644 --- a/src/components/metrics/MetricsTable.tsx +++ b/src/components/metrics/MetricsTable.tsx @@ -7,11 +7,11 @@ import { useWebsiteExpandedMetricsQuery, useWebsiteMetricsQuery, } from '@/components/hooks'; -import { Arrow } from '@/components/icons'; +import { Close, Maximize } from '@/components/icons'; import { DownloadButton } from '@/components/input/DownloadButton'; import { DEFAULT_ANIMATION_DURATION } from '@/lib/constants'; import { percentFilter } from '@/lib/filters'; -import { Column, Icon, Row, SearchField, Text } from '@umami/react-zen'; +import { Button, Column, Icon, Row, SearchField, Text } from '@umami/react-zen'; import { ReactNode, useMemo, useState } from 'react'; import { ListExpandedTable, ListExpandedTableProps } from './ListExpandedTable'; import { ListTable, ListTableProps } from './ListTable'; @@ -28,7 +28,8 @@ export interface MetricsTableProps extends ListTableProps { showMore?: boolean; params?: { [key: string]: any }; allowDownload?: boolean; - expanded?: boolean; + isExpanded?: boolean; + onClose?: () => void; children?: ReactNode; } @@ -43,7 +44,8 @@ export function MetricsTable({ showMore = true, params, allowDownload = true, - expanded = false, + isExpanded = false, + onClose, children, ...props }: MetricsTableProps) { @@ -61,7 +63,7 @@ export function MetricsTable({ }, { retryDelay: delay || DEFAULT_ANIMATION_DURATION, - enabled: expanded, + enabled: isExpanded, }, ); @@ -75,11 +77,11 @@ export function MetricsTable({ }, { retryDelay: delay || DEFAULT_ANIMATION_DURATION, - enabled: !expanded, + enabled: !isExpanded, }, ); - const { data, isLoading, isFetching, error } = expanded ? expandedQuery : query; + const { data, isLoading, isFetching, error } = isExpanded ? expandedQuery : query; const filteredData = useMemo(() => { if (data) { @@ -110,20 +112,27 @@ export function MetricsTable({ return []; }, [data, dataFilter, search, limit, formatValue, type]); - const downloadData = expanded ? data : filteredData; + const downloadData = isExpanded ? data : filteredData; return ( {allowSearch && } - + {children} {allowDownload && } + {onClose && ( + + )} {data && - (expanded ? ( + (isExpanded ? ( ) : ( @@ -131,10 +140,10 @@ export function MetricsTable({ {showMore && data && !error && limit && ( - {formatMessage(labels.more)} - + + {formatMessage(labels.more)} )} diff --git a/src/components/metrics/QueryParametersTable.tsx b/src/components/metrics/QueryParametersTable.tsx index 0d3ac268..90fc42a6 100644 --- a/src/components/metrics/QueryParametersTable.tsx +++ b/src/components/metrics/QueryParametersTable.tsx @@ -58,7 +58,7 @@ export function QueryParametersTable({ dataFilter={filters[filter]} renderLabel={renderLabel} delay={0} - expanded={false} + isExpanded={false} > {allowFilter && } From 8897c2508d6925f1ec58f7d155f1daf8e2af7b39 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 8 Aug 2025 17:39:17 -0700 Subject: [PATCH 150/399] Fixed scrolling on expanded view. --- .../[websiteId]/WebsiteDetailsPage.tsx | 2 +- .../[websiteId]/WebsiteExpandedView.tsx | 4 +- src/components/common/LoadingPanel.tsx | 2 +- src/components/metrics/MetricsTable.tsx | 49 ++++++++++--------- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx b/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx index 99517bb5..33bca5ae 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx @@ -34,7 +34,7 @@ export function WebsiteDetailsPage({ websiteId }: { websiteId: string }) { - + {({ close }) => { return handleClose(close)} />; }} diff --git a/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx b/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx index dabb2f49..ad2f8653 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteExpandedView.tsx @@ -133,7 +133,7 @@ export function WebsiteExpandedView({ const DetailsComponent = views[view] || (() => null); return ( - + {items.map(({ id, label, path }) => { @@ -145,7 +145,7 @@ export function WebsiteExpandedView({ })} - + + {/* Show loading spinner only if no data exists */} {(isLoading || isFetching) && !data && } diff --git a/src/components/metrics/MetricsTable.tsx b/src/components/metrics/MetricsTable.tsx index 8bac8f93..2f88b415 100644 --- a/src/components/metrics/MetricsTable.tsx +++ b/src/components/metrics/MetricsTable.tsx @@ -1,3 +1,5 @@ +import { ReactNode, useMemo, useState } from 'react'; +import { Button, Column, Icon, Row, SearchField, Text, Grid } from '@umami/react-zen'; import { LinkButton } from '@/components/common/LinkButton'; import { LoadingPanel } from '@/components/common/LoadingPanel'; import { @@ -11,8 +13,7 @@ import { Close, Maximize } from '@/components/icons'; import { DownloadButton } from '@/components/input/DownloadButton'; import { DEFAULT_ANIMATION_DURATION } from '@/lib/constants'; import { percentFilter } from '@/lib/filters'; -import { Button, Column, Icon, Row, SearchField, Text } from '@umami/react-zen'; -import { ReactNode, useMemo, useState } from 'react'; + import { ListExpandedTable, ListExpandedTableProps } from './ListExpandedTable'; import { ListTable, ListTableProps } from './ListTable'; @@ -115,11 +116,11 @@ export function MetricsTable({ const downloadData = isExpanded ? data : filteredData; return ( - - - + + + {allowSearch && } - + {children} {allowDownload && } {onClose && ( @@ -131,23 +132,25 @@ export function MetricsTable({ )} - {data && - (isExpanded ? ( - - ) : ( - - ))} - - {showMore && data && !error && limit && ( - - - - - {formatMessage(labels.more)} - + + {data && + (isExpanded ? ( + + ) : ( + + ))} + {showMore && limit && ( + + + + + + {formatMessage(labels.more)} + + )} - - - + + + ); } From a97445fb82101910198a6388ed8c8e3f0128ae8c Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 9 Aug 2025 02:06:54 -0700 Subject: [PATCH 151/399] Fixed sidenav rendering. --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- src/app/(main)/SideNav.tsx | 18 +++++++++++------- src/app/(main)/links/LinksPage.tsx | 24 ++++++++++++++++++++++++ src/app/(main)/links/page.tsx | 10 ++++++++++ src/app/(main)/pixels/PixelsPage.tsx | 24 ++++++++++++++++++++++++ src/app/(main)/pixels/page.tsx | 10 ++++++++++ src/components/common/LoadingPanel.tsx | 10 +++++++--- src/components/input/TeamsButton.tsx | 8 +++----- 9 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 src/app/(main)/links/LinksPage.tsx create mode 100644 src/app/(main)/links/page.tsx create mode 100644 src/app/(main)/pixels/PixelsPage.tsx create mode 100644 src/app/(main)/pixels/page.tsx diff --git a/package.json b/package.json index d666d34e..1c65a29f 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "@react-spring/web": "^9.7.3", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.83.0", - "@umami/react-zen": "^0.157.0", + "@umami/react-zen": "^0.162.0", "@umami/redis-client": "^0.27.0", "bcryptjs": "^3.0.2", "chalk": "^5.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 392dc12b..30e81f4b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^5.83.0 version: 5.83.0(react@19.1.1) '@umami/react-zen': - specifier: ^0.157.0 - version: 0.157.0(@babel/core@7.27.1)(@types/react@19.1.9)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.1)) + specifier: ^0.162.0 + version: 0.162.0(@babel/core@7.27.1)(@types/react@19.1.9)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.1)) '@umami/redis-client': specifier: ^0.27.0 version: 0.27.0 @@ -2547,8 +2547,8 @@ packages: resolution: {integrity: sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@umami/react-zen@0.157.0': - resolution: {integrity: sha512-QZqZcah1t6KniDvFTF+GxBDkaEYUuQOyj1olao5p5rtZBMW1/v4GaVcL+8UAzWyWIUnsrRI3e5HoytapJg6VfQ==} + '@umami/react-zen@0.162.0': + resolution: {integrity: sha512-pQs5XV6arCjeyWjBBy2rCW2UcWKbq2HjU44iskaV63D88b3sWL6dyx4FnHfJ/0UQv20OJ1gv0qqElB4fva3d8Q==} '@umami/redis-client@0.27.0': resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==} @@ -9873,7 +9873,7 @@ snapshots: '@typescript-eslint/types': 8.38.0 eslint-visitor-keys: 4.2.1 - '@umami/react-zen@0.157.0(@babel/core@7.27.1)(@types/react@19.1.9)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.1))': + '@umami/react-zen@0.162.0(@babel/core@7.27.1)(@types/react@19.1.9)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.1))': dependencies: '@fontsource/jetbrains-mono': 5.2.6 '@internationalized/date': 3.8.2 diff --git a/src/app/(main)/SideNav.tsx b/src/app/(main)/SideNav.tsx index 06b0abc9..61bd1cbf 100644 --- a/src/app/(main)/SideNav.tsx +++ b/src/app/(main)/SideNav.tsx @@ -23,7 +23,7 @@ import { PanelButton } from '@/components/input/PanelButton'; export function SideNav(props: SidebarProps) { const { formatMessage, labels } = useMessages(); const { pathname, renderUrl, websiteId } = useNavigation(); - const [isCollapsed] = useGlobalState('sidenav-collapsed'); + let [isCollapsed] = useGlobalState('sidenav-collapsed'); const hasNav = !!( websiteId || @@ -32,19 +32,23 @@ export function SideNav(props: SidebarProps) { pathname.endsWith('/settings') ); + if (hasNav) { + isCollapsed = true; + } + const links = [ - { - id: 'websites', - label: formatMessage(labels.websites), - path: '/websites', - icon: , - }, { id: 'boards', label: formatMessage(labels.boards), path: '/boards', icon: , }, + { + id: 'websites', + label: formatMessage(labels.websites), + path: '/websites', + icon: , + }, { id: 'links', label: formatMessage(labels.links), diff --git a/src/app/(main)/links/LinksPage.tsx b/src/app/(main)/links/LinksPage.tsx new file mode 100644 index 00000000..1b680dd8 --- /dev/null +++ b/src/app/(main)/links/LinksPage.tsx @@ -0,0 +1,24 @@ +'use client'; +import { PageBody } from '@/components/common/PageBody'; +import { Column } from '@umami/react-zen'; +import { PageHeader } from '@/components/common/PageHeader'; +import { BoardAddButton } from '@/app/(main)/boards/BoardAddButton'; +import Link from 'next/link'; +import { useMessages } from '@/components/hooks'; + +export function LinksPage() { + const { formatMessage, labels } = useMessages(); + + return ( + + + + + + + Board 1 + + + + ); +} diff --git a/src/app/(main)/links/page.tsx b/src/app/(main)/links/page.tsx new file mode 100644 index 00000000..ed89c727 --- /dev/null +++ b/src/app/(main)/links/page.tsx @@ -0,0 +1,10 @@ +import { LinksPage } from './LinksPage'; +import { Metadata } from 'next'; + +export default function () { + return ; +} + +export const metadata: Metadata = { + title: 'Links', +}; diff --git a/src/app/(main)/pixels/PixelsPage.tsx b/src/app/(main)/pixels/PixelsPage.tsx new file mode 100644 index 00000000..fa686620 --- /dev/null +++ b/src/app/(main)/pixels/PixelsPage.tsx @@ -0,0 +1,24 @@ +'use client'; +import { PageBody } from '@/components/common/PageBody'; +import { Column } from '@umami/react-zen'; +import { PageHeader } from '@/components/common/PageHeader'; +import { BoardAddButton } from '@/app/(main)/boards/BoardAddButton'; +import Link from 'next/link'; +import { useMessages } from '@/components/hooks'; + +export function PixelsPage() { + const { formatMessage, labels } = useMessages(); + + return ( + + + + + + + Board 1 + + + + ); +} diff --git a/src/app/(main)/pixels/page.tsx b/src/app/(main)/pixels/page.tsx new file mode 100644 index 00000000..4573b065 --- /dev/null +++ b/src/app/(main)/pixels/page.tsx @@ -0,0 +1,10 @@ +import { PixelsPage } from './PixelsPage'; +import { Metadata } from 'next'; + +export default function () { + return ; +} + +export const metadata: Metadata = { + title: 'Pixels', +}; diff --git a/src/components/common/LoadingPanel.tsx b/src/components/common/LoadingPanel.tsx index 177b9898..73208c7d 100644 --- a/src/components/common/LoadingPanel.tsx +++ b/src/components/common/LoadingPanel.tsx @@ -28,9 +28,13 @@ export function LoadingPanel({ const empty = isEmpty ?? checkEmpty(data); return ( - + <> {/* Show loading spinner only if no data exists */} - {(isLoading || isFetching) && !data && } + {(isLoading || isFetching) && !data && ( + + + + )} {/* Show error */} {error && } @@ -40,7 +44,7 @@ export function LoadingPanel({ {/* Show main content when data exists */} {!error && !empty && children} - + ); } diff --git a/src/components/input/TeamsButton.tsx b/src/components/input/TeamsButton.tsx index 6c84493a..c9fd9dd0 100644 --- a/src/components/input/TeamsButton.tsx +++ b/src/components/input/TeamsButton.tsx @@ -25,6 +25,7 @@ export function TeamsButton({ showText = true }: { showText?: boolean }) { const router = useRouter(); const team = data?.data?.find(({ id }) => id === teamId); const selectedKeys = new Set([teamId || user.id]); + const label = teamId ? team?.name : user.username; const handleSelect = (id: Key) => { router.push(id === user.id ? '/websites' : `/teams/${id}/websites`); @@ -37,11 +38,8 @@ export function TeamsButton({ showText = true }: { showText?: boolean }) { return ( - - : } - > + + : }> {showText && ( From c60e8b3d23a1f9a4b785ecefb7a4d08b98975f13 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 9 Aug 2025 17:46:27 -0700 Subject: [PATCH 152/399] Moved panel button. --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- src/app/(main)/SideNav.tsx | 18 +++++++----------- src/components/input/PanelButton.tsx | 7 ++++++- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 1c65a29f..425d48b1 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "@react-spring/web": "^9.7.3", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.83.0", - "@umami/react-zen": "^0.162.0", + "@umami/react-zen": "^0.163.0", "@umami/redis-client": "^0.27.0", "bcryptjs": "^3.0.2", "chalk": "^5.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30e81f4b..35e2ae0f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^5.83.0 version: 5.83.0(react@19.1.1) '@umami/react-zen': - specifier: ^0.162.0 - version: 0.162.0(@babel/core@7.27.1)(@types/react@19.1.9)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.1)) + specifier: ^0.163.0 + version: 0.163.0(@babel/core@7.27.1)(@types/react@19.1.9)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.1)) '@umami/redis-client': specifier: ^0.27.0 version: 0.27.0 @@ -2547,8 +2547,8 @@ packages: resolution: {integrity: sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@umami/react-zen@0.162.0': - resolution: {integrity: sha512-pQs5XV6arCjeyWjBBy2rCW2UcWKbq2HjU44iskaV63D88b3sWL6dyx4FnHfJ/0UQv20OJ1gv0qqElB4fva3d8Q==} + '@umami/react-zen@0.163.0': + resolution: {integrity: sha512-H+Z7sADljnBdzRQdOUIHXKphiPkzHKTLTNtBf/VbylzXg5A61e+OYoDG37eOkR+JFU9+KmJnF+zOiXyA33LW0A==} '@umami/redis-client@0.27.0': resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==} @@ -9873,7 +9873,7 @@ snapshots: '@typescript-eslint/types': 8.38.0 eslint-visitor-keys: 4.2.1 - '@umami/react-zen@0.162.0(@babel/core@7.27.1)(@types/react@19.1.9)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.1))': + '@umami/react-zen@0.163.0(@babel/core@7.27.1)(@types/react@19.1.9)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.1))': dependencies: '@fontsource/jetbrains-mono': 5.2.6 '@internationalized/date': 3.8.2 diff --git a/src/app/(main)/SideNav.tsx b/src/app/(main)/SideNav.tsx index 61bd1cbf..57dd0a8e 100644 --- a/src/app/(main)/SideNav.tsx +++ b/src/app/(main)/SideNav.tsx @@ -15,6 +15,7 @@ import { Grid2X2, Settings, LockKeyhole, + PanelLeft, } from '@/components/icons'; import { useMessages, useNavigation, useGlobalState } from '@/components/hooks'; import { TeamsButton } from '@/components/input/TeamsButton'; @@ -23,7 +24,7 @@ import { PanelButton } from '@/components/input/PanelButton'; export function SideNav(props: SidebarProps) { const { formatMessage, labels } = useMessages(); const { pathname, renderUrl, websiteId } = useNavigation(); - let [isCollapsed] = useGlobalState('sidenav-collapsed'); + const [isCollapsed, setIsCollapsed] = useGlobalState('sidenav-collapsed'); const hasNav = !!( websiteId || @@ -32,10 +33,6 @@ export function SideNav(props: SidebarProps) { pathname.endsWith('/settings') ); - if (hasNav) { - isCollapsed = true; - } - const links = [ { id: 'boards', @@ -81,8 +78,10 @@ export function SideNav(props: SidebarProps) { return ( - - } /> + setIsCollapsed(false)}> + : }> + {!isCollapsed && !hasNav && } + {links.map(({ id, path, label, icon }) => { @@ -103,10 +102,7 @@ export function SideNav(props: SidebarProps) { })} - - - - + diff --git a/src/components/input/PanelButton.tsx b/src/components/input/PanelButton.tsx index 04a9b01c..58a69195 100644 --- a/src/components/input/PanelButton.tsx +++ b/src/components/input/PanelButton.tsx @@ -5,7 +5,12 @@ import { useGlobalState } from '@/components/hooks'; export function PanelButton(props: ButtonProps) { const [isCollapsed, setIsCollapsed] = useGlobalState('sidenav-collapsed'); return ( - - + - - - - - - {formatMessage(labels.settings)} - - - {user.isAdmin && ( - - - - - - {formatMessage(labels.admin)} - - - )} - {!cloudMode && ( - - - - - - {formatMessage(labels.logout)} - - - )} + {items.map(({ id, path, label, icon, separator }) => { + return ( + + {separator && } + + + {icon} + {label} + + + + ); + })} diff --git a/src/components/input/WebsiteSelect.tsx b/src/components/input/WebsiteSelect.tsx index 40e31a2f..917c7d21 100644 --- a/src/components/input/WebsiteSelect.tsx +++ b/src/components/input/WebsiteSelect.tsx @@ -1,17 +1,14 @@ import { useState } from 'react'; import { Select, SelectProps, ListItem, Text } from '@umami/react-zen'; import { useUserWebsitesQuery, useWebsiteQuery, useNavigation } from '@/components/hooks'; -import { ButtonProps } from 'react-basics'; export function WebsiteSelect({ websiteId, teamId, - buttonProps, ...props }: { websiteId?: string; teamId?: string; - buttonProps?: ButtonProps; } & SelectProps) { const { router, renderUrl } = useNavigation(); const [search, setSearch] = useState(''); @@ -33,7 +30,7 @@ export function WebsiteSelect({ items={data?.['data'] || []} value={websiteId} isLoading={isLoading} - buttonProps={{ ...buttonProps }} + buttonProps={{ variant: 'outline' }} allowSearch={true} searchValue={search} onSearch={handleSearch} diff --git a/src/components/metrics/MetricsTable.tsx b/src/components/metrics/MetricsTable.tsx index 2f88b415..1db956ca 100644 --- a/src/components/metrics/MetricsTable.tsx +++ b/src/components/metrics/MetricsTable.tsx @@ -117,7 +117,7 @@ export function MetricsTable({ return ( - + {allowSearch && } diff --git a/src/index.ts b/src/index.ts index 6a8ebecf..0c84624c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,7 @@ export * from '@/app/(main)/teams/[teamId]/TeamMemberRemoveButton'; export * from '@/app/(main)/teams/[teamId]/TeamMembersDataTable'; export * from '@/app/(main)/teams/[teamId]/TeamMembersTable'; export * from '@/app/(main)/teams/[teamId]/TeamDeleteForm'; -export * from '@/app/(main)/teams/[teamId]/TeamDetails'; +export * from '@/app/(main)/teams/[teamId]/TeamSettings'; export * from '@/app/(main)/teams/[teamId]/TeamEditForm'; export * from '@/app/(main)/teams/[teamId]/TeamManage'; export * from '@/app/(main)/teams/[teamId]/TeamWebsiteRemoveButton'; diff --git a/src/queries/prisma/link.ts b/src/queries/prisma/link.ts index f7f5e158..ea46023c 100644 --- a/src/queries/prisma/link.ts +++ b/src/queries/prisma/link.ts @@ -2,7 +2,7 @@ import { Prisma, Link } from '@/generated/prisma/client'; import prisma from '@/lib/prisma'; import { PageResult, QueryFilters } from '@/lib/types'; -async function findLink(criteria: Prisma.LinkFindUniqueArgs): Promise { +export async function findLink(criteria: Prisma.LinkFindUniqueArgs): Promise { return prisma.client.link.findUnique(criteria); } diff --git a/src/queries/prisma/pixel.ts b/src/queries/prisma/pixel.ts index db494fa8..a68c5300 100644 --- a/src/queries/prisma/pixel.ts +++ b/src/queries/prisma/pixel.ts @@ -2,7 +2,7 @@ import { Prisma, Pixel } from '@/generated/prisma/client'; import prisma from '@/lib/prisma'; import { PageResult, QueryFilters } from '@/lib/types'; -async function findPixel(criteria: Prisma.PixelFindUniqueArgs): Promise { +export async function findPixel(criteria: Prisma.PixelFindUniqueArgs): Promise { return prisma.client.pixel.findUnique(criteria); } @@ -22,7 +22,7 @@ export async function getPixels( const where: Prisma.PixelWhereInput = { ...criteria.where, - ...prisma.getSearchParameters(search, [{ name: 'contains' }]), + ...prisma.getSearchParameters(search, [{ name: 'contains' }, { slug: 'contains' }]), }; return prisma.pagedQuery('pixel', { ...criteria, where }, filters); diff --git a/src/queries/prisma/website.ts b/src/queries/prisma/website.ts index 5bdf6862..683aab0f 100644 --- a/src/queries/prisma/website.ts +++ b/src/queries/prisma/website.ts @@ -4,7 +4,7 @@ import prisma from '@/lib/prisma'; import { PageResult, QueryFilters } from '@/lib/types'; import { ROLES } from '@/lib/constants'; -async function findWebsite(criteria: Prisma.WebsiteFindUniqueArgs): Promise { +export async function findWebsite(criteria: Prisma.WebsiteFindUniqueArgs): Promise { return prisma.client.website.findUnique(criteria); } diff --git a/src/queries/sql/events/saveEvent.ts b/src/queries/sql/events/saveEvent.ts index 92056206..c351b95c 100644 --- a/src/queries/sql/events/saveEvent.ts +++ b/src/queries/sql/events/saveEvent.ts @@ -12,6 +12,7 @@ export interface SaveEventArgs { sessionId: string; visitId: string; createdAt?: Date; + eventType?: number; // Page pageTitle?: string; @@ -66,6 +67,7 @@ async function relationalQuery({ sessionId, visitId, createdAt, + eventType, pageTitle, tag, hostname, @@ -113,7 +115,7 @@ async function relationalQuery({ ttclid, lifatid, twclid, - eventType: eventName ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView, + eventType: eventType || (eventName ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView), eventName: eventName ? eventName?.substring(0, EVENT_NAME_LENGTH) : null, tag, hostname, From 32febf0fbbdfb118823444e256da9ca010133e32 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Mon, 18 Aug 2025 09:58:26 -0700 Subject: [PATCH 165/399] add unique index to slug columns --- prisma/migrations/14_add_link_and_pixel/migration.sql | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/prisma/migrations/14_add_link_and_pixel/migration.sql b/prisma/migrations/14_add_link_and_pixel/migration.sql index 4feec4f4..45320b03 100644 --- a/prisma/migrations/14_add_link_and_pixel/migration.sql +++ b/prisma/migrations/14_add_link_and_pixel/migration.sql @@ -12,7 +12,7 @@ CREATE TABLE "link" ( "link_id" UUID NOT NULL, "name" VARCHAR(100) NOT NULL, "url" VARCHAR(500) NOT NULL, - "slug" VARCHAR(100) UNIQUE NOT NULL, + "slug" VARCHAR(100) NOT NULL, "user_id" UUID, "team_id" UUID, "created_at" TIMESTAMPTZ(6) DEFAULT CURRENT_TIMESTAMP, @@ -26,7 +26,7 @@ CREATE TABLE "link" ( CREATE TABLE "pixel" ( "pixel_id" UUID NOT NULL, "name" VARCHAR(100) NOT NULL, - "slug" VARCHAR(100) UNIQUE NOT NULL, + "slug" VARCHAR(100) NOT NULL, "user_id" UUID, "team_id" UUID, "created_at" TIMESTAMPTZ(6) DEFAULT CURRENT_TIMESTAMP, @@ -39,6 +39,9 @@ CREATE TABLE "pixel" ( -- CreateIndex CREATE UNIQUE INDEX "link_link_id_key" ON "link"("link_id"); +-- CreateIndex +CREATE UNIQUE INDEX "link_slug_key" ON "link"("slug"); + -- CreateIndex CREATE INDEX "link_slug_idx" ON "link"("slug"); @@ -54,6 +57,9 @@ CREATE INDEX "link_created_at_idx" ON "link"("created_at"); -- CreateIndex CREATE UNIQUE INDEX "pixel_pixel_id_key" ON "pixel"("pixel_id"); +-- CreateIndex +CREATE UNIQUE INDEX "pixel_slug_key" ON "pixel"("slug"); + -- CreateIndex CREATE INDEX "pixel_slug_idx" ON "pixel"("slug"); From 0ac8bd41b63d3cc47c307b4769ebdca329e73baf Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 18 Aug 2025 15:49:10 -0700 Subject: [PATCH 166/399] Pixel route. --- src/app/(collect)/p/[slug]/route.ts | 45 ++++++++ src/app/(collect)/q/[slug]/route.ts | 0 src/app/api/links/[linkId]/route.ts | 2 +- src/app/api/pixels/[pixelId]/route.ts | 2 +- src/app/api/send/route.ts | 128 ++++++++++++++-------- src/app/api/websites/[websiteId]/route.ts | 2 +- src/lib/constants.ts | 2 + src/lib/detect.ts | 6 +- src/queries/sql/events/saveEvent.ts | 4 +- src/queries/sql/sessions/createSession.ts | 12 +- 10 files changed, 139 insertions(+), 64 deletions(-) create mode 100644 src/app/(collect)/p/[slug]/route.ts create mode 100644 src/app/(collect)/q/[slug]/route.ts diff --git a/src/app/(collect)/p/[slug]/route.ts b/src/app/(collect)/p/[slug]/route.ts new file mode 100644 index 00000000..97d9a3f2 --- /dev/null +++ b/src/app/(collect)/p/[slug]/route.ts @@ -0,0 +1,45 @@ +import { NextResponse } from 'next/server'; +import { notFound } from '@/lib/response'; +import { findPixel } from '@/queries'; +import { POST } from '@/app/api/send/route'; + +const image = Buffer.from('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw', 'base64'); + +export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) { + const { slug } = await params; + + const pixel = await findPixel({ + where: { + slug, + }, + }); + + if (!pixel) { + return notFound(); + } + + const payload = { + type: 'event', + payload: { + pixel: pixel.id, + url: request.url, + referrer: request.referrer, + }, + }; + + const req = new Request(request.url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + + const res = await POST(req); + + return new NextResponse(image, { + headers: { + 'Content-Type': 'image/gif', + 'Content-Length': image.length.toString(), + 'x-umami-collect': JSON.stringify(res), + }, + }); +} diff --git a/src/app/(collect)/q/[slug]/route.ts b/src/app/(collect)/q/[slug]/route.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/api/links/[linkId]/route.ts b/src/app/api/links/[linkId]/route.ts index db50e878..9647961c 100644 --- a/src/app/api/links/[linkId]/route.ts +++ b/src/app/api/links/[linkId]/route.ts @@ -47,7 +47,7 @@ export async function POST(request: Request, { params }: { params: Promise<{ lin return Response.json(result); } catch (e: any) { - if (e.message.includes('Unique constraint') && e.message.includes('slug')) { + if (e.message.toLowerCase().includes('unique constraint') && e.message.includes('slug')) { return badRequest('That slug is already taken.'); } diff --git a/src/app/api/pixels/[pixelId]/route.ts b/src/app/api/pixels/[pixelId]/route.ts index f9c95236..7a4bcfda 100644 --- a/src/app/api/pixels/[pixelId]/route.ts +++ b/src/app/api/pixels/[pixelId]/route.ts @@ -46,7 +46,7 @@ export async function POST(request: Request, { params }: { params: Promise<{ pix return Response.json(pixel); } catch (e: any) { - if (e.message.includes('Unique constraint') && e.message.includes('slug')) { + if (e.message.toLowerCase().includes('unique constraint') && e.message.includes('slug')) { return badRequest('That slug is already taken.'); } diff --git a/src/app/api/send/route.ts b/src/app/api/send/route.ts index 04876cd4..0b177f08 100644 --- a/src/app/api/send/route.ts +++ b/src/app/api/send/route.ts @@ -1,4 +1,5 @@ import { z } from 'zod'; +import debug from 'debug'; import { isbot } from 'isbot'; import { startOfHour, startOfMonth } from 'date-fns'; import clickhouse from '@/lib/clickhouse'; @@ -8,29 +9,52 @@ import { fetchWebsite } from '@/lib/load'; import { getClientInfo, hasBlockedIp } from '@/lib/detect'; import { createToken, parseToken } from '@/lib/jwt'; import { secret, uuid, hash } from '@/lib/crypto'; -import { COLLECTION_TYPE } from '@/lib/constants'; +import { COLLECTION_TYPE, EVENT_TYPE } from '@/lib/constants'; import { anyObjectParam, urlOrPathParam } from '@/lib/schema'; import { safeDecodeURI, safeDecodeURIComponent } from '@/lib/url'; import { createSession, saveEvent, saveSessionData } from '@/queries'; +const log = debug('umami:send'); + +interface Cache { + websiteId: string; + sessionId: string; + visitId: string; + iat: number; +} + const schema = z.object({ type: z.enum(['event', 'identify']), - payload: z.object({ - website: z.string().uuid(), - data: anyObjectParam.optional(), - hostname: z.string().max(100).optional(), - language: z.string().max(35).optional(), - referrer: urlOrPathParam.optional(), - screen: z.string().max(11).optional(), - title: z.string().optional(), - url: urlOrPathParam.optional(), - name: z.string().max(50).optional(), - tag: z.string().max(50).optional(), - ip: z.string().ip().optional(), - userAgent: z.string().optional(), - timestamp: z.coerce.number().int().optional(), - id: z.string().optional(), - }), + payload: z + .object({ + website: z.string().uuid().optional(), + link: z.string().uuid().optional(), + pixel: z.string().uuid().optional(), + data: anyObjectParam.optional(), + hostname: z.string().max(100).optional(), + language: z.string().max(35).optional(), + referrer: urlOrPathParam.optional(), + screen: z.string().max(11).optional(), + title: z.string().optional(), + url: urlOrPathParam.optional(), + name: z.string().max(50).optional(), + tag: z.string().max(50).optional(), + ip: z.string().ip().optional(), + userAgent: z.string().optional(), + timestamp: z.coerce.number().int().optional(), + id: z.string().optional(), + }) + .refine( + data => { + const keys = [data.website, data.link, data.pixel]; + const count = keys.filter(Boolean).length; + return count === 1; + }, + { + message: 'Exactly one of website, link, or pixel must be provided', + path: ['website'], + }, + ), }); export async function POST(request: Request) { @@ -45,6 +69,8 @@ export async function POST(request: Request) { const { website: websiteId, + pixel: pixelId, + link: linkId, hostname, screen, language, @@ -59,23 +85,26 @@ export async function POST(request: Request) { } = payload; // Cache check - let cache: { websiteId: string; sessionId: string; visitId: string; iat: number } | null = null; - const cacheHeader = request.headers.get('x-umami-cache'); + let cache: Cache | null = null; - if (cacheHeader) { - const result = await parseToken(cacheHeader, secret()); + if (websiteId) { + const cacheHeader = request.headers.get('x-umami-cache'); - if (result) { - cache = result; + if (cacheHeader) { + const result = await parseToken(cacheHeader, secret()); + + if (result) { + cache = result; + } } - } - // Find website - if (!cache?.websiteId) { - const website = await fetchWebsite(websiteId); + // Find website + if (!cache?.websiteId) { + const website = await fetchWebsite(websiteId); - if (!website) { - return badRequest('Website not found.'); + if (!website) { + return badRequest('Website not found.'); + } } } @@ -105,22 +134,19 @@ export async function POST(request: Request) { // Create a session if not found if (!clickhouse.enabled && !cache?.sessionId) { - await createSession( - { - id: sessionId, - websiteId, - browser, - os, - device, - screen, - language, - country, - region, - city, - distinctId: id, - }, - { skipDuplicates: true }, - ); + await createSession({ + id: sessionId, + websiteId, + browser, + os, + device, + screen, + language, + country, + region, + city, + distinctId: id, + }); } // Visit info @@ -176,10 +202,19 @@ export async function POST(request: Request) { } } + const eventType = linkId + ? EVENT_TYPE.linkEvent + : pixelId + ? EVENT_TYPE.pixelEvent + : name + ? EVENT_TYPE.customEvent + : EVENT_TYPE.pageView; + await saveEvent({ - websiteId, + websiteId: websiteId || linkId || pixelId, sessionId, visitId, + eventType, createdAt, // Page @@ -240,6 +275,7 @@ export async function POST(request: Request) { return json({ cache: token, sessionId, visitId }); } catch (e) { + log.error(e); return serverError(e); } } diff --git a/src/app/api/websites/[websiteId]/route.ts b/src/app/api/websites/[websiteId]/route.ts index 22f3979d..466711ad 100644 --- a/src/app/api/websites/[websiteId]/route.ts +++ b/src/app/api/websites/[websiteId]/route.ts @@ -54,7 +54,7 @@ export async function POST( return Response.json(website); } catch (e: any) { - if (e.message.includes('Unique constraint') && e.message.includes('share_id')) { + if (e.message.toLowerCase().includes('unique constraint') && e.message.includes('share_id')) { return badRequest('That share ID is already taken.'); } diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 168d9304..759690b6 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -87,6 +87,8 @@ export const COLLECTION_TYPE = { export const EVENT_TYPE = { pageView: 1, customEvent: 2, + linkEvent: 3, + pixelEvent: 4, } as const; export const DATA_TYPE = { diff --git a/src/lib/detect.ts b/src/lib/detect.ts index f2c9d9fb..e15e5b16 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -89,8 +89,8 @@ function decodeHeader(s: string | undefined | null): string | undefined | null { export async function getLocation(ip: string = '', headers: Headers, hasPayloadIP: boolean) { // Ignore local ips - if (await isLocalhost(ip)) { - return; + if (!ip || (await isLocalhost(ip))) { + return null; } if (!hasPayloadIP && !process.env.SKIP_LOCATION_HEADERS) { @@ -130,7 +130,7 @@ export async function getLocation(ip: string = '', headers: Headers, hasPayloadI ); } - const result = globalThis[MAXMIND].get(ip?.split(':')[0]); + const result = globalThis[MAXMIND]?.get(ip?.split(':')[0]); if (result) { const country = result.country?.iso_code ?? result?.registered_country?.iso_code; diff --git a/src/queries/sql/events/saveEvent.ts b/src/queries/sql/events/saveEvent.ts index c351b95c..06376740 100644 --- a/src/queries/sql/events/saveEvent.ts +++ b/src/queries/sql/events/saveEvent.ts @@ -11,8 +11,8 @@ export interface SaveEventArgs { websiteId: string; sessionId: string; visitId: string; + eventType: number; createdAt?: Date; - eventType?: number; // Page pageTitle?: string; @@ -115,7 +115,7 @@ async function relationalQuery({ ttclid, lifatid, twclid, - eventType: eventType || (eventName ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView), + eventType, eventName: eventName ? eventName?.substring(0, EVENT_NAME_LENGTH) : null, tag, hostname, diff --git a/src/queries/sql/sessions/createSession.ts b/src/queries/sql/sessions/createSession.ts index 395f9f4c..958754f1 100644 --- a/src/queries/sql/sessions/createSession.ts +++ b/src/queries/sql/sessions/createSession.ts @@ -1,10 +1,7 @@ import { Prisma } from '@/generated/prisma/client'; import prisma from '@/lib/prisma'; -export async function createSession( - data: Prisma.SessionCreateInput, - options = { skipDuplicates: false }, -) { +export async function createSession(data: Prisma.SessionCreateInput) { const { id, websiteId, @@ -36,12 +33,7 @@ export async function createSession( }, }); } catch (e: any) { - // With skipDuplicates flag: ignore unique constraint error and return null - if ( - options.skipDuplicates && - e instanceof Prisma.PrismaClientKnownRequestError && - e.code === 'P2002' - ) { + if (e.message.toLowerCase().includes('unique constraint')) { return null; } throw e; From 789b8b36d81a53b0d935aba814de0ea3a6f45bf0 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 18 Aug 2025 22:30:22 -0700 Subject: [PATCH 167/399] Link route. --- package.json | 6 +- pnpm-lock.yaml | 104 ++++++++++++++-------------- src/app/(collect)/q/[slug]/route.ts | 37 ++++++++++ src/app/api/send/route.ts | 4 +- 4 files changed, 93 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index e62c41ec..590c9174 100644 --- a/package.json +++ b/package.json @@ -105,14 +105,14 @@ "is-ci": "^3.0.1", "is-docker": "^3.0.0", "is-localhost-ip": "^2.0.0", - "isbot": "^5.1.16", + "isbot": "^5.1.30", "jsonwebtoken": "^9.0.2", "jszip": "^3.10.1", "kafkajs": "^2.1.0", - "lucide-react": "^0.526.0", + "lucide-react": "^0.540.0", "maxmind": "^4.3.28", "md5": "^2.3.0", - "next": "15.4.6", + "next": "15.4.7", "node-fetch": "^3.2.8", "npm-run-all": "^4.1.5", "papaparse": "^5.5.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c00d5f28..7fb9a26e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -114,8 +114,8 @@ importers: specifier: ^2.0.0 version: 2.0.0 isbot: - specifier: ^5.1.16 - version: 5.1.29 + specifier: ^5.1.30 + version: 5.1.30 jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 @@ -126,8 +126,8 @@ importers: specifier: ^2.1.0 version: 2.2.4 lucide-react: - specifier: ^0.526.0 - version: 0.526.0(react@19.1.1) + specifier: ^0.540.0 + version: 0.540.0(react@19.1.1) maxmind: specifier: ^4.3.28 version: 4.3.29 @@ -135,8 +135,8 @@ importers: specifier: ^2.3.0 version: 2.3.0 next: - specifier: 15.4.6 - version: 15.4.6(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + specifier: 15.4.7 + version: 15.4.7(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) node-fetch: specifier: ^3.2.8 version: 3.3.2 @@ -1382,56 +1382,56 @@ packages: resolution: {integrity: sha512-SXQY/nCiSOSAZWNls/DQxrICldUR7PHSMUw2J2/ZejH1dk12Vwd3+SzSihHrRW9PNcErZkC2g3seM7bWZlvBRg==} engines: {node: '>=18.0.0'} - '@next/env@15.4.6': - resolution: {integrity: sha512-yHDKVTcHrZy/8TWhj0B23ylKv5ypocuCwey9ZqPyv4rPdUdRzpGCkSi03t04KBPyU96kxVtUqx6O3nE1kpxASQ==} + '@next/env@15.4.7': + resolution: {integrity: sha512-PrBIpO8oljZGTOe9HH0miix1w5MUiGJ/q83Jge03mHEE0E3pyqzAy2+l5G6aJDbXoobmxPJTVhbCuwlLtjSHwg==} '@next/eslint-plugin-next@14.2.31': resolution: {integrity: sha512-ouaB+l8Cr/uzGxoGHUvd01OnfFTM8qM81Crw1AG0xoWDRN0DKLXyTWVe0FdAOHVBpGuXB87aufdRmrwzZDArIw==} - '@next/swc-darwin-arm64@15.4.6': - resolution: {integrity: sha512-667R0RTP4DwxzmrqTs4Lr5dcEda9OxuZsVFsjVtxVMVhzSpo6nLclXejJVfQo2/g7/Z9qF3ETDmN3h65mTjpTQ==} + '@next/swc-darwin-arm64@15.4.7': + resolution: {integrity: sha512-2Dkb+VUTp9kHHkSqtws4fDl2Oxms29HcZBwFIda1X7Ztudzy7M6XF9HDS2dq85TmdN47VpuhjE+i6wgnIboVzQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.4.6': - resolution: {integrity: sha512-KMSFoistFkaiQYVQQnaU9MPWtp/3m0kn2Xed1Ces5ll+ag1+rlac20sxG+MqhH2qYWX1O2GFOATQXEyxKiIscg==} + '@next/swc-darwin-x64@15.4.7': + resolution: {integrity: sha512-qaMnEozKdWezlmh1OGDVFueFv2z9lWTcLvt7e39QA3YOvZHNpN2rLs/IQLwZaUiw2jSvxW07LxMCWtOqsWFNQg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.4.6': - resolution: {integrity: sha512-PnOx1YdO0W7m/HWFeYd2A6JtBO8O8Eb9h6nfJia2Dw1sRHoHpNf6lN1U4GKFRzRDBi9Nq2GrHk9PF3Vmwf7XVw==} + '@next/swc-linux-arm64-gnu@15.4.7': + resolution: {integrity: sha512-ny7lODPE7a15Qms8LZiN9wjNWIeI+iAZOFDOnv2pcHStncUr7cr9lD5XF81mdhrBXLUP9yT9RzlmSWKIazWoDw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.4.6': - resolution: {integrity: sha512-XBbuQddtY1p5FGPc2naMO0kqs4YYtLYK/8aPausI5lyOjr4J77KTG9mtlU4P3NwkLI1+OjsPzKVvSJdMs3cFaw==} + '@next/swc-linux-arm64-musl@15.4.7': + resolution: {integrity: sha512-4SaCjlFR/2hGJqZLLWycccy1t+wBrE/vyJWnYaZJhUVHccpGLG5q0C+Xkw4iRzUIkE+/dr90MJRUym3s1+vO8A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.4.6': - resolution: {integrity: sha512-+WTeK7Qdw82ez3U9JgD+igBAP75gqZ1vbK6R8PlEEuY0OIe5FuYXA4aTjL811kWPf7hNeslD4hHK2WoM9W0IgA==} + '@next/swc-linux-x64-gnu@15.4.7': + resolution: {integrity: sha512-2uNXjxvONyRidg00VwvlTYDwC9EgCGNzPAPYbttIATZRxmOZ3hllk/YYESzHZb65eyZfBR5g9xgCZjRAl9YYGg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.4.6': - resolution: {integrity: sha512-XP824mCbgQsK20jlXKrUpZoh/iO3vUWhMpxCz8oYeagoiZ4V0TQiKy0ASji1KK6IAe3DYGfj5RfKP6+L2020OQ==} + '@next/swc-linux-x64-musl@15.4.7': + resolution: {integrity: sha512-ceNbPjsFgLscYNGKSu4I6LYaadq2B8tcK116nVuInpHHdAWLWSwVK6CHNvCi0wVS9+TTArIFKJGsEyVD1H+4Kg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.4.6': - resolution: {integrity: sha512-FxrsenhUz0LbgRkNWx6FRRJIPe/MI1JRA4W4EPd5leXO00AZ6YU8v5vfx4MDXTvN77lM/EqsE3+6d2CIeF5NYg==} + '@next/swc-win32-arm64-msvc@15.4.7': + resolution: {integrity: sha512-pZyxmY1iHlZJ04LUL7Css8bNvsYAMYOY9JRwFA3HZgpaNKsJSowD09Vg2R9734GxAcLJc2KDQHSCR91uD6/AAw==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.4.6': - resolution: {integrity: sha512-T4ufqnZ4u88ZheczkBTtOF+eKaM14V8kbjud/XrAakoM5DKQWjW09vD6B9fsdsWS2T7D5EY31hRHdta7QKWOng==} + '@next/swc-win32-x64-msvc@15.4.7': + resolution: {integrity: sha512-HjuwPJ7BeRzgl3KrjKqD2iDng0eQIpIReyhpF5r4yeAHFwWRuAhfW92rWv/r3qeQHEwHsLRzFDvMqRjyM5DI6A==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -4548,8 +4548,8 @@ packages: isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - isbot@5.1.29: - resolution: {integrity: sha512-DelDWWoa3mBoyWTq3wjp+GIWx/yZdN7zLUE7NFhKjAiJ+uJVRkbLlwykdduCE4sPUUy8mlTYTmdhBUYu91F+sw==} + isbot@5.1.30: + resolution: {integrity: sha512-3wVJEonAns1OETX83uWsk5IAne2S5zfDcntD2hbtU23LelSqNXzXs9zKjMPOLMzroCgIjCfjYAEHrd2D6FOkiA==} engines: {node: '>=18'} isexe@2.0.0: @@ -4996,8 +4996,8 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - lucide-react@0.526.0: - resolution: {integrity: sha512-uGWG/2RKuDLeQHCodn5cmJ9Zij80EstOdcBP+j//B2sr78w7woiEL4aMu6CRlRkyOyJ8sZry8QLhQTmZjynLdA==} + lucide-react@0.540.0: + resolution: {integrity: sha512-armkCAqQvO62EIX4Hq7hqX/q11WSZu0Jd23cnnqx0/49yIxGXyL/zyZfBxNN9YDx0ensPTb4L+DjTh3yQXUxtQ==} peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -5177,8 +5177,8 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - next@15.4.6: - resolution: {integrity: sha512-us++E/Q80/8+UekzB3SAGs71AlLDsadpFMXVNM/uQ0BMwsh9m3mr0UNQIfjKed8vpWXsASe+Qifrnu1oLIcKEQ==} + next@15.4.7: + resolution: {integrity: sha512-OcqRugwF7n7mC8OSYjvsZhhG1AYSvulor1EIUsIkbbEbf1qoE5EbH36Swj8WhF4cHqmDgkiam3z1c1W0J1Wifg==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -8178,34 +8178,34 @@ snapshots: '@netlify/plugin-nextjs@5.12.0': {} - '@next/env@15.4.6': {} + '@next/env@15.4.7': {} '@next/eslint-plugin-next@14.2.31': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@15.4.6': + '@next/swc-darwin-arm64@15.4.7': optional: true - '@next/swc-darwin-x64@15.4.6': + '@next/swc-darwin-x64@15.4.7': optional: true - '@next/swc-linux-arm64-gnu@15.4.6': + '@next/swc-linux-arm64-gnu@15.4.7': optional: true - '@next/swc-linux-arm64-musl@15.4.6': + '@next/swc-linux-arm64-musl@15.4.7': optional: true - '@next/swc-linux-x64-gnu@15.4.6': + '@next/swc-linux-x64-gnu@15.4.7': optional: true - '@next/swc-linux-x64-musl@15.4.6': + '@next/swc-linux-x64-musl@15.4.7': optional: true - '@next/swc-win32-arm64-msvc@15.4.6': + '@next/swc-win32-arm64-msvc@15.4.7': optional: true - '@next/swc-win32-x64-msvc@15.4.6': + '@next/swc-win32-x64-msvc@15.4.7': optional: true '@nodelib/fs.scandir@2.1.5': @@ -9856,7 +9856,7 @@ snapshots: glob: 10.4.5 highlight.js: 11.11.1 lucide-react: 0.511.0(react@19.1.1) - next: 15.4.6(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + next: 15.4.7(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react: 19.1.1 react-aria-components: 1.9.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react-dom: 19.1.1(react@19.1.1) @@ -12128,7 +12128,7 @@ snapshots: isarray@2.0.5: {} - isbot@5.1.29: {} + isbot@5.1.30: {} isexe@2.0.0: {} @@ -12792,7 +12792,7 @@ snapshots: dependencies: react: 19.1.1 - lucide-react@0.526.0(react@19.1.1): + lucide-react@0.540.0(react@19.1.1): dependencies: react: 19.1.1 @@ -12959,9 +12959,9 @@ snapshots: neo-async@2.6.2: {} - next@15.4.6(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + next@15.4.7(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: - '@next/env': 15.4.6 + '@next/env': 15.4.7 '@swc/helpers': 0.5.15 caniuse-lite: 1.0.30001735 postcss: 8.4.31 @@ -12969,14 +12969,14 @@ snapshots: react-dom: 19.1.1(react@19.1.1) styled-jsx: 5.1.6(@babel/core@7.28.3)(react@19.1.1) optionalDependencies: - '@next/swc-darwin-arm64': 15.4.6 - '@next/swc-darwin-x64': 15.4.6 - '@next/swc-linux-arm64-gnu': 15.4.6 - '@next/swc-linux-arm64-musl': 15.4.6 - '@next/swc-linux-x64-gnu': 15.4.6 - '@next/swc-linux-x64-musl': 15.4.6 - '@next/swc-win32-arm64-msvc': 15.4.6 - '@next/swc-win32-x64-msvc': 15.4.6 + '@next/swc-darwin-arm64': 15.4.7 + '@next/swc-darwin-x64': 15.4.7 + '@next/swc-linux-arm64-gnu': 15.4.7 + '@next/swc-linux-arm64-musl': 15.4.7 + '@next/swc-linux-x64-gnu': 15.4.7 + '@next/swc-linux-x64-musl': 15.4.7 + '@next/swc-win32-arm64-msvc': 15.4.7 + '@next/swc-win32-x64-msvc': 15.4.7 babel-plugin-react-compiler: 19.1.0-rc.2 sharp: 0.34.3 transitivePeerDependencies: diff --git a/src/app/(collect)/q/[slug]/route.ts b/src/app/(collect)/q/[slug]/route.ts index e69de29b..4c0f683c 100644 --- a/src/app/(collect)/q/[slug]/route.ts +++ b/src/app/(collect)/q/[slug]/route.ts @@ -0,0 +1,37 @@ +import { NextResponse } from 'next/server'; +import { notFound } from '@/lib/response'; +import { findLink } from '@/queries'; +import { POST } from '@/app/api/send/route'; + +export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) { + const { slug } = await params; + + const link = await findLink({ + where: { + slug, + }, + }); + + if (!link) { + return notFound(); + } + + const payload = { + type: 'event', + payload: { + link: link.id, + url: request.url, + referrer: request.referrer, + }, + }; + + const req = new Request(request.url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + + await POST(req); + + return NextResponse.redirect(link.url); +} diff --git a/src/app/api/send/route.ts b/src/app/api/send/route.ts index 0b177f08..652ff4f0 100644 --- a/src/app/api/send/route.ts +++ b/src/app/api/send/route.ts @@ -257,9 +257,7 @@ export async function POST(request: Request) { lifatid, twclid, }); - } - - if (type === COLLECTION_TYPE.identify) { + } else if (type === COLLECTION_TYPE.identify) { if (data) { await saveSessionData({ websiteId, From 2f1f704728019eb168be0f860be00b68262e10a4 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Tue, 19 Aug 2025 15:26:41 -0700 Subject: [PATCH 168/399] implement filtering and cohorts to all relevant queries --- src/app/(main)/boards/BoardsPage.tsx | 2 +- src/app/(main)/links/LinksPage.tsx | 2 +- src/app/(main)/pixels/PixelsPage.tsx | 2 +- src/app/(main)/websites/WebsitesPage.tsx | 2 +- src/queries/sql/events/getEventDataFields.ts | 10 +- .../sql/events/getEventDataProperties.ts | 3 +- src/queries/sql/events/getEventDataStats.ts | 12 +- src/queries/sql/events/getEventDataValues.ts | 6 +- .../sql/events/getEventExpandedMetrics.ts | 1 - src/queries/sql/events/getEventMetrics.ts | 1 - src/queries/sql/events/getEventStats.ts | 1 - src/queries/sql/events/getWebsiteEvents.ts | 7 +- src/queries/sql/getChannelExpandedMetrics.ts | 4 +- src/queries/sql/getChannelMetrics.ts | 4 +- src/queries/sql/getRealtimeActivity.ts | 5 +- src/queries/sql/getWebsiteStats.ts | 5 +- .../pageviews/getPageviewExpandedMetrics.ts | 3 +- .../sql/pageviews/getPageviewMetrics.ts | 3 +- src/queries/sql/pageviews/getPageviewStats.ts | 5 +- src/queries/sql/reports/getAttribution.ts | 61 ++++-- src/queries/sql/reports/getBreakdown.ts | 5 +- src/queries/sql/reports/getFunnel.ts | 17 +- src/queries/sql/reports/getGoal.ts | 42 ++-- src/queries/sql/reports/getJourney.ts | 17 +- src/queries/sql/reports/getRetention.ts | 27 +-- src/queries/sql/reports/getRevenue.ts | 195 ++++++++++++------ src/queries/sql/reports/getUTM.ts | 3 +- .../sql/sessions/getSessionDataProperties.ts | 5 +- .../sql/sessions/getSessionDataValues.ts | 6 +- .../sql/sessions/getSessionExpandedMetrics.ts | 1 - src/queries/sql/sessions/getSessionMetrics.ts | 1 - src/queries/sql/sessions/getSessionStats.ts | 5 +- .../sql/sessions/getWebsiteSessionStats.ts | 5 +- .../sql/sessions/getWebsiteSessionsWeekly.ts | 10 +- 34 files changed, 311 insertions(+), 167 deletions(-) diff --git a/src/app/(main)/boards/BoardsPage.tsx b/src/app/(main)/boards/BoardsPage.tsx index 991ef965..adf0e02b 100644 --- a/src/app/(main)/boards/BoardsPage.tsx +++ b/src/app/(main)/boards/BoardsPage.tsx @@ -7,7 +7,7 @@ import { BoardAddButton } from './BoardAddButton'; export function BoardsPage() { return ( - + diff --git a/src/app/(main)/links/LinksPage.tsx b/src/app/(main)/links/LinksPage.tsx index 766974f5..e94bccf8 100644 --- a/src/app/(main)/links/LinksPage.tsx +++ b/src/app/(main)/links/LinksPage.tsx @@ -13,7 +13,7 @@ export function LinksPage() { return ( - + diff --git a/src/app/(main)/pixels/PixelsPage.tsx b/src/app/(main)/pixels/PixelsPage.tsx index 58ccb7d1..0733d5b1 100644 --- a/src/app/(main)/pixels/PixelsPage.tsx +++ b/src/app/(main)/pixels/PixelsPage.tsx @@ -13,7 +13,7 @@ export function PixelsPage() { return ( - + diff --git a/src/app/(main)/websites/WebsitesPage.tsx b/src/app/(main)/websites/WebsitesPage.tsx index db563147..313dccc7 100644 --- a/src/app/(main)/websites/WebsitesPage.tsx +++ b/src/app/(main)/websites/WebsitesPage.tsx @@ -13,7 +13,7 @@ export function WebsitesPage() { return ( - + diff --git a/src/queries/sql/events/getEventDataFields.ts b/src/queries/sql/events/getEventDataFields.ts index 91f9771e..1b76f0a0 100644 --- a/src/queries/sql/events/getEventDataFields.ts +++ b/src/queries/sql/events/getEventDataFields.ts @@ -1,6 +1,6 @@ -import prisma from '@/lib/prisma'; import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; +import prisma from '@/lib/prisma'; import { QueryFilters } from '@/lib/types'; export async function getEventDataFields(...args: [websiteId: string, filters: QueryFilters]) { @@ -12,7 +12,10 @@ export async function getEventDataFields(...args: [websiteId: string, filters: Q async function relationalQuery(websiteId: string, filters: QueryFilters) { const { rawQuery, parseFilters, getDateSQL } = prisma; - const { filterQuery, cohortQuery, queryParams } = parseFilters(filters); + const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + }); return rawQuery( ` @@ -30,6 +33,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { and website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} ${cohortQuery} + ${joinSessionQuery} where event_data.website_id = {{websiteId::uuid}} and event_data.created_at between {{startDate}} and {{endDate}} ${filterQuery} @@ -46,7 +50,7 @@ async function clickhouseQuery( filters: QueryFilters, ): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> { const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, cohortQuery, queryParams } = parseFilters(filters); + const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId }); return rawQuery( ` diff --git a/src/queries/sql/events/getEventDataProperties.ts b/src/queries/sql/events/getEventDataProperties.ts index 708abebf..7eccf594 100644 --- a/src/queries/sql/events/getEventDataProperties.ts +++ b/src/queries/sql/events/getEventDataProperties.ts @@ -17,7 +17,7 @@ async function relationalQuery( filters: QueryFilters & { propertyName?: string }, ) { const { rawQuery, parseFilters } = prisma; - const { filterQuery, cohortQuery, queryParams } = parseFilters( + const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters( { ...filters, websiteId }, { columns: { propertyName: 'data_key' }, @@ -35,6 +35,7 @@ async function relationalQuery( and website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} ${cohortQuery} + ${joinSessionQuery} where event_data.website_id = {{websiteId::uuid}} and event_data.created_at between {{startDate}} and {{endDate}} ${filterQuery} diff --git a/src/queries/sql/events/getEventDataStats.ts b/src/queries/sql/events/getEventDataStats.ts index 01b5db34..ea42be7c 100644 --- a/src/queries/sql/events/getEventDataStats.ts +++ b/src/queries/sql/events/getEventDataStats.ts @@ -18,7 +18,10 @@ export async function getEventDataStats( async function relationalQuery(websiteId: string, filters: QueryFilters) { const { rawQuery, parseFilters } = prisma; - const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId }); + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + }); return rawQuery( ` @@ -33,9 +36,10 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { count(*) as "total" from event_data join website_event on website_event.event_id = event_data.website_event_id - and website_event.website_id = {{websiteId::uuid}} - and website_event.created_at between {{startDate}} and {{endDate}} - ${cohortQuery} + and website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + ${cohortQuery} + ${joinSessionQuery} where event_data.website_id = {{websiteId::uuid}} and event_data.created_at between {{startDate}} and {{endDate}} ${filterQuery} diff --git a/src/queries/sql/events/getEventDataValues.ts b/src/queries/sql/events/getEventDataValues.ts index 1c30617c..a8f4b4a1 100644 --- a/src/queries/sql/events/getEventDataValues.ts +++ b/src/queries/sql/events/getEventDataValues.ts @@ -25,7 +25,10 @@ async function relationalQuery( filters: QueryFilters & { eventName?: string; propertyName?: string }, ) { const { rawQuery, parseFilters, getDateSQL } = prisma; - const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId }); + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + }); return rawQuery( ` @@ -41,6 +44,7 @@ async function relationalQuery( and website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} ${cohortQuery} + ${joinSessionQuery} where event_data.website_id = {{websiteId::uuid}} and event_data.created_at between {{startDate}} and {{endDate}} and event_data.data_key = {{propertyName}} diff --git a/src/queries/sql/events/getEventExpandedMetrics.ts b/src/queries/sql/events/getEventExpandedMetrics.ts index 235822b8..96a452fa 100644 --- a/src/queries/sql/events/getEventExpandedMetrics.ts +++ b/src/queries/sql/events/getEventExpandedMetrics.ts @@ -54,7 +54,6 @@ async function relationalQuery( ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and event_type = {{eventType}} ${filterQuery} group by 1 order by 2 desc diff --git a/src/queries/sql/events/getEventMetrics.ts b/src/queries/sql/events/getEventMetrics.ts index ad95e316..4ecfe2d5 100644 --- a/src/queries/sql/events/getEventMetrics.ts +++ b/src/queries/sql/events/getEventMetrics.ts @@ -51,7 +51,6 @@ async function relationalQuery( ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and event_type = {{eventType}} ${filterQuery} group by 1 order by 2 desc diff --git a/src/queries/sql/events/getEventStats.ts b/src/queries/sql/events/getEventStats.ts index 8d26dcfc..54afaaf5 100644 --- a/src/queries/sql/events/getEventStats.ts +++ b/src/queries/sql/events/getEventStats.ts @@ -39,7 +39,6 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and event_type = {{eventType}} ${filterQuery} group by 1, 2 order by 2 diff --git a/src/queries/sql/events/getWebsiteEvents.ts b/src/queries/sql/events/getWebsiteEvents.ts index 579593d6..b81ca970 100644 --- a/src/queries/sql/events/getWebsiteEvents.ts +++ b/src/queries/sql/events/getWebsiteEvents.ts @@ -31,6 +31,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { website_id as "websiteId", session_id as "sessionId", created_at as "createdAt", + hostname, url_path as "urlPath", url_query as "urlQuery", referrer_path as "referrerPath", @@ -46,6 +47,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { event_name as "eventName" from website_event ${cohortQuery} + join session on website_event.session_id = session.session_id where website_id = {{websiteId::uuid}} ${dateQuery} ${filterQuery} @@ -77,6 +79,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) { website_id as websiteId, session_id as sessionId, created_at as createdAt, + hostname, url_path as urlPath, url_query as urlQuery, referrer_path as referrerPath, @@ -84,13 +87,13 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) { referrer_domain as referrerDomain, country as country, city as city, - device as device, + device as device, os as os, browser as browser, page_title as pageTitle, event_type as eventType, event_name as eventName, - event_id IN (SELECT event_id FROM event_data) AS hasData + event_id IN (SELECT event_id FROM event_data) as hasData from website_event ${cohortQuery} where website_id = {websiteId:UUID} diff --git a/src/queries/sql/getChannelExpandedMetrics.ts b/src/queries/sql/getChannelExpandedMetrics.ts index e4ce08ab..51f5e37e 100644 --- a/src/queries/sql/getChannelExpandedMetrics.ts +++ b/src/queries/sql/getChannelExpandedMetrics.ts @@ -40,7 +40,7 @@ async function relationalQuery( filters: QueryFilters, ): Promise { const { rawQuery, parseFilters } = prisma; - const { queryParams, filterQuery, cohortQuery, dateQuery } = parseFilters({ + const { queryParams, filterQuery, joinSessionQuery, cohortQuery, dateQuery } = parseFilters({ ...filters, websiteId, eventType: EVENT_TYPE.pageView, @@ -65,8 +65,8 @@ async function relationalQuery( count(distinct session_id) y from website_event ${cohortQuery} + ${joinSessionQuery} where website_id = {{websiteId::uuid}} - and event_type = {{eventType}} ${dateQuery} ${filterQuery} group by 1, 2 diff --git a/src/queries/sql/getChannelMetrics.ts b/src/queries/sql/getChannelMetrics.ts index 9e6ba82c..a828dc8a 100644 --- a/src/queries/sql/getChannelMetrics.ts +++ b/src/queries/sql/getChannelMetrics.ts @@ -21,7 +21,7 @@ export async function getChannelMetrics(...args: [websiteId: string, filters?: Q async function relationalQuery(websiteId: string, filters: QueryFilters) { const { rawQuery, parseFilters } = prisma; - const { queryParams, filterQuery, cohortQuery, dateQuery } = parseFilters({ + const { queryParams, filterQuery, joinSessionQuery, cohortQuery, dateQuery } = parseFilters({ ...filters, websiteId, eventType: EVENT_TYPE.pageView, @@ -46,8 +46,8 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { count(distinct session_id) y from website_event ${cohortQuery} + ${joinSessionQuery} where website_id = {{websiteId::uuid}} - and event_type = {{eventType}} ${dateQuery} ${filterQuery} group by 1, 2 diff --git a/src/queries/sql/getRealtimeActivity.ts b/src/queries/sql/getRealtimeActivity.ts index d53cab6b..6ae72aa3 100644 --- a/src/queries/sql/getRealtimeActivity.ts +++ b/src/queries/sql/getRealtimeActivity.ts @@ -12,7 +12,10 @@ export async function getRealtimeActivity(...args: [websiteId: string, filters: async function relationalQuery(websiteId: string, filters: QueryFilters) { const { rawQuery, parseFilters } = prisma; - const { queryParams, filterQuery, cohortQuery, dateQuery } = parseFilters(filters); + const { queryParams, filterQuery, cohortQuery, dateQuery } = parseFilters({ + ...filters, + websiteId, + }); return rawQuery( ` diff --git a/src/queries/sql/getWebsiteStats.ts b/src/queries/sql/getWebsiteStats.ts index 4fa15a3c..925c4081 100644 --- a/src/queries/sql/getWebsiteStats.ts +++ b/src/queries/sql/getWebsiteStats.ts @@ -49,11 +49,10 @@ async function relationalQuery( min(website_event.created_at) as "min_time", max(website_event.created_at) as "max_time" from website_event - ${joinSessionQuery} - ${cohortQuery} + ${cohortQuery} + ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and event_type = {{eventType}} ${filterQuery} group by 1, 2 ) as t diff --git a/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts b/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts index ce1f1df9..3d0e2f8c 100644 --- a/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts +++ b/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts @@ -76,12 +76,11 @@ async function relationalQuery( select ${column} x, count(distinct website_event.session_id) as y from website_event - ${joinSessionQuery} ${cohortQuery} + ${joinSessionQuery} ${entryExitQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and event_type = {{eventType}} ${excludeDomain} ${filterQuery} group by 1 diff --git a/src/queries/sql/pageviews/getPageviewMetrics.ts b/src/queries/sql/pageviews/getPageviewMetrics.ts index 8d73c6f0..a5b13733 100644 --- a/src/queries/sql/pageviews/getPageviewMetrics.ts +++ b/src/queries/sql/pageviews/getPageviewMetrics.ts @@ -73,12 +73,11 @@ async function relationalQuery( select ${column} x, count(distinct website_event.session_id) as y from website_event - ${joinSessionQuery} ${cohortQuery} + ${joinSessionQuery} ${entryExitQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and event_type = {{eventType}} ${excludeDomain} ${filterQuery} group by 1 diff --git a/src/queries/sql/pageviews/getPageviewStats.ts b/src/queries/sql/pageviews/getPageviewStats.ts index e9e763e8..a8ee4734 100644 --- a/src/queries/sql/pageviews/getPageviewStats.ts +++ b/src/queries/sql/pageviews/getPageviewStats.ts @@ -26,11 +26,10 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { ${getDateSQL('website_event.created_at', unit, timezone)} x, count(*) y from website_event - ${joinSessionQuery} - ${cohortQuery} + ${cohortQuery} + ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and event_type = {{eventType}} ${filterQuery} group by 1 order by 1 diff --git a/src/queries/sql/reports/getAttribution.ts b/src/queries/sql/reports/getAttribution.ts index 0bfbd58b..b4df4d11 100644 --- a/src/queries/sql/reports/getAttribution.ts +++ b/src/queries/sql/reports/getAttribution.ts @@ -42,9 +42,10 @@ async function relationalQuery( const { rawQuery, parseFilters } = prisma; const eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent; const column = type === 'page' ? 'url_path' : 'event_name'; - const { filterQuery, queryParams } = parseFilters({ + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ ...filters, ...parameters, + websiteId, eventType, }); @@ -71,23 +72,32 @@ async function relationalQuery( session_id, max(created_at) max_dt from website_event + ${cohortQuery} + ${joinSessionQuery} where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} and ${column} = {{step}} - and event_type = {{eventType}} ${filterQuery} group by 1),`; const revenueEventQuery = `WITH events AS ( select - session_id, - max(created_at) max_dt, - sum(revenue) value + revenue.session_id, + max(revenue.created_at) max_dt, + sum(revenue.revenue) value from revenue - where website_id = {{websiteId::uuid}} - and created_at between {{startDate}} and {{endDate}} - and ${column} = {{step}} - and currency = {{currency}} + join website_event + on website_event.website_id = revenue.website_id + and website_event.session_id = revenue.session_id + and website_event.event_id = revenue.event_id + and website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + ${cohortQuery} + ${joinSessionQuery} + where revenue.website_id = {{websiteId::uuid}} + and revenue.created_at between {{startDate}} and {{endDate}} + and revenue.${column} = {{step}} + and revenue.currency = {{currency}} ${filterQuery} group by 1),`; @@ -227,10 +237,11 @@ async function relationalQuery( count(distinct session_id) as "visitors", count(distinct visit_id) as "visits" from website_event + ${joinSessionQuery} + ${cohortQuery} where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} and ${column} = {{step}} - and event_type = {{eventType}} ${filterQuery} `, queryParams, @@ -257,7 +268,7 @@ async function clickhouseQuery( const { rawQuery, parseFilters } = clickhouse; const eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent; const column = type === 'page' ? 'url_path' : 'event_name'; - const { filterQuery, queryParams } = parseFilters({ + const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, ...parameters, websiteId, @@ -293,7 +304,6 @@ async function clickhouseQuery( on we.session_id = e.session_id where we.website_id = {websiteId:UUID} and we.created_at between {startDate:DateTime64} and {endDate:DateTime64} - ${filterQuery} group by e.session_id) `; } @@ -307,7 +317,6 @@ async function clickhouseQuery( where we.website_id = {websiteId:UUID} and we.created_at between {startDate:DateTime64} and {endDate:DateTime64} and we.created_at < e.max_dt - ${filterQuery} group by e.session_id) `; } @@ -317,22 +326,31 @@ async function clickhouseQuery( session_id, max(created_at) max_dt from website_event + ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} and ${column} = {step:String} - and event_type = {eventType:UInt32} + ${filterQuery} group by 1),`; const revenueEventQuery = `WITH events AS ( select - session_id, - max(created_at) max_dt, - sum(revenue) as value + website_revenue.session_id, + max(website_revenue.created_at) max_dt, + sum(website_revenue.revenue) as value from website_revenue - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and ${column} = {step:String} - and currency = {currency:String} + join website_event + on website_event.website_id = website_revenue.website_id + and website_event.session_id = website_revenue.session_id + and website_event.event_id = website_revenue.event_id + and website_event.website_id = {websiteId:UUID} + and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} + ${cohortQuery} + where website_revenue.website_id = {websiteId:UUID} + and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and website_revenue.${column} = {step:String} + and website_revenue.currency = {currency:String} + ${filterQuery} group by 1),`; const referrerRes = await rawQuery< @@ -474,6 +492,7 @@ async function clickhouseQuery( uniqExact(session_id) as "visitors", uniqExact(visit_id) as "visits" from website_event + ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} and ${column} = {step:String} diff --git a/src/queries/sql/reports/getBreakdown.ts b/src/queries/sql/reports/getBreakdown.ts index 7cae67a1..6cea68f3 100644 --- a/src/queries/sql/reports/getBreakdown.ts +++ b/src/queries/sql/reports/getBreakdown.ts @@ -62,11 +62,10 @@ async function relationalQuery( min(website_event.created_at) as "min_time", max(website_event.created_at) as "max_time" from website_event - ${cohortQuery} - ${joinSessionQuery} + ${cohortQuery} + ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and event_type = {{eventType}} ${filterQuery} group by ${parseFieldsByName(fields)}, website_event.session_id, website_event.visit_id diff --git a/src/queries/sql/reports/getFunnel.ts b/src/queries/sql/reports/getFunnel.ts index 9065b609..81e2f3bb 100644 --- a/src/queries/sql/reports/getFunnel.ts +++ b/src/queries/sql/reports/getFunnel.ts @@ -34,7 +34,12 @@ async function relationalQuery( const { rawQuery, getAddIntervalQuery, parseFilters } = prisma; const { levelOneQuery, levelQuery, sumQuery, params } = getFunnelQuery(steps, window); - const { filterQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, endDate }); + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + startDate, + endDate, + }); function getFunnelQuery( steps: { type: string; value: string }[], @@ -65,6 +70,8 @@ async function relationalQuery( WITH level1 AS ( select distinct session_id, created_at from website_event + ${cohortQuery} + ${joinSessionQuery} where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} and ${column} ${operator} {{${i}}} @@ -132,7 +139,12 @@ async function clickhouseQuery( steps, window, ); - const { filterQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, endDate }); + const { filterQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + startDate, + endDate, + }); function getFunnelQuery( steps: { type: string; value: string }[], @@ -204,6 +216,7 @@ async function clickhouseQuery( WITH level0 AS ( select distinct session_id, url_path, referrer_path, event_name, created_at from website_event + ${cohortQuery} where (${stepFilterQuery}) and website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} diff --git a/src/queries/sql/reports/getGoal.ts b/src/queries/sql/reports/getGoal.ts index c659bb47..3ecce7ac 100644 --- a/src/queries/sql/reports/getGoal.ts +++ b/src/queries/sql/reports/getGoal.ts @@ -1,4 +1,5 @@ import clickhouse from '@/lib/clickhouse'; +import { EVENT_TYPE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import { QueryFilters } from '@/lib/types'; @@ -28,16 +29,16 @@ async function relationalQuery( ) { const { startDate, endDate, type, value } = parameters; const { rawQuery, parseFilters } = prisma; - const { filterQuery, dateQuery, queryParams } = parseFilters({ + const eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent; + const column = type === 'page' ? 'url_path' : 'event_name'; + const { filterQuery, dateQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, value, startDate, endDate, + eventType, }); - const isPage = type === 'page'; - const column = isPage ? 'url_path' : 'event_name'; - const eventType = isPage ? 1 : 2; return rawQuery( ` @@ -45,16 +46,19 @@ async function relationalQuery( ( select count(distinct session_id) from website_event + ${cohortQuery} + ${joinSessionQuery} where website_id = {websiteId:UUID} - and event_type = ${eventType} ${dateQuery} + ${filterQuery} ) as total from website_event + ${cohortQuery} + ${joinSessionQuery} where website_id = {websiteId:UUID} - and event_type = ${eventType} - and ${column} = {value:String} - ${dateQuery} - ${filterQuery} + and ${column} = {value:String} + ${dateQuery} + ${filterQuery} `, queryParams, ); @@ -67,16 +71,16 @@ async function clickhouseQuery( ) { const { startDate, endDate, type, value } = parameters; const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, dateQuery, queryParams } = parseFilters({ + const eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent; + const column = type === 'page' ? 'url_path' : 'event_name'; + const { filterQuery, dateQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, value, startDate, endDate, + eventType, }); - const isPage = type === 'page'; - const column = isPage ? 'url_path' : 'event_name'; - const eventType = isPage ? 1 : 2; return rawQuery( ` @@ -84,15 +88,17 @@ async function clickhouseQuery( ( select count(distinct session_id) from website_event + ${cohortQuery} where website_id = {websiteId:UUID} - ${dateQuery} + ${dateQuery} + ${filterQuery} ) as total from website_event + ${cohortQuery} where website_id = {websiteId:UUID} - and event_type = ${eventType} - and ${column} = {value:String} - ${dateQuery} - ${filterQuery} + and ${column} = {value:String} + ${dateQuery} + ${filterQuery} `, queryParams, ).then(results => results?.[0]); diff --git a/src/queries/sql/reports/getJourney.ts b/src/queries/sql/reports/getJourney.ts index e7ab14ad..3ed4acc9 100644 --- a/src/queries/sql/reports/getJourney.ts +++ b/src/queries/sql/reports/getJourney.ts @@ -43,7 +43,12 @@ async function relationalQuery( startStep, endStep, ); - const { filterQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, endDate }); + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + startDate, + endDate, + }); function getJourneyQuery( steps: number, @@ -117,6 +122,8 @@ async function relationalQuery( coalesce(nullIf(event_name, ''), url_path) event, row_number() OVER (PARTITION BY visit_id ORDER BY created_at) AS event_number from website_event + ${cohortQuery} + ${joinSessionQuery} where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}}), ${filterQuery} @@ -148,7 +155,12 @@ async function clickhouseQuery( startStep, endStep, ); - const { filterQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, endDate }); + const { filterQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + startDate, + endDate, + }); function getJourneyQuery( steps: number, @@ -221,6 +233,7 @@ async function clickhouseQuery( coalesce(nullIf(event_name, ''), url_path) event, row_number() OVER (PARTITION BY visit_id ORDER BY created_at) AS event_number from website_event + ${cohortQuery} where website_id = {websiteId:UUID} ${filterQuery} and created_at between {startDate:DateTime64} and {endDate:DateTime64}), diff --git a/src/queries/sql/reports/getRetention.ts b/src/queries/sql/reports/getRetention.ts index c552ae45..67c373f8 100644 --- a/src/queries/sql/reports/getRetention.ts +++ b/src/queries/sql/reports/getRetention.ts @@ -35,7 +35,7 @@ async function relationalQuery( const { getDateSQL, getDayDiffQuery, getCastColumnQuery, rawQuery, parseFilters } = prisma; const unit = 'day'; - const { filterQuery, queryParams } = parseFilters({ + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, @@ -54,11 +54,13 @@ async function relationalQuery( ), user_activities AS ( select distinct - w.session_id, - ${getDayDiffQuery(getDateSQL('created_at', unit, timezone), 'c.cohort_date')} as day_number - from website_event w - join cohort_items c - on w.session_id = c.session_id + website_event.session_id, + ${getDayDiffQuery(getDateSQL('created_at', unit, timezone), 'cohort_items.cohort_date')} as day_number + from website_event + join cohort_items + on website_event.session_id = cohort_items.session_id + ${cohortQuery} + ${joinSessionQuery} where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} ${filterQuery} @@ -104,7 +106,7 @@ async function clickhouseQuery( const { getDateSQL, rawQuery, parseFilters } = clickhouse; const unit = 'day'; - const { filterQuery, queryParams } = parseFilters({ + const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, @@ -125,11 +127,12 @@ async function clickhouseQuery( ), user_activities AS ( select distinct - w.session_id, - (${getDateSQL('created_at', unit, timezone)} - c.cohort_date) / 86400 as day_number - from website_event w - join cohort_items c - on w.session_id = c.session_id + website_event.session_id, + (${getDateSQL('created_at', unit, timezone)} - cohort_items.cohort_date) / 86400 as day_number + from website_event + join cohort_items + on website_event.session_id = cohort_items.session_id + ${cohortQuery} where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} ${filterQuery} diff --git a/src/queries/sql/reports/getRevenue.ts b/src/queries/sql/reports/getRevenue.ts index 20d77297..f5c652aa 100644 --- a/src/queries/sql/reports/getRevenue.ts +++ b/src/queries/sql/reports/getRevenue.ts @@ -38,18 +38,33 @@ async function relationalQuery( ): Promise { const { startDate, endDate, currency, unit = 'day' } = parameters; const { getDateSQL, rawQuery, parseFilters } = prisma; - const { queryParams } = parseFilters({ ...filters, websiteId, startDate, endDate, currency }); + const { queryParams, filterQuery, cohortQuery, joinSessionQuery } = parseFilters({ + ...filters, + websiteId, + startDate, + endDate, + currency, + }); const chart = await rawQuery( ` select - event_name x, - ${getDateSQL('created_at', unit)} t, - sum(revenue) y + revenue.event_name x, + ${getDateSQL('revenue.created_at', unit)} t, + sum(revenue.revenue) y from revenue - where website_id = {{websiteId::uuid}} - and created_at between {{startDate}} and {{endDate}} - and currency like {{currency}} + join website_event + on website_event.website_id = revenue.website_id + and website_event.session_id = revenue.session_id + and website_event.event_id = revenue.event_id + and website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + ${cohortQuery} + ${joinSessionQuery} + where revenue.website_id = {{websiteId::uuid}} + and revenue.created_at between {{startDate}} and {{endDate}} + and revenue.currency like {{currency}} + ${filterQuery} group by x, t order by t `, @@ -59,15 +74,24 @@ async function relationalQuery( const country = await rawQuery( ` select - s.country as name, + session.country as name, sum(r.revenue) value - from revenue r - join session s - on s.session_id = r.session_id - where r.website_id = {{websiteId::uuid}} - and r.created_at between {{startDate}} and {{endDate}} - and r.currency = {{currency}} - group by s.country + from revenue + join website_event + on website_event.website_id = revenue.website_id + and website_event.session_id = revenue.session_id + and website_event.event_id = revenue.event_id + and website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + join session + on session.website_id = revenue.website_id + and session.session_id = revenue.session_id + ${cohortQuery} + where revenue.website_id = {{websiteId::uuid}} + and revenue.created_at between {{startDate}} and {{endDate}} + and revenue.currency = {{currency}} + ${filterQuery} + group by session.country `, queryParams, ); @@ -75,13 +99,22 @@ async function relationalQuery( const total = await rawQuery( ` select - sum(revenue) as sum, - count(distinct event_id) as count, - count(distinct session_id) as unique_count - from revenue r - where website_id = {{websiteId::uuid}} - and created_at between {{startDate}} and {{endDate}} - and currency = {{currency}} + sum(revenue.revenue) as sum, + count(distinct revenue.event_id) as count, + count(distinct revenue.session_id) as unique_count + from revenue + join website_event + on website_event.website_id = revenue.website_id + and website_event.session_id = revenue.session_id + and website_event.event_id = revenue.event_id + and website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + ${cohortQuery} + ${joinSessionQuery} + where revenue.website_id = {{websiteId::uuid}} + and revenue.created_at between {{startDate}} and {{endDate}} + and revenue.currency = {{currency}} + ${filterQuery} `, queryParams, ).then(result => result?.[0]); @@ -91,14 +124,23 @@ async function relationalQuery( const table = await rawQuery( ` select - currency, - sum(revenue) as sum, - count(distinct event_id) as count, - count(distinct session_id) as unique_count - from revenue r - where website_id = {{websiteId::uuid}} - and created_at between {{startDate}} and {{endDate}} - group by currency + revenue.currency, + sum(revenue.revenue) as sum, + count(distinct revenue.event_id) as count, + count(distinct revenue.session_id) as unique_count + from revenue + join website_event + on website_event.website_id = revenue.website_id + and website_event.session_id = revenue.session_id + and website_event.event_id = revenue.event_id + and website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + ${cohortQuery} + ${joinSessionQuery} + where revenue.website_id = {{websiteId::uuid}} + and revenue.created_at between {{startDate}} and {{endDate}} + ${filterQuery} + group by revenue.currency order by sum desc `, queryParams, @@ -114,7 +156,7 @@ async function clickhouseQuery( ): Promise { const { startDate, endDate, unit = 'day', currency } = parameters; const { getDateSQL, rawQuery, parseFilters } = clickhouse; - const { queryParams } = parseFilters({ + const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, @@ -131,13 +173,21 @@ async function clickhouseQuery( >( ` select - event_name x, - ${getDateSQL('created_at', unit)} t, - sum(revenue) y + website_revenue.event_name x, + ${getDateSQL('website_revenue.created_at', unit)} t, + sum(website_revenue.revenue) y from website_revenue - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and currency = {currency:String} + join website_event + on website_event.website_id = website_revenue.website_id + and website_event.session_id = website_revenue.session_id + and website_event.event_id = website_revenue.event_id + and website_event.website_id = {websiteId:UUID} + and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} + ${cohortQuery} + where website_revenue.website_id = {websiteId:UUID} + and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and website_revenue.currency = {currency:String} + ${filterQuery} group by x, t order by t `, @@ -152,20 +202,21 @@ async function clickhouseQuery( >( ` select - s.country as name, - sum(w.revenue) as value - from website_revenue w - join ( - select distinct website_id, session_id, country - from website_event - where website_id = {websiteId:UUID} - ) s - on w.website_id = s.website_id - and w.session_id = s.session_id - where w.website_id = {websiteId:UUID} - and w.created_at between {startDate:DateTime64} and {endDate:DateTime64} - and w.currency = {currency:String} - group by s.country + website_event.country as name, + sum(website_revenue.revenue) as value + from website_revenue + join website_event + on website_event.website_id = website_revenue.website_id + and website_event.session_id = website_revenue.session_id + and website_event.event_id = website_revenue.event_id + and website_event.website_id = {websiteId:UUID} + and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} + ${cohortQuery} + where website_revenue.website_id = {websiteId:UUID} + and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and website_revenue.currency = {currency:String} + ${filterQuery} + group by website_event.country `, queryParams, ); @@ -177,13 +228,21 @@ async function clickhouseQuery( }>( ` select - sum(revenue) as sum, - uniqExact(event_id) as count, - uniqExact(session_id) as unique_count + sum(website_revenue.revenue) as sum, + uniqExact(website_revenue.event_id) as count, + uniqExact(website_revenue.session_id) as unique_count from website_revenue - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and currency = {currency:String} + join website_event + on website_event.website_id = website_revenue.website_id + and website_event.session_id = website_revenue.session_id + and website_event.event_id = website_revenue.event_id + and website_event.website_id = {websiteId:UUID} + and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} + ${cohortQuery} + where website_revenue.website_id = {websiteId:UUID} + and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and website_revenue.currency = {currency:String} + ${filterQuery} `, queryParams, ).then(result => result?.[0]); @@ -200,14 +259,22 @@ async function clickhouseQuery( >( ` select - currency, - sum(revenue) as sum, - uniqExact(event_id) as count, - uniqExact(session_id) as unique_count + website_revenue.currency, + sum(website_revenue.revenue) as sum, + uniqExact(website_revenue.event_id) as count, + uniqExact(website_revenue.session_id) as unique_count from website_revenue - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - group by currency + join website_event + on website_event.website_id = website_revenue.website_id + and website_event.session_id = website_revenue.session_id + and website_event.event_id = website_revenue.event_id + and website_event.website_id = {websiteId:UUID} + and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} + ${cohortQuery} + where website_revenue.website_id = {websiteId:UUID} + and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} + ${filterQuery} + group by website_revenue.currency order by sum desc `, queryParams, diff --git a/src/queries/sql/reports/getUTM.ts b/src/queries/sql/reports/getUTM.ts index fbf98021..61a3c042 100644 --- a/src/queries/sql/reports/getUTM.ts +++ b/src/queries/sql/reports/getUTM.ts @@ -27,7 +27,7 @@ async function relationalQuery( const { column, startDate, endDate } = parameters; const { parseFilters, rawQuery } = prisma; - const { filterQuery, cohortQuery, queryParams } = parseFilters({ + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, @@ -40,6 +40,7 @@ async function relationalQuery( select ${column} utm, count(*) as views from website_event ${cohortQuery} + ${joinSessionQuery} where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} and coalesce(${column}, '') != '' diff --git a/src/queries/sql/sessions/getSessionDataProperties.ts b/src/queries/sql/sessions/getSessionDataProperties.ts index ed2bc3e4..d72a0480 100644 --- a/src/queries/sql/sessions/getSessionDataProperties.ts +++ b/src/queries/sql/sessions/getSessionDataProperties.ts @@ -17,7 +17,7 @@ async function relationalQuery( filters: QueryFilters & { propertyName?: string }, ) { const { rawQuery, parseFilters } = prisma; - const { filterQuery, cohortQuery, queryParams } = parseFilters( + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters( { ...filters, websiteId }, { columns: { propertyName: 'data_key' }, @@ -30,7 +30,8 @@ async function relationalQuery( data_key as "propertyName", count(distinct session_data.session_id) as "total" from website_event - ${cohortQuery} + ${cohortQuery} + ${joinSessionQuery} join session_data on session_data.session_id = website_event.session_id where website_event.website_id = {{websiteId::uuid}} diff --git a/src/queries/sql/sessions/getSessionDataValues.ts b/src/queries/sql/sessions/getSessionDataValues.ts index e4d04f1a..9ff3cb45 100644 --- a/src/queries/sql/sessions/getSessionDataValues.ts +++ b/src/queries/sql/sessions/getSessionDataValues.ts @@ -17,7 +17,10 @@ async function relationalQuery( filters: QueryFilters & { propertyName?: string }, ) { const { rawQuery, parseFilters, getDateSQL } = prisma; - const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId }); + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + }); return rawQuery( ` @@ -30,6 +33,7 @@ async function relationalQuery( count(distinct session_data.session_id) as "total" from website_event ${cohortQuery} + ${joinSessionQuery} join session_data on session_data.session_id = website_event.session_id where website_event.website_id = {{websiteId::uuid}} diff --git a/src/queries/sql/sessions/getSessionExpandedMetrics.ts b/src/queries/sql/sessions/getSessionExpandedMetrics.ts index 7c6d98f6..56dba66e 100644 --- a/src/queries/sql/sessions/getSessionExpandedMetrics.ts +++ b/src/queries/sql/sessions/getSessionExpandedMetrics.ts @@ -63,7 +63,6 @@ async function relationalQuery( ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and website_event.event_type = {{eventType}} ${filterQuery} group by 1 ${includeCountry ? ', 3' : ''} diff --git a/src/queries/sql/sessions/getSessionMetrics.ts b/src/queries/sql/sessions/getSessionMetrics.ts index 725c7379..9af82636 100644 --- a/src/queries/sql/sessions/getSessionMetrics.ts +++ b/src/queries/sql/sessions/getSessionMetrics.ts @@ -54,7 +54,6 @@ async function relationalQuery( ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and website_event.event_type = {{eventType}} ${filterQuery} group by 1 ${includeCountry ? ', 3' : ''} diff --git a/src/queries/sql/sessions/getSessionStats.ts b/src/queries/sql/sessions/getSessionStats.ts index 497dc80d..62ef4480 100644 --- a/src/queries/sql/sessions/getSessionStats.ts +++ b/src/queries/sql/sessions/getSessionStats.ts @@ -26,11 +26,10 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { ${getDateSQL('website_event.created_at', unit, timezone)} x, count(distinct website_event.session_id) y from website_event - ${joinSessionQuery} - ${cohortQuery} + ${cohortQuery} + ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} - and event_type = {{eventType}} ${filterQuery} group by 1 order by 1 diff --git a/src/queries/sql/sessions/getWebsiteSessionStats.ts b/src/queries/sql/sessions/getWebsiteSessionStats.ts index 5718037f..804a483b 100644 --- a/src/queries/sql/sessions/getWebsiteSessionStats.ts +++ b/src/queries/sql/sessions/getWebsiteSessionStats.ts @@ -26,7 +26,10 @@ async function relationalQuery( filters: QueryFilters, ): Promise { const { parseFilters, rawQuery } = prisma; - const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId }); + const { filterQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + }); return rawQuery( ` diff --git a/src/queries/sql/sessions/getWebsiteSessionsWeekly.ts b/src/queries/sql/sessions/getWebsiteSessionsWeekly.ts index 89596737..9bae5425 100644 --- a/src/queries/sql/sessions/getWebsiteSessionsWeekly.ts +++ b/src/queries/sql/sessions/getWebsiteSessionsWeekly.ts @@ -14,9 +14,12 @@ export async function getWebsiteSessionsWeekly( } async function relationalQuery(websiteId: string, filters: QueryFilters) { - const { timezone = 'utc' } = filters; + const timezone = 'utc'; const { rawQuery, getDateWeeklySQL, parseFilters } = prisma; - const { queryParams } = parseFilters(filters); + const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({ + ...filters, + websiteId, + }); return rawQuery( ` @@ -24,8 +27,11 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { ${getDateWeeklySQL('created_at', timezone)} as time, count(distinct session_id) as value from website_event + ${cohortQuery} + ${joinSessionQuery} where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} + ${filterQuery} group by time order by 2 `, From 65024d4bf7223b4dcf00745b78b4865c804c9147 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Tue, 19 Aug 2025 16:20:21 -0700 Subject: [PATCH 169/399] fix search for segments, fix hooks endpoint for cohorts --- .../(reports)/revenue/RevenuePage.tsx | 2 +- .../cohorts/CohortDeleteButton.tsx | 2 +- .../websites/[websiteId]/segments/route.ts | 6 ++- .../hooks/queries/useWebsiteCohortsQuery.ts | 2 +- .../hooks/queries/useWebsiteSegmentsQuery.ts | 3 +- src/queries/prisma/segment.ts | 38 +++++++++++++++++-- 6 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/app/(main)/websites/[websiteId]/(reports)/revenue/RevenuePage.tsx b/src/app/(main)/websites/[websiteId]/(reports)/revenue/RevenuePage.tsx index 9232d7be..19ac89db 100644 --- a/src/app/(main)/websites/[websiteId]/(reports)/revenue/RevenuePage.tsx +++ b/src/app/(main)/websites/[websiteId]/(reports)/revenue/RevenuePage.tsx @@ -11,7 +11,7 @@ export function RevenuePage({ websiteId }: { websiteId: string }) { return ( - + ); diff --git a/src/app/(main)/websites/[websiteId]/cohorts/CohortDeleteButton.tsx b/src/app/(main)/websites/[websiteId]/cohorts/CohortDeleteButton.tsx index c7e6d679..043b51f9 100644 --- a/src/app/(main)/websites/[websiteId]/cohorts/CohortDeleteButton.tsx +++ b/src/app/(main)/websites/[websiteId]/cohorts/CohortDeleteButton.tsx @@ -19,7 +19,7 @@ export function CohortDeleteButton({ const { formatMessage, labels } = useMessages(); const { del, useMutation } = useApi(); const { mutate, isPending, error } = useMutation({ - mutationFn: () => del(`/websites/${websiteId}/cohorts/${cohortId}`), + mutationFn: () => del(`/websites/${websiteId}/segments/${cohortId}`), }); const { touch } = useModified(); diff --git a/src/app/api/websites/[websiteId]/segments/route.ts b/src/app/api/websites/[websiteId]/segments/route.ts index ed89e55f..75d99289 100644 --- a/src/app/api/websites/[websiteId]/segments/route.ts +++ b/src/app/api/websites/[websiteId]/segments/route.ts @@ -1,6 +1,6 @@ import { canUpdateWebsite, canViewWebsite } from '@/validations'; import { uuid } from '@/lib/crypto'; -import { parseRequest } from '@/lib/request'; +import { getQueryFilters, parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; import { segmentTypeParam, searchParams } from '@/lib/schema'; import { createSegment, getWebsiteSegments } from '@/queries'; @@ -28,7 +28,9 @@ export async function GET( return unauthorized(); } - const segments = await getWebsiteSegments(websiteId, type); + const filters = await getQueryFilters(query); + + const segments = await getWebsiteSegments(websiteId, type, filters); return json(segments); } diff --git a/src/components/hooks/queries/useWebsiteCohortsQuery.ts b/src/components/hooks/queries/useWebsiteCohortsQuery.ts index d20d4465..f769df23 100644 --- a/src/components/hooks/queries/useWebsiteCohortsQuery.ts +++ b/src/components/hooks/queries/useWebsiteCohortsQuery.ts @@ -16,7 +16,7 @@ export function useWebsiteCohortsQuery( return useQuery({ queryKey: ['website:cohorts', { websiteId, modified, ...filters, ...params }], queryFn: pageParams => { - return get(`/websites/${websiteId}/cohorts`, { ...pageParams, ...filters, ...params }); + return get(`/websites/${websiteId}/segments`, { ...pageParams, ...filters, ...params }); }, enabled: !!websiteId, placeholderData: keepPreviousData, diff --git a/src/components/hooks/queries/useWebsiteSegmentsQuery.ts b/src/components/hooks/queries/useWebsiteSegmentsQuery.ts index 6b4f2bc4..4a556822 100644 --- a/src/components/hooks/queries/useWebsiteSegmentsQuery.ts +++ b/src/components/hooks/queries/useWebsiteSegmentsQuery.ts @@ -15,7 +15,8 @@ export function useWebsiteSegmentsQuery( return useQuery({ queryKey: ['website:segments', { websiteId, modified, ...filters, ...params }], - queryFn: () => get(`/websites/${websiteId}/segments`, { ...filters, ...params }), + queryFn: pageParams => + get(`/websites/${websiteId}/segments`, { ...pageParams, ...filters, ...params }), enabled: !!websiteId, placeholderData: keepPreviousData, ...options, diff --git a/src/queries/prisma/segment.ts b/src/queries/prisma/segment.ts index f4e3b355..60c64b3a 100644 --- a/src/queries/prisma/segment.ts +++ b/src/queries/prisma/segment.ts @@ -1,5 +1,6 @@ import prisma from '@/lib/prisma'; import { Prisma, Segment } from '@/generated/prisma/client'; +import { PageResult, QueryFilters } from '@/lib/types'; async function findSegment(criteria: Prisma.SegmentFindUniqueArgs): Promise { return prisma.client.Segment.findUnique(criteria); @@ -13,16 +14,45 @@ export async function getSegment(segmentId: string): Promise { }); } +export async function getSegments( + criteria: Prisma.SegmentFindManyArgs, + filters: QueryFilters, +): Promise> { + const { search } = filters; + const { getSearchParameters, pagedQuery } = prisma; + + const where: Prisma.SegmentWhereInput = { + ...criteria.where, + ...getSearchParameters(search, [ + { + name: 'contains', + }, + ]), + }; + + return pagedQuery('segment', { ...criteria, where }, filters); +} + export async function getWebsiteSegment(websiteId: string, segmentId: string): Promise { return prisma.client.Segment.findFirst({ where: { id: segmentId, websiteId }, }); } -export async function getWebsiteSegments(websiteId: string, type: string): Promise { - return prisma.pagedQuery('segment', { - where: { websiteId, type }, - }); +export async function getWebsiteSegments( + websiteId: string, + type: string, + filters?: QueryFilters, +): Promise> { + return getSegments( + { + where: { + websiteId, + type, + }, + }, + filters, + ); } export async function createSegment(data: Prisma.SegmentUncheckedCreateInput): Promise { From 8e766e2db7da410c10ce525737f93eede2bd2898 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 21 Aug 2025 01:33:20 -0700 Subject: [PATCH 170/399] Pixel/link metrics pages. --- .../admin/teams/[teamId]/AdminTeamPage.tsx | 2 +- .../websites/[websiteId]/AdminWebsitePage.tsx | 2 +- src/app/(main)/links/LinkEditForm.tsx | 5 +- src/app/(main)/links/LinkProvider.tsx | 20 ++++++ src/app/(main)/links/LinksTable.tsx | 17 +++-- .../(main)/links/[linkId]/LinkControls.tsx | 34 +++++++++ src/app/(main)/links/[linkId]/LinkHeader.tsx | 22 ++++++ .../(main)/links/[linkId]/LinkMetricsBar.tsx | 71 +++++++++++++++++++ src/app/(main)/links/[linkId]/LinkPage.tsx | 59 +++++++++++++++ src/app/(main)/links/[linkId]/page.tsx | 12 ++++ src/app/(main)/pixels/PixelEditForm.tsx | 5 +- src/app/(main)/pixels/PixelProvider.tsx | 20 ++++++ src/app/(main)/pixels/PixelsTable.tsx | 16 +++-- .../(main)/pixels/[pixelId]/PixelControls.tsx | 34 +++++++++ .../(main)/pixels/[pixelId]/PixelHeader.tsx | 22 ++++++ .../pixels/[pixelId]/PixelMetricsBar.tsx | 71 +++++++++++++++++++ src/app/(main)/pixels/[pixelId]/PixelPage.tsx | 59 +++++++++++++++ src/app/(main)/pixels/[pixelId]/page.tsx | 12 ++++ .../teams/[teamId]/TeamSettingsPage.tsx | 2 +- .../[websiteId]/WebsiteSettingsPage.tsx | 2 +- .../teams/{[teamId] => }/TeamProvider.tsx | 0 .../(main)/teams/[teamId]/TeamEditForm.tsx | 2 +- .../(main)/teams/[teamId]/TeamSettings.tsx | 2 +- .../{[websiteId] => }/WebsiteProvider.tsx | 0 ...WebsiteDetailsPage.tsx => WebsitePage.tsx} | 2 +- src/app/(main)/websites/[websiteId]/page.tsx | 6 +- .../[websiteId]/settings/WebsiteEditForm.tsx | 2 +- .../[websiteId]/settings/WebsiteSettings.tsx | 2 +- .../settings/WebsiteSettingsHeader.tsx | 2 +- .../settings/WebsiteTransferForm.tsx | 2 +- src/app/share/[...shareId]/SharePage.tsx | 6 +- src/components/common/PageHeader.tsx | 12 ++-- src/components/hooks/context/useLink.ts | 6 ++ src/components/hooks/context/usePixel.ts | 6 ++ src/components/hooks/{ => context}/useTeam.ts | 2 +- .../hooks/{ => context}/useWebsite.ts | 2 +- src/components/hooks/index.ts | 9 ++- .../hooks/queries/useUpdateQuery.ts | 7 +- src/components/hooks/useSlug.ts | 14 ++++ src/components/messages.ts | 2 +- src/components/metrics/PagesTable.tsx | 2 +- src/index.ts | 4 +- 42 files changed, 530 insertions(+), 49 deletions(-) create mode 100644 src/app/(main)/links/LinkProvider.tsx create mode 100644 src/app/(main)/links/[linkId]/LinkControls.tsx create mode 100644 src/app/(main)/links/[linkId]/LinkHeader.tsx create mode 100644 src/app/(main)/links/[linkId]/LinkMetricsBar.tsx create mode 100644 src/app/(main)/links/[linkId]/LinkPage.tsx create mode 100644 src/app/(main)/links/[linkId]/page.tsx create mode 100644 src/app/(main)/pixels/PixelProvider.tsx create mode 100644 src/app/(main)/pixels/[pixelId]/PixelControls.tsx create mode 100644 src/app/(main)/pixels/[pixelId]/PixelHeader.tsx create mode 100644 src/app/(main)/pixels/[pixelId]/PixelMetricsBar.tsx create mode 100644 src/app/(main)/pixels/[pixelId]/PixelPage.tsx create mode 100644 src/app/(main)/pixels/[pixelId]/page.tsx rename src/app/(main)/teams/{[teamId] => }/TeamProvider.tsx (100%) rename src/app/(main)/websites/{[websiteId] => }/WebsiteProvider.tsx (100%) rename src/app/(main)/websites/[websiteId]/{WebsiteDetailsPage.tsx => WebsitePage.tsx} (95%) create mode 100644 src/components/hooks/context/useLink.ts create mode 100644 src/components/hooks/context/usePixel.ts rename src/components/hooks/{ => context}/useTeam.ts (58%) rename src/components/hooks/{ => context}/useWebsite.ts (56%) create mode 100644 src/components/hooks/useSlug.ts diff --git a/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx b/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx index a7851d78..21501973 100644 --- a/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx +++ b/src/app/(main)/admin/teams/[teamId]/AdminTeamPage.tsx @@ -1,6 +1,6 @@ 'use client'; import { TeamSettings } from '@/app/(main)/teams/[teamId]/TeamSettings'; -import { TeamProvider } from '@/app/(main)/teams/[teamId]/TeamProvider'; +import { TeamProvider } from '@/app/(main)/teams/TeamProvider'; export function AdminTeamPage({ teamId }: { teamId: string }) { return ( diff --git a/src/app/(main)/admin/websites/[websiteId]/AdminWebsitePage.tsx b/src/app/(main)/admin/websites/[websiteId]/AdminWebsitePage.tsx index 54cb9384..5da82afd 100644 --- a/src/app/(main)/admin/websites/[websiteId]/AdminWebsitePage.tsx +++ b/src/app/(main)/admin/websites/[websiteId]/AdminWebsitePage.tsx @@ -1,6 +1,6 @@ 'use client'; import { WebsiteSettings } from '@/app/(main)/websites/[websiteId]/settings/WebsiteSettings'; -import { WebsiteProvider } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; +import { WebsiteProvider } from '@/app/(main)/websites/WebsiteProvider'; import { Panel } from '@/components/common/Panel'; export function AdminWebsitePage({ websiteId }: { websiteId: string }) { diff --git a/src/app/(main)/links/LinkEditForm.tsx b/src/app/(main)/links/LinkEditForm.tsx index a6257768..38298d9f 100644 --- a/src/app/(main)/links/LinkEditForm.tsx +++ b/src/app/(main)/links/LinkEditForm.tsx @@ -32,8 +32,8 @@ export function LinkEditForm({ onSave?: () => void; onClose?: () => void; }) { - const { formatMessage, labels } = useMessages(); - const { mutate, error, isPending, touch } = useUpdateQuery( + const { formatMessage, labels, messages } = useMessages(); + const { mutate, error, isPending, touch, toast } = useUpdateQuery( linkId ? `/links/${linkId}` : '/links', { id: linkId, @@ -48,6 +48,7 @@ export function LinkEditForm({ const handleSubmit = async (data: any) => { mutate(data, { onSuccess: async () => { + toast(formatMessage(messages.saved)); touch('links'); onSave?.(); onClose?.(); diff --git a/src/app/(main)/links/LinkProvider.tsx b/src/app/(main)/links/LinkProvider.tsx new file mode 100644 index 00000000..6593d85a --- /dev/null +++ b/src/app/(main)/links/LinkProvider.tsx @@ -0,0 +1,20 @@ +'use client'; +import { createContext, ReactNode } from 'react'; +import { useLinkQuery } from '@/components/hooks'; +import { Loading } from '@umami/react-zen'; + +export const LinkContext = createContext(null); + +export function LinkProvider({ linkId, children }: { linkId?: string; children: ReactNode }) { + const { data: link, isLoading, isFetching } = useLinkQuery(linkId); + + if (isFetching && isLoading) { + return ; + } + + if (!link) { + return null; + } + + return {children}; +} diff --git a/src/app/(main)/links/LinksTable.tsx b/src/app/(main)/links/LinksTable.tsx index 5e854a4a..b8471829 100644 --- a/src/app/(main)/links/LinksTable.tsx +++ b/src/app/(main)/links/LinksTable.tsx @@ -1,17 +1,16 @@ +import Link from 'next/link'; import { DataTable, DataColumn, Row } from '@umami/react-zen'; -import { useConfig, useMessages, useNavigation } from '@/components/hooks'; +import { useMessages, useNavigation, useSlug } from '@/components/hooks'; import { Empty } from '@/components/common/Empty'; import { DateDistance } from '@/components/common/DateDistance'; import { ExternalLink } from '@/components/common/ExternalLink'; import { LinkEditButton } from './LinkEditButton'; import { LinkDeleteButton } from './LinkDeleteButton'; -import { LINKS_URL } from '@/lib/constants'; export function LinksTable({ data = [] }) { const { formatMessage, labels } = useMessages(); - const { websiteId } = useNavigation(); - const { linksUrl } = useConfig(); - const hostUrl = linksUrl || LINKS_URL; + const { websiteId, renderUrl } = useNavigation(); + const { getSlugUrl } = useSlug('link'); if (data.length === 0) { return ; @@ -19,10 +18,14 @@ export function LinksTable({ data = [] }) { return ( - + + {({ id, name }: any) => { + return {name}; + }} + {({ slug }: any) => { - const url = `${hostUrl}/${slug}`; + const url = getSlugUrl(slug); return {url}; }} diff --git a/src/app/(main)/links/[linkId]/LinkControls.tsx b/src/app/(main)/links/[linkId]/LinkControls.tsx new file mode 100644 index 00000000..c9fd595f --- /dev/null +++ b/src/app/(main)/links/[linkId]/LinkControls.tsx @@ -0,0 +1,34 @@ +import { Column, Row } from '@umami/react-zen'; +import { WebsiteFilterButton } from '@/app/(main)/websites/[websiteId]/WebsiteFilterButton'; +import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter'; +import { FilterBar } from '@/components/input/FilterBar'; +import { WebsiteMonthSelect } from '@/components/input/WebsiteMonthSelect'; +import { ExportButton } from '@/components/input/ExportButton'; + +export function LinkControls({ + linkId: websiteId, + allowFilter = true, + allowDateFilter = true, + allowMonthFilter, + allowCompare, + allowDownload = false, +}: { + linkId: string; + allowFilter?: boolean; + allowCompare?: boolean; + allowDateFilter?: boolean; + allowMonthFilter?: boolean; + allowDownload?: boolean; +}) { + return ( + + + {allowFilter ? :
} + {allowDateFilter && } + {allowDownload && } + {allowMonthFilter && } + + {allowFilter && } + + ); +} diff --git a/src/app/(main)/links/[linkId]/LinkHeader.tsx b/src/app/(main)/links/[linkId]/LinkHeader.tsx new file mode 100644 index 00000000..6f8f7a57 --- /dev/null +++ b/src/app/(main)/links/[linkId]/LinkHeader.tsx @@ -0,0 +1,22 @@ +import { useLink, useMessages, useSlug } from '@/components/hooks'; +import { PageHeader } from '@/components/common/PageHeader'; +import { Icon, Text } from '@umami/react-zen'; +import { ExternalLink } from '@/components/icons'; +import { LinkButton } from '@/components/common/LinkButton'; + +export function LinkHeader() { + const { formatMessage, labels } = useMessages(); + const { getSlugUrl } = useSlug('link'); + const link = useLink(); + + return ( + + + + + + {formatMessage(labels.view)} + + + ); +} diff --git a/src/app/(main)/links/[linkId]/LinkMetricsBar.tsx b/src/app/(main)/links/[linkId]/LinkMetricsBar.tsx new file mode 100644 index 00000000..5e9d6cbf --- /dev/null +++ b/src/app/(main)/links/[linkId]/LinkMetricsBar.tsx @@ -0,0 +1,71 @@ +import { useDateRange, useMessages } from '@/components/hooks'; +import { MetricCard } from '@/components/metrics/MetricCard'; +import { MetricsBar } from '@/components/metrics/MetricsBar'; +import { formatLongNumber } from '@/lib/format'; +import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery'; +import { LoadingPanel } from '@/components/common/LoadingPanel'; + +export function LinkMetricsBar({ + linkId, +}: { + linkId: string; + showChange?: boolean; + compareMode?: boolean; +}) { + const { dateRange } = useDateRange(linkId); + const { formatMessage, labels } = useMessages(); + const { data, isLoading, isFetching, error } = useWebsiteStatsQuery(linkId); + const isAllTime = dateRange.value === 'all'; + + const { pageviews, visitors, visits, comparison } = data || {}; + + const metrics = data + ? [ + { + value: visitors, + label: formatMessage(labels.visitors), + change: visitors - comparison.visitors, + formatValue: formatLongNumber, + }, + { + value: visits, + label: formatMessage(labels.visits), + change: visits - comparison.visits, + formatValue: formatLongNumber, + }, + { + value: pageviews, + label: formatMessage(labels.views), + change: pageviews - comparison.pageviews, + formatValue: formatLongNumber, + }, + ] + : null; + + return ( + + + {metrics?.map(({ label, value, prev, change, formatValue, reverseColors }: any) => { + return ( + + ); + })} + + + ); +} diff --git a/src/app/(main)/links/[linkId]/LinkPage.tsx b/src/app/(main)/links/[linkId]/LinkPage.tsx new file mode 100644 index 00000000..d57f937a --- /dev/null +++ b/src/app/(main)/links/[linkId]/LinkPage.tsx @@ -0,0 +1,59 @@ +'use client'; +import { PageBody } from '@/components/common/PageBody'; +import { LinkProvider } from '@/app/(main)/links/LinkProvider'; +import { LinkHeader } from '@/app/(main)/links/[linkId]/LinkHeader'; +import { Panel } from '@/components/common/Panel'; +import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart'; +import { LinkMetricsBar } from '@/app/(main)/links/[linkId]/LinkMetricsBar'; +import { LinkControls } from '@/app/(main)/links/[linkId]/LinkControls'; +import { Grid } from '@umami/react-zen'; +import { GridRow } from '@/components/common/GridRow'; +import { ReferrersTable } from '@/components/metrics/ReferrersTable'; +import { BrowsersTable } from '@/components/metrics/BrowsersTable'; +import { OSTable } from '@/components/metrics/OSTable'; +import { DevicesTable } from '@/components/metrics/DevicesTable'; +import { WorldMap } from '@/components/metrics/WorldMap'; +import { CountriesTable } from '@/components/metrics/CountriesTable'; + +export function LinkPage({ linkId }: { linkId: string }) { + const props = { websiteId: linkId, limit: 10, allowDownload: false }; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/app/(main)/links/[linkId]/page.tsx b/src/app/(main)/links/[linkId]/page.tsx new file mode 100644 index 00000000..ae3b2c9a --- /dev/null +++ b/src/app/(main)/links/[linkId]/page.tsx @@ -0,0 +1,12 @@ +import { LinkPage } from './LinkPage'; +import { Metadata } from 'next'; + +export default async function ({ params }: { params: Promise<{ linkId: string }> }) { + const { linkId } = await params; + + return ; +} + +export const metadata: Metadata = { + title: 'Link', +}; diff --git a/src/app/(main)/pixels/PixelEditForm.tsx b/src/app/(main)/pixels/PixelEditForm.tsx index 8026c76a..6024a745 100644 --- a/src/app/(main)/pixels/PixelEditForm.tsx +++ b/src/app/(main)/pixels/PixelEditForm.tsx @@ -31,8 +31,8 @@ export function PixelEditForm({ onSave?: () => void; onClose?: () => void; }) { - const { formatMessage, labels } = useMessages(); - const { mutate, error, isPending, touch } = useUpdateQuery( + const { formatMessage, labels, messages } = useMessages(); + const { mutate, error, isPending, touch, toast } = useUpdateQuery( pixelId ? `/pixels/${pixelId}` : '/pixels', { id: pixelId, @@ -47,6 +47,7 @@ export function PixelEditForm({ const handleSubmit = async (data: any) => { mutate(data, { onSuccess: async () => { + toast(formatMessage(messages.saved)); touch('pixels'); onSave?.(); onClose?.(); diff --git a/src/app/(main)/pixels/PixelProvider.tsx b/src/app/(main)/pixels/PixelProvider.tsx new file mode 100644 index 00000000..1a5c1d5d --- /dev/null +++ b/src/app/(main)/pixels/PixelProvider.tsx @@ -0,0 +1,20 @@ +'use client'; +import { createContext, ReactNode } from 'react'; +import { usePixelQuery } from '@/components/hooks'; +import { Loading } from '@umami/react-zen'; + +export const PixelContext = createContext(null); + +export function PixelProvider({ pixelId, children }: { pixelId?: string; children: ReactNode }) { + const { data: pixel, isLoading, isFetching } = usePixelQuery(pixelId); + + if (isFetching && isLoading) { + return ; + } + + if (!pixel) { + return null; + } + + return {children}; +} diff --git a/src/app/(main)/pixels/PixelsTable.tsx b/src/app/(main)/pixels/PixelsTable.tsx index cb11554e..dcb5307c 100644 --- a/src/app/(main)/pixels/PixelsTable.tsx +++ b/src/app/(main)/pixels/PixelsTable.tsx @@ -1,16 +1,16 @@ +import Link from 'next/link'; import { DataTable, DataColumn, Row } from '@umami/react-zen'; -import { useConfig, useMessages } from '@/components/hooks'; +import { useMessages, useNavigation, useSlug } from '@/components/hooks'; import { Empty } from '@/components/common/Empty'; import { DateDistance } from '@/components/common/DateDistance'; import { PixelEditButton } from './PixelEditButton'; import { PixelDeleteButton } from './PixelDeleteButton'; -import { PIXELS_URL } from '@/lib/constants'; import { ExternalLink } from '@/components/common/ExternalLink'; export function PixelsTable({ data = [] }) { const { formatMessage, labels } = useMessages(); - const { pixelsUrl } = useConfig(); - const hostUrl = pixelsUrl || PIXELS_URL; + const { renderUrl } = useNavigation(); + const { getSlugUrl } = useSlug('pixel'); if (data.length === 0) { return ; @@ -18,10 +18,14 @@ export function PixelsTable({ data = [] }) { return ( - + + {({ id, name }: any) => { + return {name}; + }} + {({ slug }: any) => { - const url = `${hostUrl}/${slug}`; + const url = getSlugUrl(slug); return {url}; }} diff --git a/src/app/(main)/pixels/[pixelId]/PixelControls.tsx b/src/app/(main)/pixels/[pixelId]/PixelControls.tsx new file mode 100644 index 00000000..6bd829cf --- /dev/null +++ b/src/app/(main)/pixels/[pixelId]/PixelControls.tsx @@ -0,0 +1,34 @@ +import { Column, Row } from '@umami/react-zen'; +import { WebsiteFilterButton } from '@/app/(main)/websites/[websiteId]/WebsiteFilterButton'; +import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter'; +import { FilterBar } from '@/components/input/FilterBar'; +import { WebsiteMonthSelect } from '@/components/input/WebsiteMonthSelect'; +import { ExportButton } from '@/components/input/ExportButton'; + +export function PixelControls({ + pixelId: websiteId, + allowFilter = true, + allowDateFilter = true, + allowMonthFilter, + allowCompare, + allowDownload = false, +}: { + pixelId: string; + allowFilter?: boolean; + allowCompare?: boolean; + allowDateFilter?: boolean; + allowMonthFilter?: boolean; + allowDownload?: boolean; +}) { + return ( + + + {allowFilter ? :
} + {allowDateFilter && } + {allowDownload && } + {allowMonthFilter && } + + {allowFilter && } + + ); +} diff --git a/src/app/(main)/pixels/[pixelId]/PixelHeader.tsx b/src/app/(main)/pixels/[pixelId]/PixelHeader.tsx new file mode 100644 index 00000000..ad81a9bf --- /dev/null +++ b/src/app/(main)/pixels/[pixelId]/PixelHeader.tsx @@ -0,0 +1,22 @@ +import { usePixel, useMessages, useSlug } from '@/components/hooks'; +import { PageHeader } from '@/components/common/PageHeader'; +import { Icon, Text } from '@umami/react-zen'; +import { ExternalLink } from '@/components/icons'; +import { LinkButton } from '@/components/common/LinkButton'; + +export function PixelHeader() { + const { formatMessage, labels } = useMessages(); + const { getSlugUrl } = useSlug('pixel'); + const pixel = usePixel(); + + return ( + + + + + + {formatMessage(labels.view)} + + + ); +} diff --git a/src/app/(main)/pixels/[pixelId]/PixelMetricsBar.tsx b/src/app/(main)/pixels/[pixelId]/PixelMetricsBar.tsx new file mode 100644 index 00000000..5b01ef84 --- /dev/null +++ b/src/app/(main)/pixels/[pixelId]/PixelMetricsBar.tsx @@ -0,0 +1,71 @@ +import { useDateRange, useMessages } from '@/components/hooks'; +import { MetricCard } from '@/components/metrics/MetricCard'; +import { MetricsBar } from '@/components/metrics/MetricsBar'; +import { formatLongNumber } from '@/lib/format'; +import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery'; +import { LoadingPanel } from '@/components/common/LoadingPanel'; + +export function PixelMetricsBar({ + pixelId, +}: { + pixelId: string; + showChange?: boolean; + compareMode?: boolean; +}) { + const { dateRange } = useDateRange(pixelId); + const { formatMessage, labels } = useMessages(); + const { data, isLoading, isFetching, error } = useWebsiteStatsQuery(pixelId); + const isAllTime = dateRange.value === 'all'; + + const { pageviews, visitors, visits, comparison } = data || {}; + + const metrics = data + ? [ + { + value: visitors, + label: formatMessage(labels.visitors), + change: visitors - comparison.visitors, + formatValue: formatLongNumber, + }, + { + value: visits, + label: formatMessage(labels.visits), + change: visits - comparison.visits, + formatValue: formatLongNumber, + }, + { + value: pageviews, + label: formatMessage(labels.views), + change: pageviews - comparison.pageviews, + formatValue: formatLongNumber, + }, + ] + : null; + + return ( + + + {metrics?.map(({ label, value, prev, change, formatValue, reverseColors }: any) => { + return ( + + ); + })} + + + ); +} diff --git a/src/app/(main)/pixels/[pixelId]/PixelPage.tsx b/src/app/(main)/pixels/[pixelId]/PixelPage.tsx new file mode 100644 index 00000000..eb42b125 --- /dev/null +++ b/src/app/(main)/pixels/[pixelId]/PixelPage.tsx @@ -0,0 +1,59 @@ +'use client'; +import { PageBody } from '@/components/common/PageBody'; +import { PixelProvider } from '@/app/(main)/pixels/PixelProvider'; +import { PixelHeader } from '@/app/(main)/pixels/[pixelId]/PixelHeader'; +import { Panel } from '@/components/common/Panel'; +import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart'; +import { PixelMetricsBar } from '@/app/(main)/pixels/[pixelId]/PixelMetricsBar'; +import { PixelControls } from '@/app/(main)/pixels/[pixelId]/PixelControls'; +import { Grid } from '@umami/react-zen'; +import { GridRow } from '@/components/common/GridRow'; +import { ReferrersTable } from '@/components/metrics/ReferrersTable'; +import { BrowsersTable } from '@/components/metrics/BrowsersTable'; +import { OSTable } from '@/components/metrics/OSTable'; +import { DevicesTable } from '@/components/metrics/DevicesTable'; +import { WorldMap } from '@/components/metrics/WorldMap'; +import { CountriesTable } from '@/components/metrics/CountriesTable'; + +export function PixelPage({ pixelId }: { pixelId: string }) { + const props = { websiteId: pixelId, limit: 10, allowDownload: false }; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/app/(main)/pixels/[pixelId]/page.tsx b/src/app/(main)/pixels/[pixelId]/page.tsx new file mode 100644 index 00000000..1cb72c1d --- /dev/null +++ b/src/app/(main)/pixels/[pixelId]/page.tsx @@ -0,0 +1,12 @@ +import { PixelPage } from './PixelPage'; +import { Metadata } from 'next'; + +export default async function ({ params }: { params: Promise<{ pixelId: string }> }) { + const { pixelId } = await params; + + return ; +} + +export const metadata: Metadata = { + title: 'Pixel', +}; diff --git a/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx b/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx index 3736299d..8ad2b694 100644 --- a/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx +++ b/src/app/(main)/settings/teams/[teamId]/TeamSettingsPage.tsx @@ -1,5 +1,5 @@ 'use client'; -import { TeamProvider } from '@/app/(main)/teams/[teamId]/TeamProvider'; +import { TeamProvider } from '@/app/(main)/teams/TeamProvider'; import { TeamSettings } from '@/app/(main)/teams/[teamId]/TeamSettings'; export function TeamSettingsPage({ teamId }: { teamId: string }) { diff --git a/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage.tsx b/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage.tsx index 59df2f3c..e5140cb2 100644 --- a/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage.tsx +++ b/src/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage.tsx @@ -1,6 +1,6 @@ 'use client'; import { Column } from '@umami/react-zen'; -import { WebsiteProvider } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; +import { WebsiteProvider } from '@/app/(main)/websites/WebsiteProvider'; import { WebsiteSettings } from '@/app/(main)/websites/[websiteId]/settings/WebsiteSettings'; import { WebsiteSettingsHeader } from '@/app/(main)/websites/[websiteId]/settings/WebsiteSettingsHeader'; import { Panel } from '@/components/common/Panel'; diff --git a/src/app/(main)/teams/[teamId]/TeamProvider.tsx b/src/app/(main)/teams/TeamProvider.tsx similarity index 100% rename from src/app/(main)/teams/[teamId]/TeamProvider.tsx rename to src/app/(main)/teams/TeamProvider.tsx diff --git a/src/app/(main)/teams/[teamId]/TeamEditForm.tsx b/src/app/(main)/teams/[teamId]/TeamEditForm.tsx index 9c053ac8..ec3b8fb0 100644 --- a/src/app/(main)/teams/[teamId]/TeamEditForm.tsx +++ b/src/app/(main)/teams/[teamId]/TeamEditForm.tsx @@ -10,7 +10,7 @@ import { import { getRandomChars } from '@/lib/crypto'; import { useContext } from 'react'; import { useApi, useMessages, useModified } from '@/components/hooks'; -import { TeamContext } from '@/app/(main)/teams/[teamId]/TeamProvider'; +import { TeamContext } from '@/app/(main)/teams/TeamProvider'; const generateId = () => `team_${getRandomChars(16)}`; diff --git a/src/app/(main)/teams/[teamId]/TeamSettings.tsx b/src/app/(main)/teams/[teamId]/TeamSettings.tsx index acf1a936..af2a4f32 100644 --- a/src/app/(main)/teams/[teamId]/TeamSettings.tsx +++ b/src/app/(main)/teams/[teamId]/TeamSettings.tsx @@ -1,6 +1,6 @@ import { useContext, useState } from 'react'; import { Column, Tabs, TabList, Tab, TabPanel } from '@umami/react-zen'; -import { TeamContext } from '@/app/(main)/teams/[teamId]/TeamProvider'; +import { TeamContext } from '@/app/(main)/teams/TeamProvider'; import { useLoginQuery, useMessages, useNavigation } from '@/components/hooks'; import { ROLES } from '@/lib/constants'; diff --git a/src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx b/src/app/(main)/websites/WebsiteProvider.tsx similarity index 100% rename from src/app/(main)/websites/[websiteId]/WebsiteProvider.tsx rename to src/app/(main)/websites/WebsiteProvider.tsx diff --git a/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx b/src/app/(main)/websites/[websiteId]/WebsitePage.tsx similarity index 95% rename from src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx rename to src/app/(main)/websites/[websiteId]/WebsitePage.tsx index 33bca5ae..8a0edbfc 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsitePage.tsx @@ -8,7 +8,7 @@ import { WebsiteMetricsBar } from './WebsiteMetricsBar'; import { WebsiteTableView } from './WebsiteTableView'; import { WebsiteControls } from './WebsiteControls'; -export function WebsiteDetailsPage({ websiteId }: { websiteId: string }) { +export function WebsitePage({ websiteId }: { websiteId: string }) { const { router, query: { view, compare }, diff --git a/src/app/(main)/websites/[websiteId]/page.tsx b/src/app/(main)/websites/[websiteId]/page.tsx index 286a4612..9755e6d0 100644 --- a/src/app/(main)/websites/[websiteId]/page.tsx +++ b/src/app/(main)/websites/[websiteId]/page.tsx @@ -1,10 +1,10 @@ -import { WebsiteDetailsPage } from './WebsiteDetailsPage'; +import { WebsitePage } from './WebsitePage'; import { Metadata } from 'next'; -export default async function WebsitePage({ params }: { params: Promise<{ websiteId: string }> }) { +export default async function ({ params }: { params: Promise<{ websiteId: string }> }) { const { websiteId } = await params; - return ; + return ; } export const metadata: Metadata = { diff --git a/src/app/(main)/websites/[websiteId]/settings/WebsiteEditForm.tsx b/src/app/(main)/websites/[websiteId]/settings/WebsiteEditForm.tsx index cb7cb0d1..dbefd669 100644 --- a/src/app/(main)/websites/[websiteId]/settings/WebsiteEditForm.tsx +++ b/src/app/(main)/websites/[websiteId]/settings/WebsiteEditForm.tsx @@ -9,7 +9,7 @@ import { } from '@umami/react-zen'; import { useApi, useMessages, useModified } from '@/components/hooks'; import { DOMAIN_REGEX } from '@/lib/constants'; -import { WebsiteContext } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; +import { WebsiteContext } from '@/app/(main)/websites/WebsiteProvider'; export function WebsiteEditForm({ websiteId, onSave }: { websiteId: string; onSave?: () => void }) { const website = useContext(WebsiteContext); diff --git a/src/app/(main)/websites/[websiteId]/settings/WebsiteSettings.tsx b/src/app/(main)/websites/[websiteId]/settings/WebsiteSettings.tsx index baf59452..de775b22 100644 --- a/src/app/(main)/websites/[websiteId]/settings/WebsiteSettings.tsx +++ b/src/app/(main)/websites/[websiteId]/settings/WebsiteSettings.tsx @@ -1,6 +1,6 @@ import { useContext } from 'react'; import { Tabs, TabList, Tab, TabPanel } from '@umami/react-zen'; -import { WebsiteContext } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; +import { WebsiteContext } from '@/app/(main)/websites/WebsiteProvider'; import { useMessages } from '@/components/hooks'; import { WebsiteShareForm } from './WebsiteShareForm'; import { WebsiteTrackingCode } from './WebsiteTrackingCode'; diff --git a/src/app/(main)/websites/[websiteId]/settings/WebsiteSettingsHeader.tsx b/src/app/(main)/websites/[websiteId]/settings/WebsiteSettingsHeader.tsx index ee542f2f..5f8c8536 100644 --- a/src/app/(main)/websites/[websiteId]/settings/WebsiteSettingsHeader.tsx +++ b/src/app/(main)/websites/[websiteId]/settings/WebsiteSettingsHeader.tsx @@ -1,5 +1,5 @@ import { useContext } from 'react'; -import { WebsiteContext } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; +import { WebsiteContext } from '@/app/(main)/websites/WebsiteProvider'; import { PageHeader } from '@/components/common/PageHeader'; import { Globe } from '@/components/icons'; diff --git a/src/app/(main)/websites/[websiteId]/settings/WebsiteTransferForm.tsx b/src/app/(main)/websites/[websiteId]/settings/WebsiteTransferForm.tsx index 1545f84d..b1b3a45b 100644 --- a/src/app/(main)/websites/[websiteId]/settings/WebsiteTransferForm.tsx +++ b/src/app/(main)/websites/[websiteId]/settings/WebsiteTransferForm.tsx @@ -11,7 +11,7 @@ import { Text, } from '@umami/react-zen'; import { useApi, useLoginQuery, useMessages, useUserTeamsQuery } from '@/components/hooks'; -import { WebsiteContext } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; +import { WebsiteContext } from '@/app/(main)/websites/WebsiteProvider'; import { ROLES } from '@/lib/constants'; export function WebsiteTransferForm({ diff --git a/src/app/share/[...shareId]/SharePage.tsx b/src/app/share/[...shareId]/SharePage.tsx index c5f734b5..ae2be609 100644 --- a/src/app/share/[...shareId]/SharePage.tsx +++ b/src/app/share/[...shareId]/SharePage.tsx @@ -1,6 +1,6 @@ 'use client'; -import { WebsiteProvider } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; -import { WebsiteDetailsPage } from '@/app/(main)/websites/[websiteId]/WebsiteDetailsPage'; +import { WebsiteProvider } from '@/app/(main)/websites/WebsiteProvider'; +import { WebsitePage } from '@/app/(main)/websites/[websiteId]/WebsitePage'; import { useShareTokenQuery } from '@/components/hooks'; import { PageBody } from '@/components/common/PageBody'; import { Header } from './Header'; @@ -17,7 +17,7 @@ export function SharePage({ shareId }) {
- +