Merge pull request #2157 from umami-software/dev

v2.4.0
This commit is contained in:
Mike Cao 2023-07-30 23:27:37 -07:00 committed by GitHub
commit 2d3560f516
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
233 changed files with 17443 additions and 2005 deletions

19
.github/stale.yml vendored
View File

@ -1,19 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
- enhancement
- bug
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@ -16,13 +16,13 @@ jobs:
strategy:
matrix:
include:
- node-version: 14.x
- node-version: 16.x
db-type: postgresql
- node-version: 14.x
- node-version: 16.x
db-type: mysql
- node-version: 16.x
- node-version: 18.x
db-type: postgresql
- node-version: 16.x
- node-version: 18.x
db-type: mysql
steps:

22
.github/workflows/stale-issues.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: Close stale issues
on:
schedule:
- cron: '30 1 * * *'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v8
with:
days-before-issue-stale: 60
days-before-issue-close: 7
stale-issue-label: 'stale'
stale-issue-message: 'This issue is stale because it has been open for 60 days with no activity.'
close-issue-message: 'This issue was closed because it has been inactive for 7 days since being marked as stale.'
days-before-pr-stale: -1
days-before-pr-close: -1
repo-token: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@ -25,6 +25,7 @@ node_modules
*.iml
*.log
.vscode
.tool-versions
# debug
npm-debug.log*

1
assets/bar-chart.svg Normal file
View File

@ -0,0 +1 @@
<svg height="512" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m7 13v9a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1-1v-9a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1zm7-12h-4a1 1 0 0 0 -1 1v20a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-20a1 1 0 0 0 -1-1zm8 5h-4a1 1 0 0 0 -1 1v15a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-15a1 1 0 0 0 -1-1z"/></svg>

After

Width:  |  Height:  |  Size: 328 B

View File

@ -0,0 +1,29 @@
import { useState } from 'react';
import { Button, LoadingButton, Form, FormButtons } from 'react-basics';
import useMessages from 'hooks/useMessages';
export function ConfirmDeleteForm({ name, onConfirm, onClose }) {
const [loading, setLoading] = useState(false);
const { formatMessage, labels, messages, FormattedMessage } = useMessages();
const handleConfirm = () => {
setLoading(true);
onConfirm();
};
return (
<Form>
<p>
<FormattedMessage {...messages.confirmDelete} values={{ target: <b>{name}</b> }} />
</p>
<FormButtons flex>
<LoadingButton loading={loading} onClick={handleConfirm} variant="danger">
{formatMessage(labels.delete)}
</LoadingButton>
<Button onClick={onClose}>{formatMessage(labels.cancel)}</Button>
</FormButtons>
</Form>
);
}
export default ConfirmDeleteForm;

View File

@ -0,0 +1,12 @@
import Link from 'next/link';
import { Icon, Icons, Text } from 'react-basics';
import styles from './LinkButton.module.css';
export default function LinkButton({ href, icon, children }) {
return (
<Link className={styles.button} href={href}>
<Icon>{icon || <Icons.ArrowRight />}</Icon>
<Text>{children}</Text>
</Link>
);
}

View File

@ -0,0 +1,28 @@
.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);
}

View File

@ -1,15 +1,23 @@
import { useState, useEffect, useCallback } from 'react';
import { useEffect, useCallback, useState } from 'react';
import { Button, Row, Column } from 'react-basics';
import { setItem } from 'next-basics';
import useStore, { checkVersion } from 'store/version';
import { REPO_URL, VERSION_CHECK } from 'lib/constants';
import styles from './UpdateNotice.module.css';
import useMessages from 'hooks/useMessages';
import { useRouter } from 'next/router';
export function UpdateNotice() {
export function UpdateNotice({ user, config }) {
const { formatMessage, labels, messages } = useMessages();
const { latest, checked, hasUpdate, releaseUrl } = useStore();
const [dismissed, setDismissed] = useState(false);
const { pathname } = useRouter();
const [dismissed, setDismissed] = useState(checked);
const allowUpdate =
user?.isAdmin &&
!config?.updatesDisabled &&
!config?.cloudMode &&
!pathname.includes('/share/') &&
!dismissed;
const updateCheck = useCallback(() => {
setItem(VERSION_CHECK, { version: latest, time: Date.now() });
@ -27,12 +35,12 @@ export function UpdateNotice() {
}
useEffect(() => {
if (!checked) {
if (allowUpdate) {
checkVersion();
}
}, [checked]);
}, [allowUpdate]);
if (!hasUpdate || dismissed) {
if (!allowUpdate || !hasUpdate) {
return null;
}

View File

@ -4,7 +4,7 @@
gap: 20px;
margin: 20px auto;
justify-self: center;
background: #fff;
background: var(--base50);
padding: 20px;
border: 1px solid var(--base300);
border-radius: var(--border-radius);
@ -15,7 +15,8 @@
display: flex;
justify-content: center;
align-items: center;
font-weight: 600;
color: var(--font-color100);
font-weight: 700;
}
.buttons {

View File

@ -1,5 +1,7 @@
import { Icons } from 'react-basics';
import AddUser from 'assets/add-user.svg';
import Bars from 'assets/bars.svg';
import BarChart from 'assets/bar-chart.svg';
import Bolt from 'assets/bolt.svg';
import Calendar from 'assets/calendar.svg';
import Clock from 'assets/clock.svg';
@ -22,6 +24,8 @@ import Visitor from 'assets/visitor.svg';
const icons = {
...Icons,
AddUser,
Bars,
BarChart,
Bolt,
Calendar,
Clock,

View File

@ -10,11 +10,7 @@ export function RefreshButton({ websiteId, isLoading }) {
function handleClick() {
if (!isLoading && dateRange) {
if (/^\d+/.test(dateRange.value)) {
setWebsiteDateRange(websiteId, dateRange.value);
} else {
setWebsiteDateRange(websiteId, dateRange);
}
setWebsiteDateRange(websiteId, dateRange);
}
}

View File

@ -1,25 +1,13 @@
import useApi from 'hooks/useApi';
import useDateRange from 'hooks/useDateRange';
import DateFilter from './DateFilter';
import styles from './WebsiteDateFilter.module.css';
export default function WebsiteDateFilter({ websiteId }) {
const { get } = useApi();
const [dateRange, setDateRange] = useDateRange(websiteId);
const { value, startDate, endDate } = dateRange;
const handleChange = async value => {
if (value === 'all' && websiteId) {
const data = await get(`/websites/${websiteId}`);
if (data) {
const start = new Date(data.createdAt).getTime();
const end = Date.now();
setDateRange(`range:${start}:${end}`);
}
} else if (value !== 'all') {
setDateRange(value);
}
setDateRange(value);
};
return (

View File

@ -11,17 +11,14 @@ import styles from './AppLayout.module.css';
export function AppLayout({ title, children }) {
const { user } = useRequireLogin();
const config = useConfig();
const { pathname } = useRouter();
if (!user || !config) {
return null;
}
const allowUpdate = user?.isAdmin && !config?.updatesDisabled && !pathname.includes('/share/');
return (
<div className={styles.layout} data-app-version={CURRENT_VERSION}>
{allowUpdate && <UpdateNotice />}
<UpdateNotice user={user} config={config} />
<Head>
<title>{title ? `${title} | umami` : 'umami'}</title>
</Head>

View File

@ -8,7 +8,6 @@
.nav {
height: 60px;
width: 100vw;
z-index: var(--z-index-overlay);
grid-column: 1;
grid-row: 1 / 2;
}

View File

@ -81,6 +81,7 @@ export const labels = defineMessages({
devices: { id: 'label.devices', defaultMessage: 'Devices' },
countries: { id: 'label.countries', defaultMessage: 'Countries' },
languages: { id: 'label.languages', defaultMessage: 'Languages' },
event: { id: 'label.event', defaultMessage: 'Event' },
events: { id: 'label.events', defaultMessage: 'Events' },
query: { id: 'label.query', defaultMessage: 'Query' },
queryParameters: { id: 'label.query-parameters', defaultMessage: 'Query parameters' },
@ -159,6 +160,8 @@ export const labels = defineMessages({
value: { id: 'labels.value', defaultMessage: 'Value' },
overview: { id: 'labels.overview', defaultMessage: 'Overview' },
totalRecords: { id: 'labels.total-records', defaultMessage: 'Total records' },
insights: { id: 'label.insights', defaultMessage: 'Insights' },
dropoff: { id: 'label.dropoff', defaultMessage: 'Dropoff' },
});
export const messages = defineMessages({
@ -270,4 +273,8 @@ export const messages = defineMessages({
id: 'message.no-event-data',
defaultMessage: 'No event data is available.',
},
newVersionAvailable: {
id: 'new-version-available',
defaultMessage: 'A new version of Umami {version} is available!',
},
});

View File

@ -29,7 +29,7 @@ export function ActiveUsers({ websiteId, value, refetchInterval = 60000 }) {
}
return (
<StatusLight variant="success">
<StatusLight className={styles.container} variant="success">
<div className={styles.text}>{formatMessage(messages.activeUsers, { x: count })}</div>
</StatusLight>
);

View File

@ -1,10 +1,14 @@
.container {
display: flex;
align-items: center;
margin-left: 20px;
}
.text {
display: flex;
white-space: nowrap;
font-size: var(--font-size-md);
font-weight: 400;
}
.value {

View File

@ -3,7 +3,7 @@ import BarChart from './BarChart';
import { useLocale, useTheme, useMessages } from 'hooks';
import { renderDateLabels, renderStatusTooltipPopup } from 'lib/charts';
export function PageviewsChart({ websiteId, data, unit, className, loading, ...props }) {
export function PageviewsChart({ websiteId, data, unit, loading, ...props }) {
const { formatMessage, labels } = useMessages();
const { colors } = useTheme();
const { locale } = useLocale();
@ -31,7 +31,6 @@ export function PageviewsChart({ websiteId, data, unit, className, loading, ...p
<BarChart
{...props}
key={websiteId}
className={className}
datasets={datasets}
unit={unit}
loading={loading}

View File

@ -18,7 +18,9 @@ export function Dashboard({ userId }) {
const { showCharts, limit, editing } = dashboard;
const [max, setMax] = useState(limit);
const { get, useQuery } = useApi();
const { data, isLoading, error } = useQuery(['websites'], () => get('/websites', { userId }));
const { data, isLoading, error } = useQuery(['websites'], () =>
get('/websites', { userId, includeTeams: 1 }),
);
const hasData = data && data.length !== 0;
const { dir } = useLocale();

View File

@ -1,4 +1,4 @@
import { Menu, Icon, Text, PopupTrigger, Popup, Item, Button } from 'react-basics';
import { TooltipPopup, Icon, Text, Flexbox, Popup, Item, Button } from 'react-basics';
import Icons from 'components/icons';
import { saveDashboard } from 'store/dashboard';
import useMessages from 'hooks/useMessages';
@ -6,40 +6,30 @@ import useMessages from 'hooks/useMessages';
export function DashboardSettingsButton() {
const { formatMessage, labels } = useMessages();
const menuOptions = [
{
label: formatMessage(labels.toggleCharts),
value: 'charts',
},
{
label: formatMessage(labels.editDashboard),
value: 'order',
},
];
const handleToggleCharts = () => {
saveDashboard(state => ({ showCharts: !state.showCharts }));
};
function handleSelect(value) {
if (value === 'charts') {
saveDashboard(state => ({ showCharts: !state.showCharts }));
}
if (value === 'order') {
saveDashboard({ editing: true });
}
}
const handleEdit = () => {
saveDashboard({ editing: true });
};
return (
<PopupTrigger>
<Button>
<Flexbox gap={10}>
<TooltipPopup label={formatMessage(labels.toggleCharts)} position="bottom">
<Button onClick={handleToggleCharts}>
<Icon>
<Icons.BarChart />
</Icon>
</Button>
</TooltipPopup>
<Button onClick={handleEdit}>
<Icon>
<Icons.Edit />
</Icon>
<Text>{formatMessage(labels.edit)}</Text>
</Button>
<Popup alignment="end">
<Menu variant="popup" items={menuOptions} onSelect={handleSelect}>
{({ label, value }) => <Item key={value}>{label}</Item>}
</Menu>
</Popup>
</PopupTrigger>
</Flexbox>
);
}

View File

@ -13,14 +13,15 @@ export function EventDataTable({ data = [] }) {
return (
<GridTable data={data}>
<GridColumn name="event" label={formatMessage(labels.event)}>
{row => (
<Link href={resolveUrl({ event: row.event })} shallow={true}>
{row.event}
</Link>
)}
</GridColumn>
<GridColumn name="field" label={formatMessage(labels.field)}>
{row => {
return (
<Link href={resolveUrl({ view: row.field })} shallow={true}>
{row.field}
</Link>
);
}}
{row => row.field}
</GridColumn>
<GridColumn name="total" label={formatMessage(labels.totalRecords)}>
{({ total }) => total.toLocaleString()}

View File

@ -5,14 +5,14 @@ import Icons from 'components/icons';
import PageHeader from 'components/layout/PageHeader';
import Empty from 'components/common/Empty';
export function EventDataTable({ data = [], field }) {
export function EventDataValueTable({ data = [], event }) {
const { formatMessage, labels } = useMessages();
const { resolveUrl } = usePageQuery();
const Title = () => {
return (
<>
<Link href={resolveUrl({ view: undefined })}>
<Link href={resolveUrl({ event: undefined })}>
<Button>
<Icon rotate={180}>
<Icons.ArrowRight />
@ -20,7 +20,7 @@ export function EventDataTable({ data = [], field }) {
<Text>{formatMessage(labels.back)}</Text>
</Button>
</Link>
<Text>{field}</Text>
<Text>{event}</Text>
</>
);
};
@ -31,6 +31,7 @@ export function EventDataTable({ data = [], field }) {
{data.length <= 0 && <Empty />}
{data.length > 0 && (
<GridTable data={data}>
<GridColumn name="field" label={formatMessage(labels.field)} />
<GridColumn name="value" label={formatMessage(labels.value)} />
<GridColumn name="total" label={formatMessage(labels.totalRecords)} width="200px">
{({ total }) => total.toLocaleString()}
@ -41,4 +42,4 @@ export function EventDataTable({ data = [], field }) {
);
}
export default EventDataTable;
export default EventDataValueTable;

View File

@ -1,17 +1,26 @@
import { useCallback } from 'react';
import { useRouter } from 'next/router';
import DataTable from 'components/metrics/DataTable';
import useLocale from 'hooks/useLocale';
import useCountryNames from 'hooks/useCountryNames';
import useMessages from 'hooks/useMessages';
import classNames from 'classnames';
import styles from './RealtimeCountries.module.css';
export function RealtimeCountries({ data }) {
const { formatMessage, labels } = useMessages();
const { locale } = useLocale();
const countryNames = useCountryNames(locale);
const { basePath } = useRouter();
const renderCountryName = useCallback(
({ x }) => <span className={locale}>{countryNames[x]}</span>,
[countryNames, locale],
({ x: code }) => (
<span className={classNames(locale, styles.row)}>
<img src={`${basePath}/images/flags/${code?.toLowerCase() || 'xx'}.png`} alt={code} />
{countryNames[code]}
</span>
),
[countryNames, locale, basePath],
);
return (

View File

@ -0,0 +1,5 @@
.row {
display: flex;
align-items: center;
gap: 10px;
}

View File

@ -52,7 +52,7 @@ export function RealtimeLog({ data, websiteDomain }) {
const getTime = ({ createdAt }) => dateFormat(new Date(createdAt), 'pp', locale);
const getColor = ({ sessionId }) => stringToColor(sessionId);
const getColor = ({ id, sessionId }) => stringToColor(sessionId || id);
const getIcon = ({ __type }) => icons[__type];

View File

@ -93,9 +93,7 @@ export function RealtimePage({ websiteId }) {
<Page loading={isLoading} error={error}>
<WebsiteHeader websiteId={websiteId} />
<RealtimeHeader websiteId={websiteId} data={currentData} />
<div className={styles.chart}>
<RealtimeChart data={realtimeData} unit="minute" records={REALTIME_RANGE} />
</div>
<RealtimeChart className={styles.chart} data={realtimeData} unit="minute" />
<GridRow>
<GridColumn xs={12} sm={12} md={12} lg={4} xl={4}>
<RealtimeUrls websiteId={websiteId} websiteDomain={website?.domain} data={realtimeData} />

View File

@ -1,10 +1,10 @@
import { useState } from 'react';
import { createPortal } from 'react-dom';
import { REPORT_PARAMETERS } from 'lib/constants';
import PopupForm from '../PopupForm';
import FieldSelectForm from '../FieldSelectForm';
import FieldAggregateForm from '../FieldAggregateForm';
import FieldFilterForm from '../FieldFilterForm';
import PopupForm from './PopupForm';
import FieldSelectForm from './FieldSelectForm';
import FieldAggregateForm from './FieldAggregateForm';
import FieldFilterForm from './FieldFilterForm';
import styles from './FieldAddForm.module.css';
export function FieldAddForm({ fields = [], group, element, onAdd, onClose }) {

View File

@ -19,6 +19,10 @@ export default function FieldAggregateForm({ name, type, onSelect }) {
{ label: formatMessage(labels.total), value: 'total' },
{ label: formatMessage(labels.unique), value: 'unique' },
],
uuid: [
{ label: formatMessage(labels.total), value: 'total' },
{ label: formatMessage(labels.unique), value: 'unique' },
],
};
const items = options[type];

View File

@ -9,10 +9,10 @@ export default function FieldSelectForm({ fields, onSelect }) {
<Form>
<FormRow label={formatMessage(labels.fields)}>
<Menu className={styles.menu} onSelect={key => onSelect(fields[key])}>
{fields.map(({ name, type }, index) => {
{fields.map(({ label, name, type }, index) => {
return (
<Item key={index} className={styles.item}>
<div>{name}</div>
<div>{label || name}</div>
<div className={styles.type}>{type}</div>
</Item>
);

View File

@ -3,20 +3,10 @@ import { Button, Icons, Text, Icon } from 'react-basics';
import Page from 'components/layout/Page';
import PageHeader from 'components/layout/PageHeader';
import Funnel from 'assets/funnel.svg';
import Nodes from 'assets/nodes.svg';
import Lightbulb from 'assets/lightbulb.svg';
import styles from './ReportTemplates.module.css';
import { useMessages } from 'hooks';
const reports = [
{
title: 'Funnel',
description: 'Understand the conversion and drop-off rate of users.',
url: '/reports/funnel',
icon: <Funnel />,
},
];
function ReportItem({ title, description, url, icon }) {
return (
<div className={styles.report}>
@ -42,6 +32,23 @@ function ReportItem({ title, description, url, icon }) {
export function ReportTemplates() {
const { formatMessage, labels } = useMessages();
const reports = [
/*
{
title: formatMessage(labels.insights),
description: 'Dive deeper into your data by using segments and filters.',
url: '/reports/insights',
icon: <Lightbulb />,
},
*/
{
title: formatMessage(labels.funnel),
description: 'Understand the conversion and drop-off rate of users.',
url: '/reports/funnel',
icon: <Funnel />,
},
];
return (
<Page>
<PageHeader title={formatMessage(labels.reports)} />

View File

@ -1,9 +1,12 @@
import Link from 'next/link';
import { Button, Text, Icon, Icons } from 'react-basics';
import { useState } from 'react';
import { Flexbox, Icon, Icons, Text, Button, Modal } from 'react-basics';
import LinkButton from 'components/common/LinkButton';
import SettingsTable from 'components/common/SettingsTable';
import useMessages from 'hooks/useMessages';
import ConfirmDeleteForm from 'components/common/ConfirmDeleteForm';
import { useMessages } from 'hooks';
export function ReportsTable({ data = [] }) {
export function ReportsTable({ data = [], onDelete = () => {} }) {
const [report, setReport] = useState(null);
const { formatMessage, labels } = useMessages();
const columns = [
@ -13,23 +16,39 @@ export function ReportsTable({ data = [] }) {
{ name: 'action', label: ' ' },
];
return (
<SettingsTable columns={columns} data={data}>
{row => {
const { id } = row;
const handleConfirm = () => {
onDelete(report.id);
};
return (
<Link href={`/reports/${id}`}>
<Button>
<Icon>
<Icons.ArrowRight />
</Icon>
<Text>{formatMessage(labels.view)}</Text>
</Button>
</Link>
);
}}
</SettingsTable>
return (
<>
<SettingsTable columns={columns} data={data}>
{row => {
const { id } = row;
return (
<Flexbox gap={10}>
<LinkButton href={`/reports/${id}`}>{formatMessage(labels.view)}</LinkButton>
<Button onClick={() => setReport(row)}>
<Icon>
<Icons.Trash />
</Icon>
<Text>{formatMessage(labels.delete)}</Text>
</Button>
</Flexbox>
);
}}
</SettingsTable>
{report && (
<Modal>
<ConfirmDeleteForm
name={report.name}
onConfirm={handleConfirm}
onClose={() => setReport(null)}
/>
</Modal>
)}
</>
);
}

View File

@ -5,7 +5,7 @@ import { ReportContext } from 'components/pages/reports/Report';
import Empty from 'components/common/Empty';
import { DATA_TYPES, REPORT_PARAMETERS } from 'lib/constants';
import Icons from 'components/icons';
import FieldAddForm from './FieldAddForm';
import FieldAddForm from '../FieldAddForm';
import BaseParameters from '../BaseParameters';
import ParameterList from '../ParameterList';
import styles from './EventDataParameters.module.css';
@ -54,9 +54,11 @@ export function EventDataParameters() {
};
const handleAdd = (group, value) => {
const data = parameterData[group].filter(({ name }) => name !== value.name);
const data = parameterData[group];
updateReport({ parameters: { [group]: data.concat(value) } });
if (!data.find(({ name }) => name === value.name)) {
updateReport({ parameters: { [group]: data.concat(value) } });
}
};
const handleRemove = (group, index) => {

View File

@ -6,13 +6,12 @@ import { ReportContext } from '../Report';
export function FunnelTable() {
const { report } = useContext(ReportContext);
const { formatMessage, labels } = useMessages();
return (
<DataTable
data={report?.data}
title={formatMessage(labels.url)}
metric={formatMessage(labels.visitors)}
showPercentage={false}
showPercentage={true}
/>
);
}

View File

@ -1,44 +0,0 @@
import { useState } from 'react';
import { createPortal } from 'react-dom';
import { REPORT_PARAMETERS } from 'lib/constants';
import PopupForm from '../PopupForm';
import FieldSelectForm from '../FieldSelectForm';
import FieldAggregateForm from '../FieldAggregateForm';
import FieldFilterForm from '../FieldFilterForm';
import styles from './FieldAddForm.module.css';
export function FieldAddForm({ fields = [], group, element, onAdd, onClose }) {
const [selected, setSelected] = useState();
const handleSelect = value => {
const { type } = value;
if (group === REPORT_PARAMETERS.groups || type === 'array' || type === 'boolean') {
value.value = group === REPORT_PARAMETERS.groups ? '' : 'total';
handleSave(value);
return;
}
setSelected(value);
};
const handleSave = value => {
onAdd(group, value);
onClose();
};
return createPortal(
<PopupForm className={styles.popup} element={element} onClose={onClose}>
{!selected && <FieldSelectForm fields={fields} onSelect={handleSelect} />}
{selected && group === REPORT_PARAMETERS.fields && (
<FieldAggregateForm {...selected} onSelect={handleSave} />
)}
{selected && group === REPORT_PARAMETERS.filters && (
<FieldFilterForm {...selected} onSelect={handleSave} />
)}
</PopupForm>,
document.body,
);
}
export default FieldAddForm;

View File

@ -1,38 +0,0 @@
.menu {
width: 360px;
max-height: 300px;
overflow: auto;
}
.item {
display: flex;
flex-direction: row;
justify-content: space-between;
border-radius: var(--border-radius);
}
.item:hover {
background: var(--base75);
}
.type {
color: var(--font-color300);
}
.selected {
font-weight: bold;
}
.popup {
display: flex;
}
.filter {
display: flex;
flex-direction: column;
gap: 20px;
}
.dropdown {
min-width: 60px;
}

View File

@ -1,42 +1,22 @@
import { useContext, useRef } from 'react';
import { useApi, useMessages } from 'hooks';
import { useMessages } from 'hooks';
import { Form, FormRow, FormButtons, SubmitButton, PopupTrigger, Icon, Popup } from 'react-basics';
import { ReportContext } from 'components/pages/reports/Report';
import Empty from 'components/common/Empty';
import { DATA_TYPES, REPORT_PARAMETERS } from 'lib/constants';
import { REPORT_PARAMETERS, WEBSITE_EVENT_FIELDS } from 'lib/constants';
import Icons from 'components/icons';
import FieldAddForm from './FieldAddForm';
import BaseParameters from '../BaseParameters';
import FieldAddForm from '../FieldAddForm';
import ParameterList from '../ParameterList';
import styles from './InsightsParameters.module.css';
function useFields(websiteId, startDate, endDate) {
const { get, useQuery } = useApi();
const { data, error, isLoading } = useQuery(
['fields', websiteId, startDate, endDate],
() =>
get('/reports/event-data', {
websiteId,
startAt: +startDate,
endAt: +endDate,
}),
{ enabled: !!(websiteId && startDate && endDate) },
);
return { data, error, isLoading };
}
export function InsightsParameters() {
const { report, runReport, updateReport, isRunning } = useContext(ReportContext);
const { formatMessage, labels, messages } = useMessages();
const { formatMessage, labels } = useMessages();
const ref = useRef(null);
const { parameters } = report || {};
const { websiteId, dateRange, fields, filters, groups } = parameters || {};
const { startDate, endDate } = dateRange || {};
const queryEnabled = websiteId && dateRange && fields?.length;
const { data, error } = useFields(websiteId, startDate, endDate);
const parametersSelected = websiteId && startDate && endDate;
const hasData = data?.length !== 0;
const fieldOptions = Object.keys(WEBSITE_EVENT_FIELDS).map(key => WEBSITE_EVENT_FIELDS[key]);
const parameterGroups = [
{ label: formatMessage(labels.fields), group: REPORT_PARAMETERS.fields },
@ -78,10 +58,7 @@ export function InsightsParameters() {
{(close, element) => {
return (
<FieldAddForm
fields={data.map(({ eventKey, InsightsType }) => ({
name: eventKey,
type: DATA_TYPES[InsightsType],
}))}
fields={fieldOptions}
group={group}
element={element}
onAdd={handleAdd}
@ -95,50 +72,43 @@ export function InsightsParameters() {
};
return (
<Form ref={ref} values={parameters} error={error} onSubmit={handleSubmit}>
<Form ref={ref} values={parameters} onSubmit={handleSubmit}>
<BaseParameters />
{!hasData && <Empty message={formatMessage(messages.noInsights)} />}
{parametersSelected &&
hasData &&
parameterGroups.map(({ label, group }) => {
return (
<FormRow
key={label}
label={label}
action={<AddButton group={group} onAdd={handleAdd} />}
{parameterGroups.map(({ label, group }) => {
return (
<FormRow key={label} label={label} action={<AddButton group={group} onAdd={handleAdd} />}>
<ParameterList
items={parameterData[group]}
onRemove={index => handleRemove(group, index)}
>
<ParameterList
items={parameterData[group]}
onRemove={index => handleRemove(group, index)}
>
{({ name, value }) => {
return (
<div className={styles.parameter}>
{group === REPORT_PARAMETERS.fields && (
<>
<div>{name}</div>
<div className={styles.op}>{value}</div>
</>
)}
{group === REPORT_PARAMETERS.filters && (
<>
<div>{name}</div>
<div className={styles.op}>{value[0]}</div>
<div>{value[1]}</div>
</>
)}
{group === REPORT_PARAMETERS.groups && (
<>
<div>{name}</div>
</>
)}
</div>
);
}}
</ParameterList>
</FormRow>
);
})}
{({ name, value }) => {
return (
<div className={styles.parameter}>
{group === REPORT_PARAMETERS.fields && (
<>
<div>{name}</div>
<div className={styles.op}>{value}</div>
</>
)}
{group === REPORT_PARAMETERS.filters && (
<>
<div>{name}</div>
<div className={styles.op}>{value[0]}</div>
<div>{value[1]}</div>
</>
)}
{group === REPORT_PARAMETERS.groups && (
<>
<div>{name}</div>
</>
)}
</div>
);
}}
</ParameterList>
</FormRow>
);
})}
<FormButtons>
<SubmitButton variant="primary" disabled={!queryEnabled} loading={isRunning}>
{formatMessage(labels.runQuery)}

View File

@ -10,6 +10,7 @@ import {
} from 'react-basics';
import { useEffect, useMemo, useRef, useState } from 'react';
import { getRandomChars } from 'next-basics';
import { useRouter } from 'next/router';
import useApi from 'hooks/useApi';
import useMessages from 'hooks/useMessages';
@ -20,12 +21,16 @@ export function ShareUrl({ websiteId, data, onSave }) {
const { name, shareId } = data;
const [id, setId] = useState(shareId);
const { post, useMutation } = useApi();
const { basePath } = useRouter();
const { mutate, error } = useMutation(({ shareId }) =>
post(`/websites/${websiteId}`, { shareId }),
);
const ref = useRef(null);
const url = useMemo(
() => `${process.env.analyticsUrl || location.origin}/share/${id}/${encodeURIComponent(name)}`,
() =>
`${process.env.analyticsUrl || location.origin}${basePath}/share/${id}/${encodeURIComponent(
name,
)}`,
[id, name],
);

View File

@ -1,7 +1,7 @@
import { useMemo } from 'react';
import PageviewsChart from 'components/metrics/PageviewsChart';
import { useApi, useDateRange, useTimezone, usePageQuery } from 'hooks';
import { getDateArray, getDateLength } from 'lib/date';
import { getDateArray } from 'lib/date';
export function WebsiteChart({ websiteId }) {
const [dateRange] = useDateRange(websiteId);
@ -43,17 +43,9 @@ export function WebsiteChart({ websiteId }) {
};
}
return { pageviews: [], sessions: [] };
}, [data, startDate, endDate, unit, modified]);
}, [data, startDate, endDate, unit]);
return (
<PageviewsChart
websiteId={websiteId}
data={chartData}
unit={unit}
records={getDateLength(startDate, endDate, unit)}
loading={isLoading}
/>
);
return <PageviewsChart websiteId={websiteId} data={chartData} unit={unit} loading={isLoading} />;
}
export default WebsiteChart;

View File

@ -41,7 +41,7 @@ export default function WebsiteChartList({ websites, showCharts, limit }) {
</Link>
</WebsiteHeader>
<WebsiteMetricsBar websiteId={id} />
<WebsiteChart websiteId={id} showChart={showCharts} />
{showCharts && <WebsiteChart websiteId={id} />}
</div>
) : null;
})}

View File

@ -5,18 +5,18 @@ import { EventDataMetricsBar } from 'components/pages/event-data/EventDataMetric
import { useDateRange, useApi, usePageQuery } from 'hooks';
import styles from './WebsiteEventData.module.css';
function useFields(websiteId, field) {
function useData(websiteId, event) {
const [dateRange] = useDateRange(websiteId);
const { startDate, endDate } = dateRange;
const { get, useQuery } = useApi();
const { data, error, isLoading } = useQuery(
['event-data:fields', { websiteId, startDate, endDate, field }],
['event-data:events', { websiteId, startDate, endDate, event }],
() =>
get('/event-data/fields', {
get('/event-data/events', {
websiteId,
startAt: +startDate,
endAt: +endDate,
field,
event,
}),
{ enabled: !!(websiteId && startDate && endDate) },
);
@ -26,15 +26,15 @@ function useFields(websiteId, field) {
export default function WebsiteEventData({ websiteId }) {
const {
query: { view },
query: { event },
} = usePageQuery();
const { data } = useFields(websiteId, view);
const { data } = useData(websiteId, event);
return (
<Flexbox className={styles.container} direction="column" gap={20}>
<EventDataMetricsBar websiteId={websiteId} />
{!view && <EventDataTable data={data} />}
{view && <EventDataValueTable field={view} data={data} />}
{!event && <EventDataTable data={data} />}
{event && <EventDataValueTable event={event} data={data} />}
</Flexbox>
);
}

View File

@ -4,9 +4,9 @@ import Link from 'next/link';
import { useRouter } from 'next/router';
import Favicon from 'components/common/Favicon';
import ActiveUsers from 'components/metrics/ActiveUsers';
import styles from './WebsiteHeader.module.css';
import Icons from 'components/icons';
import { useMessages, useWebsite } from 'hooks';
import styles from './WebsiteHeader.module.css';
export function WebsiteHeader({ websiteId, showLinks = true, children }) {
const { formatMessage, labels } = useMessages();
@ -42,11 +42,11 @@ export function WebsiteHeader({ websiteId, showLinks = true, children }) {
<Column className={styles.title} variant="two">
<Favicon domain={domain} />
<Text>{name}</Text>
<ActiveUsers websiteId={websiteId} />
</Column>
<Column className={styles.actions} variant="two">
<ActiveUsers websiteId={websiteId} />
{showLinks && (
<Flexbox alignItems="center">
<div className={styles.links}>
{links.map(({ label, icon, path }) => {
const selected = path ? pathname.endsWith(path) : pathname === '/websites/[id]';
@ -58,13 +58,13 @@ export function WebsiteHeader({ websiteId, showLinks = true, children }) {
[styles.selected]: selected,
})}
>
<Icon>{icon}</Icon>
<Text>{label}</Text>
<Icon className={styles.icon}>{icon}</Icon>
<Text className={styles.label}>{label}</Text>
</Button>
</Link>
);
})}
</Flexbox>
</div>
)}
{children}
</Column>

View File

@ -27,3 +27,29 @@
.selected {
font-weight: bold;
}
.links {
display: flex;
flex-direction: row;
align-items: center;
}
@media only screen and (max-width: 768px) {
.links {
justify-content: space-evenly;
flex: 1;
border-bottom: 1px solid var(--base300);
padding-bottom: 10px;
margin-bottom: 10px;
}
.label {
display: none;
}
.icon,
.icon svg {
width: 30px;
height: 30px;
}
}

View File

@ -7,7 +7,11 @@ import WebsiteHeader from './WebsiteHeader';
export function WebsiteReportsPage({ websiteId }) {
const { formatMessage, labels } = useMessages();
const { reports, error, isLoading } = useReports(websiteId);
const { reports, error, isLoading, deleteReport } = useReports(websiteId);
const handleDelete = async id => {
await deleteReport(id);
};
return (
<Page loading={isLoading} error={error}>
@ -22,7 +26,7 @@ export function WebsiteReportsPage({ websiteId }) {
</Button>
</Link>
</Flexbox>
<ReportsTable websiteId={websiteId} data={reports} />
<ReportsTable data={reports} onDelete={handleDelete} />
</Page>
);
}

View File

@ -6,7 +6,7 @@ CREATE TABLE umami.website_event
website_id UUID,
session_id UUID,
event_id UUID,
--session
--sessions
hostname LowCardinality(String),
browser LowCardinality(String),
os LowCardinality(String),
@ -17,14 +17,14 @@ CREATE TABLE umami.website_event
subdivision1 LowCardinality(String),
subdivision2 LowCardinality(String),
city String,
--pageview
--pageviews
url_path String,
url_query String,
referrer_path String,
referrer_query String,
referrer_domain String,
page_title String,
--event
--events
event_type UInt32,
event_name String,
created_at DateTime('UTC'),
@ -38,7 +38,7 @@ CREATE TABLE umami.website_event_queue (
website_id UUID,
session_id UUID,
event_id UUID,
--session
--sessions
hostname LowCardinality(String),
browser LowCardinality(String),
os LowCardinality(String),
@ -49,14 +49,14 @@ CREATE TABLE umami.website_event_queue (
subdivision1 LowCardinality(String),
subdivision2 LowCardinality(String),
city String,
--pageview
--pageviews
url_path String,
url_query String,
referrer_path String,
referrer_query String,
referrer_domain String,
page_title String,
--event
--events
event_type UInt32,
event_name String,
created_at DateTime('UTC'),
@ -66,11 +66,11 @@ CREATE TABLE umami.website_event_queue (
)
ENGINE = Kafka
SETTINGS kafka_broker_list = 'domain:9092,domain:9093,domain:9094', -- input broker list
kafka_topic_list = 'event',
kafka_topic_list = 'events',
kafka_group_name = 'event_consumer_group',
kafka_format = 'JSONEachRow',
kafka_max_block_size = 1048576,
kafka_handle_error_mode = 'stream'
kafka_handle_error_mode = 'stream';
CREATE MATERIALIZED VIEW umami.website_event_queue_mv TO umami.website_event AS
SELECT website_id,
@ -108,7 +108,7 @@ SETTINGS index_granularity = 8192 AS
SELECT _error AS error,
_raw_message AS raw
FROM umami.website_event_queue
WHERE length(_error) > 0
WHERE length(_error) > 0;
CREATE TABLE umami.event_data
(
@ -151,7 +151,7 @@ SETTINGS kafka_broker_list = 'domain:9092,domain:9093,domain:9094', -- input bro
kafka_group_name = 'event_data_consumer_group',
kafka_format = 'JSONEachRow',
kafka_max_block_size = 1048576,
kafka_handle_error_mode = 'stream'
kafka_handle_error_mode = 'stream';
CREATE MATERIALIZED VIEW umami.event_data_queue_mv TO umami.event_data AS
SELECT website_id,
@ -178,4 +178,4 @@ SETTINGS index_granularity = 8192 AS
SELECT _error AS error,
_raw_message AS raw
FROM umami.event_data_queue
WHERE length(_error) > 0
WHERE length(_error) > 0;

View File

@ -97,8 +97,8 @@ model WebsiteEvent {
model EventData {
id String @id() @map("event_data_id") @db.VarChar(36)
websiteEventId String @map("website_event_id") @db.VarChar(36)
websiteId String @map("website_id") @db.VarChar(36)
websiteEventId String @map("website_event_id") @db.VarChar(36)
eventKey String @map("event_key") @db.VarChar(500)
stringValue String? @map("string_value") @db.VarChar(500)
numberValue Decimal? @map("number_value") @db.Decimal(19, 4)

View File

@ -21,7 +21,7 @@ export function useConfig() {
}
}, []);
return config || {};
return config;
}
export default useConfig;

View File

@ -1,20 +1,43 @@
import { parseDateRange } from 'lib/date';
import { getMinimumUnit, parseDateRange } from 'lib/date';
import { setItem } from 'next-basics';
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE } from 'lib/constants';
import useLocale from './useLocale';
import websiteStore, { setWebsiteDateRange } from 'store/websites';
import appStore, { setDateRange } from 'store/app';
import useApi from './useApi';
export function useDateRange(websiteId) {
const { get } = useApi();
const { locale } = useLocale();
const websiteConfig = websiteStore(state => state[websiteId]?.dateRange);
const defaultConfig = DEFAULT_DATE_RANGE;
const globalConfig = appStore(state => state.dateRange);
const dateRange = parseDateRange(websiteConfig || globalConfig || defaultConfig, locale);
const saveDateRange = value => {
const saveDateRange = async value => {
if (websiteId) {
setWebsiteDateRange(websiteId, value);
let dateRange = value;
if (typeof value === 'string') {
if (value === 'all') {
const result = await get(`/websites/${websiteId}/daterange`);
const { mindate, maxdate } = result;
const startDate = new Date(mindate);
const endDate = new Date(maxdate);
dateRange = {
startDate,
endDate,
unit: getMinimumUnit(startDate, endDate),
value,
};
} else {
dateRange = parseDateRange(value, locale);
}
}
setWebsiteDateRange(websiteId, dateRange);
} else {
setItem(DATE_RANGE_CONFIG, value);
setDateRange(value);

View File

@ -24,6 +24,7 @@ export function useFilters() {
boolean: ['t', 'f'],
number: ['eq', 'neq', 'gt', 'lt', 'gte', 'lte'],
date: ['be', 'af'],
uuid: ['eq'],
};
return { filters, types };

View File

@ -1,10 +1,23 @@
import { useState } from 'react';
import useApi from './useApi';
export function useReports(websiteId) {
const { get, useQuery } = useApi();
const { data, error, isLoading } = useQuery(['reports'], () => get(`/reports`, { websiteId }));
const [modified, setModified] = useState(Date.now());
const { get, useQuery, del, useMutation } = useApi();
const { mutate } = useMutation(reportId => del(`/reports/${reportId}`));
const { data, error, isLoading } = useQuery(['reports:website', { websiteId, modified }], () =>
get(`/reports`, { websiteId }),
);
return { reports: data, error, isLoading };
const deleteReport = id => {
mutate(id, {
onSuccess: () => {
setModified(Date.now());
},
});
};
return { reports: data, error, isLoading, deleteReport };
}
export default useReports;

View File

@ -39,9 +39,11 @@
"label.devices": "Devices",
"label.dismiss": "Dismiss",
"label.domain": "Domain",
"label.dropoff": "Dropoff",
"label.edit": "Edit",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Enable share URL",
"label.event": "Event",
"label.event-data": "Event Data",
"label.events": "Events",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combined",
"label.filter-raw": "Raw",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "You do not have any websites configured.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "الأجهزة",
"label.dismiss": "اخفاء",
"label.domain": "النطاق",
"label.dropoff": "Dropoff",
"label.edit": "تعديل",
"label.edit-dashboard": "تعديل لوحة التحكم",
"label.enable-share-url": "تفعيل مشاركة الرابط",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "الأحداث",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "مجمعة",
"label.filter-raw": "مفصلة",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "انضمام",
"label.join-team": "الانضمام للمجموعة",
"label.language": "اللغة",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "هذه المجموعة ليس لديه اي موقع.",
"messages.no-websites-configured": "لم تقم بإعداد اي موقع.",
"messages.team-websites-info": "يمكن مشاهدة الموقع من اي عضو في المجموعة."
"messages.team-websites-info": "يمكن مشاهدة الموقع من اي عضو في المجموعة.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Прылады",
"label.dismiss": "Адмена",
"label.domain": "Дамен",
"label.dropoff": "Dropoff",
"label.edit": "Змяніць",
"label.edit-dashboard": "Змяніць інфармацыйную панэль",
"label.enable-share-url": "Дазволіць дзяліцца спасылкай",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Падзеі",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Камбініаваны",
"label.filter-raw": "Сырыя",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Мова",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Вы не наладзілі ніводнага сайту.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "ডিভাইস গুলো",
"label.dismiss": "বাতিল",
"label.domain": "ডোমেইন",
"label.dropoff": "Dropoff",
"label.edit": "সম্পাদনা করুন",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "শেয়ার ইউআরএল শেয়ার করুন",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "ঘটনা",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "সম্মিলিত",
"label.filter-raw": "অপরিশোধিত",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "ভাষা",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "কোনও ওয়েবসাইট কনফিগার করা নেই।",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Dispositius",
"label.dismiss": "Descarta",
"label.domain": "Domini",
"label.dropoff": "Dropoff",
"label.edit": "Edita",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Activa l'enllaç per compartir",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Esdeveniments",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combinat",
"label.filter-raw": "En cru",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "No hi ha cap lloc web configurat.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Zařízení",
"label.dismiss": "Odejít",
"label.domain": "Doména",
"label.dropoff": "Dropoff",
"label.edit": "Upravit",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Povolit sdílení URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Události",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Kombinace",
"label.filter-raw": "Nezpracované",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Nemáte nastavený žádný web.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Enheder",
"label.dismiss": "Afvis",
"label.domain": "Domæne",
"label.dropoff": "Dropoff",
"label.edit": "Rediger",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Aktivér delings-URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Hændelser",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Kombineret",
"label.filter-raw": "Rå",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Sprog",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Du har ikke konfigureret nogen hjemmesider.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Grät",
"label.dismiss": "Verwerfe",
"label.domain": "Domain",
"label.dropoff": "Dropoff",
"label.edit": "Bearbeite",
"label.edit-dashboard": "Dashboard bearbeite",
"label.enable-share-url": "Freigab-URL aktiviere",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Ereigniss",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Kombiniert",
"label.filter-raw": "Rohdate",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Biträte",
"label.join-team": "Team biträte",
"label.language": "Sprach",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "Dem Team sind kei Websiite zuegordnet.",
"messages.no-websites-configured": "Es isch kei Websiite vorhande.",
"messages.team-websites-info": "Websiite chönd vo jedem im Team agluegt werde"
"messages.team-websites-info": "Websiite chönd vo jedem im Team agluegt werde",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -3,7 +3,7 @@
"label.actions": "Aktionen",
"label.activity-log": "Aktivitätsverlauf",
"label.add": "Add",
"label.add-description": "Add description",
"label.add-description": "Beschreibung hinzufügen",
"label.add-website": "Webseite hinzufügen",
"label.admin": "Administrator",
"label.all": "Alle",
@ -39,16 +39,19 @@
"label.devices": "Geräte",
"label.dismiss": "Verwerfen",
"label.domain": "Domain",
"label.dropoff": "Dropoff",
"label.edit": "Bearbeiten",
"label.edit-dashboard": "Dashboard bearbeiten",
"label.enable-share-url": "Freigabe-URL aktivieren",
"label.event-data": "Event data",
"label.event": "Event",
"label.event-data": "Event daten",
"label.events": "Ereignisse",
"label.field": "Field",
"label.fields": "Fields",
"label.filter-combined": "Kombiniert",
"label.filter-raw": "Rohdaten",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Beitreten",
"label.join-team": "Team beitreten",
"label.language": "Sprache",
@ -74,7 +77,7 @@
"label.powered-by": "Betrieben durch {name}",
"label.profile": "Profil",
"label.queries": "Abfragen",
"label.query": "Query",
"label.query": "Abfrage",
"label.query-parameters": "Abfrageparameter",
"label.realtime": "Echtzeit",
"label.referrers": "Referrer",
@ -82,15 +85,15 @@
"label.regenerate": "Erneuern",
"label.regions": "Regionen",
"label.remove": "Entfernen",
"label.reports": "Reports",
"label.reports": "Reporte",
"label.required": "Erforderlich",
"label.reset": "Zurücksetzen",
"label.reset-website": "Statistik zurücksetzen",
"label.role": "Rolle",
"label.run-query": "Run query",
"label.run-query": "Abfrage starten",
"label.save": "Speichern",
"label.screens": "Bildschirmauflösungen",
"label.select-date": "Select date",
"label.select-date": "Datum auswählen",
"label.select-website": "Website auswählen",
"label.sessions": "Sessions",
"label.settings": "Einstellungen",
@ -124,31 +127,31 @@
"label.view-only": "View only",
"label.views": "Aufrufe",
"label.visitors": "Besucher",
"label.website": "Website",
"label.website": "Webseite",
"label.website-id": "Webseite ID",
"label.websites": "Webseiten",
"label.window": "Window",
"label.yesterday": "Gestern",
"labels.after": "After",
"labels.average": "Average",
"labels.average": "Durchschnitt",
"labels.before": "Before",
"labels.breakdown": "Breakdown",
"labels.contains": "Contains",
"labels.create-report": "Create report",
"labels.description": "Description",
"labels.create-report": "Report erstellen",
"labels.description": "Beschreibung",
"labels.does-not-contain": "Does not contain",
"labels.does-not-equal": "Does not equal",
"labels.equals": "Equals",
"labels.false": "False",
"labels.filters": "Filters",
"labels.greater-than": "Greater than",
"labels.greater-than-equals": "Greater than or equals",
"labels.less-than": "Less than",
"labels.less-than-equals": "Less than or equals",
"labels.greater-than": "Größer als",
"labels.greater-than-equals": "Größer oder gleich",
"labels.less-than": "Kleiner als",
"labels.less-than-equals": "Kleiner oder gleich",
"labels.max": "Max",
"labels.min": "Min",
"labels.overview": "Overview",
"labels.sum": "Sum",
"labels.overview": "Übersicht",
"labels.sum": "Summe",
"labels.total": "Total",
"labels.total-records": "Total records",
"labels.true": "True",
@ -184,8 +187,9 @@
"message.tracking-code": "Tracking Code",
"message.user-deleted": "Benutzer gelöscht.",
"message.visitor-log": "Besucher aus {country} benutzt {browser} auf {os} {device}",
"messages.no-results-found": "No results were found.",
"messages.no-results-found": "Keine Ergebnisse gefunden.",
"messages.no-team-websites": "Diesem Team sind keine Websites zugeordnet.",
"messages.no-websites-configured": "Es ist keine Webseite vorhanden.",
"messages.team-websites-info": "Webseiten können von jedem im Team eingesehen werden."
"messages.team-websites-info": "Webseiten können von jedem im Team eingesehen werden.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Συσκευές",
"label.dismiss": "Dismiss",
"label.domain": "Τομέας",
"label.dropoff": "Dropoff",
"label.edit": "Επεξεργασία",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Ενεργοποίηση κοινής χρήσης URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Γεγονότα",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Σε συνδυασμό",
"label.filter-raw": "Ακατέργαστο",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Δεν έχετε ρυθμίσει κανένα ιστότοπο.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Devices",
"label.dismiss": "Dismiss",
"label.domain": "Domain",
"label.dropoff": "Dropoff",
"label.edit": "Edit",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Enable share URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Events",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combined",
"label.filter-raw": "Raw",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "You don't have any websites configured.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Devices",
"label.dismiss": "Dismiss",
"label.domain": "Domain",
"label.dropoff": "Dropoff",
"label.edit": "Edit",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Enable share URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Events",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combined",
"label.filter-raw": "Raw",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "You do not have any websites configured.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

195
lang/es-ES.json Normal file
View File

@ -0,0 +1,195 @@
{
"label.access-code": "Código de acceso",
"label.actions": "Acciones",
"label.activity-log": "Registro de actividad",
"label.add": "Añadir",
"label.add-description": "Añadir descripción",
"label.add-website": "Nuevo sitio web",
"label.admin": "Administrador",
"label.all": "Todos",
"label.all-time": "Todos los tiempos",
"label.analytics": "Analíticas",
"label.average-visit-time": "Tiempo promedio de visita",
"label.back": "Atrás",
"label.bounce-rate": "Porcentaje de rebote",
"label.browsers": "Navegadores",
"label.cancel": "Cancelar",
"label.change-password": "Cambiar contraseña",
"label.cities": "Ciudades",
"label.clear-all": "Limpiar todo",
"label.confirm": "Confirmar",
"label.confirm-password": "Confirmar contraseña",
"label.continue": "Continuar",
"label.countries": "Países",
"label.create-team": "Crear equipo",
"label.create-user": "Crear usuario",
"label.created": "Creado",
"label.current-password": "Contraseña actual",
"label.custom-range": "Intervalo personalizado",
"label.dashboard": "Panel de control",
"label.data": "Datos",
"label.date-range": "Intervalo de fechas",
"label.default-date-range": "Intervalo por defecto",
"label.delete": "Eliminar",
"label.delete-team": "Eliminar equipo",
"label.delete-user": "Eliminar usuario",
"label.delete-website": "Eliminar sitio",
"label.desktop": "Escritorio",
"label.details": "Detalles",
"label.devices": "Dispositivos",
"label.dismiss": "Ignorar",
"label.domain": "Dominio",
"label.dropoff": "Dropoff",
"label.edit": "Editar",
"label.edit-dashboard": "Editar panel",
"label.enable-share-url": "Habilitar compartir URL",
"label.event": "Evento",
"label.event-data": "Datos de evento",
"label.events": "Eventos",
"label.field": "Campo",
"label.fields": "Campos",
"label.filter-combined": "Combinado",
"label.filter-raw": "En crudo",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Unir",
"label.join-team": "Unirse al equipo",
"label.language": "Idioma",
"label.languages": "Idiomas",
"label.laptop": "Portátil",
"label.last-days": "Últimos {x} días",
"label.last-hours": "Últimas {x} horas",
"label.leave": "Abandonar",
"label.leave-team": "Abandonar equipo",
"label.login": "Iniciar sesión",
"label.logout": "Cerrar sesión",
"label.members": "Miembros",
"label.mobile": "Móvil",
"label.more": "Más",
"label.name": "Nombre",
"label.new-password": "Nueva contraseña",
"label.none": "Ninguno",
"label.operating-systems": "Sistemas operativos",
"label.owner": "Propietario",
"label.page-views": "Vistas",
"label.pages": "Páginas",
"label.password": "Contraseña",
"label.powered-by": "Con la ayuda de {name}",
"label.profile": "Perfil",
"label.queries": "Consultas",
"label.query": "Query",
"label.query-parameters": "Parámetros de petición",
"label.realtime": "Tiempo real",
"label.referrers": "Referido desde",
"label.refresh": "Actualizar",
"label.regenerate": "Regenerar",
"label.regions": "Regiones",
"label.remove": "Quitar",
"label.reports": "Reportes",
"label.required": "Obligatorio",
"label.reset": "Reiniciar",
"label.reset-website": "Reiniciar estadísticas",
"label.role": "Rol",
"label.run-query": "Ejecutar consulta",
"label.save": "Guardar",
"label.screens": "Pantallas",
"label.select-date": "Seleccionar fecha",
"label.select-website": "Seleccionar sitio web",
"label.sessions": "Sesiones",
"label.settings": "Configuraciones",
"label.share-url": "Compartir URL",
"label.single-day": "Un solo día",
"label.tablet": "Tableta",
"label.team": "Equipo",
"label.team-guest": "Invitado al equipo",
"label.team-id": "ID de equipo",
"label.team-member": "Miembro del equipo",
"label.team-owner": "Admin. del equipo",
"label.teams": "Equipos",
"label.theme": "Tema",
"label.this-month": "Este mes",
"label.this-week": "Esta semana",
"label.this-year": "Este año",
"label.timezone": "Zona horaria",
"label.title": "Título",
"label.today": "Hoy",
"label.toggle-charts": "Alternar gráficas",
"label.tracking-code": "Código de rastreo",
"label.unique-visitors": "Visitantes únicos",
"label.unknown": "Desconocida",
"label.url": "URL",
"label.urls": "URLs",
"label.user": "Usuario",
"label.username": "Nombre de usuario",
"label.users": "Usuarios",
"label.view": "Visualizar",
"label.view-details": "Ver detalles",
"label.view-only": "Ver sólo",
"label.views": "Vistas",
"label.visitors": "Visitantes",
"label.website": "Sitio web",
"label.website-id": "ID del sitio web",
"label.websites": "Sitios web",
"label.window": "Ventana",
"label.yesterday": "Ayer",
"labels.after": "Después",
"labels.average": "Media",
"labels.before": "Antes",
"labels.breakdown": "Desglose",
"labels.contains": "Contiene",
"labels.create-report": "Crear reporte",
"labels.description": "Descripciones",
"labels.does-not-contain": "No contiene",
"labels.does-not-equal": "No es igual a",
"labels.equals": "Es igual a",
"labels.false": "False",
"labels.filters": "Filtros",
"labels.greater-than": "Mayor que",
"labels.greater-than-equals": "Mayor que o igual a",
"labels.less-than": "Menor que",
"labels.less-than-equals": "Menor que o igual a",
"labels.max": "Máx",
"labels.min": "Mín",
"labels.overview": "Resumen",
"labels.sum": "Suma",
"labels.total": "Total",
"labels.total-records": "Total de registros",
"labels.true": "Verdadero",
"labels.type": "Tipo",
"labels.unique": "Único",
"labels.untitled": "Sin título",
"labels.value": "Valor",
"message.active-users": "{x} {x, plural, one {activo} other {activos}}",
"message.confirm-delete": "¿Seguro que quieres eliminar {target}?",
"message.confirm-leave": "¿Seguro que quieres abandonar {target}?",
"message.confirm-reset": "¿Seguro que quieres BORRAR las analíticas de {target}?",
"message.delete-account": "Para borrar esta cuenta, escribe {confirmation} a continuación para confirmar.",
"message.delete-website": "Para borrar este sitio web, escribe {confirmation} a continuación para confirmar.",
"message.delete-website-warning": "Toda la información relacionada será eliminada.",
"message.error": "Algo falló.",
"message.event-log": "{event} en {url}",
"message.go-to-settings": "Ir a la configuración",
"message.incorrect-username-password": "Nombre de usuario o contraseña incorrectos.",
"message.invalid-domain": "Dominio inválido",
"message.min-password-length": "Longitud mínima de {n} caracteres",
"message.no-data-available": "No hay información disponible.",
"message.no-event-data": "No hay datos de eventos disponibles.",
"message.no-match-password": "Las contraseñas no coinciden",
"message.no-teams": "No has creado ningún equipo.",
"message.no-users": "No hay usuarios.",
"message.page-not-found": "Página no encontrada",
"message.reset-website": "Para reiniciar este sitio web, escribe {confirmation} a continuación para confirmar.",
"message.reset-website-warning": "Todas las estadísticas de esta página serán eliminadas, pero el código de rastreo permanecerá intacto.",
"message.saved": "Guardado.",
"message.share-url": "Esta es la URL pública para {target}.",
"message.team-already-member": "Ya eres miembro de este equipo.",
"message.team-not-found": "Equipo no encontrado.",
"message.tracking-code": "Código de rastreo",
"message.user-deleted": "Usuario eliminado.",
"message.visitor-log": "Visitante desde {country} usando {browser} en {os} {device}",
"messages.no-results-found": "No se encontraron resultados.",
"messages.no-team-websites": "Este equipo no tiene ningún sitio web configurado.",
"messages.no-websites-configured": "No tienes ningún sitio web configurado.",
"messages.team-websites-info": "Las analíticas de tus sitios web pueden ser vistas por cualquier miembro del equipo.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Dispositivos",
"label.dismiss": "Ignorar",
"label.domain": "Dominio",
"label.dropoff": "Dropoff",
"label.edit": "Editar",
"label.edit-dashboard": "Editar panel",
"label.enable-share-url": "Habilitar compartir URL",
"label.event": "Evento",
"label.event-data": "Event data",
"label.events": "Eventos",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combinado",
"label.filter-raw": "Personalizado",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Unir",
"label.join-team": "Unir a equipo",
"label.language": "Idioma",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "Este equipo no tiene ningún sitio web configurado.",
"messages.no-websites-configured": "No tienes ningún sitio configurado.",
"messages.team-websites-info": "Las analíticas de tus sitios pueden verse por cualquier miembro del equipo."
"messages.team-websites-info": "Las analíticas de tus sitios pueden verse por cualquier miembro del equipo.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "دستگاه‌ها",
"label.dismiss": "رد کردن",
"label.domain": "دامنه",
"label.dropoff": "Dropoff",
"label.edit": "ویرایش",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "فعال کردن اشتراک گذاری URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "رویدادها",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "ترکیب شده",
"label.filter-raw": "خام",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "زبان",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "شما هیچ وب‌سایتی را پیکربندی نکرده‌اید.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Laitteet",
"label.dismiss": "Hylkää",
"label.domain": "Verkkotunnus",
"label.dropoff": "Dropoff",
"label.edit": "Muokkaa",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Ota jakamisen URL-osoite käyttöön",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Tapahtumat",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Yhdistetty",
"label.filter-raw": "Käsittelemätön",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Kieli",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Sinulla ei ole määritettyjä verkkosivustoja.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Tóleindir",
"label.dismiss": "Lat fara",
"label.domain": "Økisnavn",
"label.dropoff": "Dropoff",
"label.edit": "Ger broyting",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Virkja deili leinki",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Hendingar/tiltøk",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Samansett",
"label.filter-raw": "Óviðgjørt",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Tú hevur ongar heimasíður stillaða til.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -2,8 +2,8 @@
"label.access-code": "Code d'accès",
"label.actions": "Actions",
"label.activity-log": "Journal d'activité",
"label.add": "Add",
"label.add-description": "Add description",
"label.add": "Ajouter",
"label.add-description": "Ajouter une description",
"label.add-website": "Ajouter un site",
"label.admin": "Administrateur",
"label.all": "Tout",
@ -39,16 +39,19 @@
"label.devices": "Appareils",
"label.dismiss": "Ignorer",
"label.domain": "Domaine",
"label.dropoff": "Dropoff",
"label.edit": "Modifier",
"label.edit-dashboard": "Modifier le tableau de bord",
"label.enable-share-url": "Activer l'URL de partage",
"label.event-data": "Event data",
"label.event": "Event",
"label.event-data": "Données d'événements",
"label.events": "Événements",
"label.field": "Field",
"label.fields": "Fields",
"label.field": "Champ",
"label.fields": "Champs",
"label.filter-combined": "Combiné",
"label.filter-raw": "Brut",
"label.funnel": "Funnel",
"label.funnel": "Entonnoir",
"label.insights": "Insights",
"label.join": "Rejoindre",
"label.join-team": "Rejoindre une équipe",
"label.language": "Langue",
@ -73,24 +76,24 @@
"label.password": "Mot de passe",
"label.powered-by": "Propulsé par {name}",
"label.profile": "Profil",
"label.queries": "Queries",
"label.query": "Query",
"label.queries": "Requêtes",
"label.query": "Requête",
"label.query-parameters": "Paramètres d'URL",
"label.realtime": "Temps réel",
"label.referrers": "Sources",
"label.referrers": "Sites référents",
"label.refresh": "Rafraîchir",
"label.regenerate": "Régénérer",
"label.regions": "Régions",
"label.remove": "Retirer",
"label.reports": "Reports",
"label.reports": "Rapports",
"label.required": "Requis",
"label.reset": "Réinitialiser",
"label.reset-website": "Réinitialiser les statistiques",
"label.role": "Rôle",
"label.run-query": "Run query",
"label.run-query": "Éxécuter la requête",
"label.save": "Enregistrer",
"label.screens": "Résolutions d'écran",
"label.select-date": "Select date",
"label.select-date": "Choisir une période",
"label.select-website": "Choisir un site",
"label.sessions": "Sessions",
"label.settings": "Paramètres",
@ -121,46 +124,46 @@
"label.users": "Utilisateurs",
"label.view": "Voir",
"label.view-details": "Voir les détails",
"label.view-only": "View only",
"label.view-only": "Consultation",
"label.views": "Vues",
"label.visitors": "Visiteurs",
"label.website": "Website",
"label.website-id": "ID de site",
"label.websites": "Sites",
"label.window": "Window",
"label.window": "Fenêtre",
"label.yesterday": "Hier",
"labels.after": "After",
"labels.average": "Average",
"labels.before": "Before",
"labels.breakdown": "Breakdown",
"labels.contains": "Contains",
"labels.create-report": "Create report",
"labels.after": "Après",
"labels.average": "Moyenne",
"labels.before": "Avant",
"labels.breakdown": "Répartition",
"labels.contains": "Contient",
"labels.create-report": "Créer un rapport",
"labels.description": "Description",
"labels.does-not-contain": "Does not contain",
"labels.does-not-equal": "Does not equal",
"labels.equals": "Equals",
"labels.false": "False",
"labels.filters": "Filters",
"labels.greater-than": "Greater than",
"labels.greater-than-equals": "Greater than or equals",
"labels.less-than": "Less than",
"labels.less-than-equals": "Less than or equals",
"labels.does-not-contain": "Ne contient pas",
"labels.does-not-equal": "N'est pas égal",
"labels.equals": "Est égal",
"labels.false": "Faux",
"labels.filters": "Filtres",
"labels.greater-than": "Supérieur à",
"labels.greater-than-equals": "Supérieur ou égal à",
"labels.less-than": "Inférieur à",
"labels.less-than-equals": "Inférieur ou égal à",
"labels.max": "Max",
"labels.min": "Min",
"labels.overview": "Overview",
"labels.sum": "Sum",
"labels.overview": "Vue d'ensemble",
"labels.sum": "Somme",
"labels.total": "Total",
"labels.total-records": "Total records",
"labels.true": "True",
"labels.total-records": "Nombre d'enregistrements",
"labels.true": "Vrai",
"labels.type": "Type",
"labels.unique": "Unique",
"labels.untitled": "Untitled",
"labels.value": "Value",
"labels.untitled": "Sans titre",
"labels.value": "Valeur",
"message.active-users": "{x} {x, plural, one {visiteur} other {visiteurs}} actuellement",
"message.confirm-delete": "Êtes-vous sûr de vouloir supprimer {target} ?",
"message.confirm-leave": "Êtes-vous sûr de vouloir quitter {target} ?",
"message.confirm-reset": "Êtes-vous sûr de vouloir réinitialiser les statistiques de {target} ?",
"message.delete-account": "To delete this account, type {confirmation} in the box below to confirm.",
"message.delete-account": "Pour supprimer ce compte, taper {confirmation} ci-dessous pour confirmer.",
"message.delete-website": "Pour supprimer ce site, taper {confirmation} ci-dessous pour confirmer.",
"message.delete-website-warning": "Toutes les données associées seront supprimées.",
"message.error": "Un problème est survenu.",
@ -170,12 +173,12 @@
"message.invalid-domain": "Domaine invalide",
"message.min-password-length": "Taille minimale de {n} caractères",
"message.no-data-available": "Aucune donnée disponible.",
"message.no-event-data": "No event data is available.",
"message.no-event-data": "Aucune donnée d'événement disponible.",
"message.no-match-password": "Les mots de passe ne correspondent pas",
"message.no-teams": "Vous n'avez créé aucune équipe.",
"message.no-users": "Il n'y aucun utilisateur.",
"message.no-teams": "Vous n'avez pas créé d'équipe.",
"message.no-users": "Aucun utilisateur.",
"message.page-not-found": "Page non trouvée.",
"message.reset-website": "To reset this website, type {confirmation} in the box below to confirm.",
"message.reset-website": "Pour réinitialiser ce site, taper {confirmation} ci-dessous pour confirmer.",
"message.reset-website-warning": "Toutes les statistiques pour ce site seront supprimées, mais votre code de suivi restera intact.",
"message.saved": "Enregistré avec succès.",
"message.share-url": "Les statistiques de votre site sont accessibles publiquement sur cette URL :",
@ -184,8 +187,9 @@
"message.tracking-code": "Code de suivi",
"message.user-deleted": "Utilisateur supprimé.",
"message.visitor-log": "Visiteur de {country} utilisant {browser} sur {os} {device}",
"messages.no-results-found": "No results were found.",
"messages.no-results-found": "Aucun résultat n'a été trouvé.",
"messages.no-team-websites": "Cette équipe n'a aucun site.",
"messages.no-websites-configured": "Vous n'avez configuré aucun site.",
"messages.team-websites-info": "Les sites peuvent être vus par tout utilisateur dans l'équipe."
"messages.no-websites-configured": "Vous n'avez pas configuré de site.",
"messages.team-websites-info": "Les sites peuvent être vus par tout utilisateur dans l'équipe.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Dispositivos",
"label.dismiss": "Desbotar",
"label.domain": "Dominio",
"label.dropoff": "Dropoff",
"label.edit": "Editar",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Activar URL de compartición",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Eventos",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combinado",
"label.filter-raw": "Raw",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Idioma",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Non tes sitios web configurados.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "מכשירים",
"label.dismiss": "שיחרור",
"label.domain": "דומיין",
"label.dropoff": "Dropoff",
"label.edit": "עריכה",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "הפעלת URL שיתוף",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "אירועים",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "משותף",
"label.filter-raw": "גולמי",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "לא מוגדרים אתרים",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "उपकरण",
"label.dismiss": "खारिज कीजिये",
"label.domain": "डोमेन",
"label.dropoff": "Dropoff",
"label.edit": "संपादित करें",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "शेयर URL सक्षम करें",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "स्पर्धाएँ",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "संयुक्त",
"label.filter-raw": "रॉ",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "आपके पास कोई वेबसाइट कॉन्फ़िगर नहीं है।",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Devices",
"label.dismiss": "Odbaci",
"label.domain": "Domena",
"label.dropoff": "Dropoff",
"label.edit": "Uredi",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Omogući dijeljenje poveznice",
"label.event": "Event",
"label.event-data": "Podaci događaja",
"label.events": "Events",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combined",
"label.filter-raw": "Raw",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Jezik",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "You do not have any websites configured.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Eszközök",
"label.dismiss": "Mellőzés",
"label.domain": "Domain",
"label.dropoff": "Dropoff",
"label.edit": "Módosítás",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "URL-megosztás engedélyezése",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Események",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Összevont",
"label.filter-raw": "Nyers",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Még nem állítottál be egyetlen weboldalt sem.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Perangkat",
"label.dismiss": "Tutup",
"label.domain": "Domain",
"label.dropoff": "Dropoff",
"label.edit": "Sunting",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Aktifkan URL berbagi",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Perihal",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Gabungan",
"label.filter-raw": "Mentah",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Bahasa",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Anda tidak memiliki situs web yang dikonfigurasi.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Dispositivi",
"label.dismiss": "Scarta",
"label.domain": "Dominio",
"label.dropoff": "Dropoff",
"label.edit": "Modifica",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Abilita URL di condivisione",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Eventi",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Aggregati",
"label.filter-raw": "Raw",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Lingua",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Non hai ancora configurato alcun sito.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "デバイス",
"label.dismiss": "無視する",
"label.domain": "ドメイン",
"label.dropoff": "Dropoff",
"label.edit": "編集",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "共有リンクを有効にする",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "イベント",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "パスまで",
"label.filter-raw": "すべて表示",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Webサイトが設定されていません。",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "ឧបករណ៍",
"label.dismiss": "បដិសេធ",
"label.domain": "ឈ្មោះគេហទំព័រ",
"label.dropoff": "Dropoff",
"label.edit": "កែប្រែ",
"label.edit-dashboard": "កែផ្ទាំងគ្រប់គ្រង",
"label.enable-share-url": "បើកការចែករំលែក URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "ព្រឹត្តិការណ៍",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "រួមបញ្ចូលគ្នា",
"label.filter-raw": "ដើម",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "ភាសា",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "អ្នកមិនទាន់បានដាក់គេហទំព័រណាមួយចូលទេ។",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "기기",
"label.dismiss": "무시하기",
"label.domain": "도메인",
"label.dropoff": "Dropoff",
"label.edit": "편집",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "URL 공유 활성화",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "이벤트",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "합쳐서 보기",
"label.filter-raw": "전체 보기",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "구성된 웹 사이트가 없습니다.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Įrenginiai",
"label.dismiss": "Gerai",
"label.domain": "Domenas",
"label.dropoff": "Dropoff",
"label.edit": "Redaguoti",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Įjungti bendrinimą su nuoroda",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Įvykiai",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Kombinuoti",
"label.filter-raw": "Neapdoroti",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Jūs nesate susikonfiguravę jokių svetainių.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Төхөөрөмж",
"label.dismiss": "Үл хэргэсэх",
"label.domain": "Домэйн",
"label.dropoff": "Dropoff",
"label.edit": "Засах",
"label.edit-dashboard": "Хянах самбар засах",
"label.enable-share-url": "Хуваалцах холбоос идэвхжүүлэх",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Үйлдэл",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Нэгтгэсэн",
"label.filter-raw": "Түүхий",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Нэгдэх",
"label.join-team": "Багт нэгдэх",
"label.language": "Хэл",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "Энэ багт ямар ч веб алга.",
"messages.no-websites-configured": "Та ямар нэгэн веб тохируулаагүй байна.",
"messages.team-websites-info": "Вебийг багийн бүх гишүүд үзэж болно."
"messages.team-websites-info": "Вебийг багийн бүх гишүүд үзэж болно.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Peranti",
"label.dismiss": "Ketepikan",
"label.domain": "Domain",
"label.dropoff": "Dropoff",
"label.edit": "Edit",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Aktifkan url berkongsi",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Peristiwa",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Digabungkan",
"label.filter-raw": "Mentah",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Anda tidak ada sebarang laman web yang telah dikonfigurasikan.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Enheter",
"label.dismiss": "Avbryt",
"label.domain": "Domene",
"label.dropoff": "Dropoff",
"label.edit": "Rediger",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Aktiver delings-URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Arrangementer",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Kombinert",
"label.filter-raw": "Rå",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Språk",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Du har ikke satt opp noen nettsteder.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Apparaten",
"label.dismiss": "Negeren",
"label.domain": "Domein",
"label.dropoff": "Dropoff",
"label.edit": "Bewerken",
"label.edit-dashboard": "Dashboard aanpassen",
"label.enable-share-url": "Sta delen via openbare URL toe",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Gebeurtenissen",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Gecombineerd",
"label.filter-raw": "Ruw",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Lid worden",
"label.join-team": "Word lid van een team",
"label.language": "Taal",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "Er zijn geen websites gekoppeld aan dit team.",
"messages.no-websites-configured": "Je hebt geen websites ingesteld.",
"messages.team-websites-info": "Websites kunnen door iedereen in het team worden bekeken."
"messages.team-websites-info": "Websites kunnen door iedereen in het team worden bekeken.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -2,8 +2,8 @@
"label.access-code": "Kod dostępu",
"label.actions": "Działania",
"label.activity-log": "Dziennik aktywności",
"label.add": "Add",
"label.add-description": "Add description",
"label.add": "Dodaj",
"label.add-description": "Dodaj opis",
"label.add-website": "Dodaj witrynę",
"label.admin": "Administrator",
"label.all": "Wszystkie",
@ -39,16 +39,19 @@
"label.devices": "Urządzenia",
"label.dismiss": "Odrzuć",
"label.domain": "Domena",
"label.dropoff": "Dropoff",
"label.edit": "Edytuj",
"label.edit-dashboard": "Edytuj panel",
"label.enable-share-url": "Włącz udostępnianie adresu URL",
"label.event-data": "Event data",
"label.event": "Event",
"label.event-data": "Dane zdarzenia",
"label.events": "Zdarzenia",
"label.field": "Field",
"label.fields": "Fields",
"label.field": "Pole",
"label.fields": "Pola",
"label.filter-combined": "Połączone",
"label.filter-raw": "Surowe dane",
"label.funnel": "Funnel",
"label.funnel": "Lejek",
"label.insights": "Insights",
"label.join": "Dołącz",
"label.join-team": "Dołącz do zespołu",
"label.language": "Język",
@ -74,23 +77,23 @@
"label.powered-by": "Obsługiwane przez {name}",
"label.profile": "Profil",
"label.queries": "Zapytania",
"label.query": "Query",
"label.query-parameters": "Parametry query",
"label.query": "Zapytanie",
"label.query-parameters": "Parametry zapytania",
"label.realtime": "Czas rzeczywisty",
"label.referrers": "Źródła odsyłające",
"label.refresh": "Odśwież",
"label.regenerate": "Wygeneruj ponownie",
"label.regions": "Regiony",
"label.remove": "Usuń",
"label.reports": "Reports",
"label.reports": "Raporty",
"label.required": "Wymagany",
"label.reset": "Zresetuj",
"label.reset-website": "Zresetuj statystyki",
"label.role": "Role",
"label.run-query": "Run query",
"label.run-query": "Uruchom zapytanie",
"label.save": "Zapisz",
"label.screens": "Ekrany",
"label.select-date": "Select date",
"label.select-date": "Wybierz datę",
"label.select-website": "Wybierz witrynę",
"label.sessions": "Sesje",
"label.settings": "Ustawienia",
@ -114,54 +117,54 @@
"label.tracking-code": "Kod śledzenia",
"label.unique-visitors": "Unikalni odwiedzający",
"label.unknown": "Nieznany",
"label.url": "URL",
"label.urls": "URLs",
"label.url": "Link",
"label.urls": "Linki",
"label.user": "Użytkownik",
"label.username": "Nazwa użytkownika",
"label.users": "Użytkownicy",
"label.view": "Zobacz",
"label.view-details": "Pokaż szczegóły",
"label.view-only": "View only",
"label.view-only": "Tylko do odczytu",
"label.views": "Wyświetlenia",
"label.visitors": "Odwiedzający",
"label.website": "Website",
"label.website": "Witryna",
"label.website-id": "ID witryny",
"label.websites": "Witryny",
"label.window": "Window",
"label.window": "Okno",
"label.yesterday": "Wczoraj",
"labels.after": "After",
"labels.average": "Average",
"labels.before": "Before",
"labels.breakdown": "Breakdown",
"labels.contains": "Contains",
"labels.create-report": "Create report",
"labels.description": "Description",
"labels.does-not-contain": "Does not contain",
"labels.does-not-equal": "Does not equal",
"labels.equals": "Equals",
"labels.false": "False",
"labels.filters": "Filters",
"labels.greater-than": "Greater than",
"labels.greater-than-equals": "Greater than or equals",
"labels.less-than": "Less than",
"labels.less-than-equals": "Less than or equals",
"labels.max": "Max",
"labels.after": "Po",
"labels.average": "Średnia",
"labels.before": "Przed",
"labels.breakdown": "Rozbicie",
"labels.contains": "Zawiera",
"labels.create-report": "Stwórz raport",
"labels.description": "Opis",
"labels.does-not-contain": "Nie zawiera",
"labels.does-not-equal": "Nie jest równe",
"labels.equals": "Równe",
"labels.false": "Fałsz",
"labels.filters": "Filtry",
"labels.greater-than": "Większe niż",
"labels.greater-than-equals": "Większe niż lub równe",
"labels.less-than": "Mniejsze niż",
"labels.less-than-equals": "Mniejsze niż lub równe",
"labels.max": "Maks",
"labels.min": "Min",
"labels.overview": "Overview",
"labels.sum": "Sum",
"labels.total": "Total",
"labels.total-records": "Total records",
"labels.true": "True",
"labels.type": "Type",
"labels.unique": "Unique",
"labels.untitled": "Untitled",
"labels.value": "Value",
"labels.overview": "Przegląd",
"labels.sum": "Suma",
"labels.total": "W sumie",
"labels.total-records": "Suma rekordów",
"labels.true": "Prawda",
"labels.type": "Typ",
"labels.unique": "Unikalne",
"labels.untitled": "Bez tytułu",
"labels.value": "Wartość",
"message.active-users": "{x} aktualnie {x, plural, one {odwiedzający} other {odwiedzających}}",
"message.confirm-delete": "Czy na pewno chcesz usunąć {target}?",
"message.confirm-leave": "Czy na pewno chcesz opuścić {target}?",
"message.confirm-reset": "Czy na pewno chcesz zresetować statystyki {target}?",
"message.delete-account": "To delete this account, type {confirmation} in the box below to confirm.",
"message.delete-website": "To delete this website, type {confirmation} in the box below to confirm.",
"message.delete-account": "Aby usunąć to konto, wpisz {confirmation} w polu poniżej, aby potwierdzić.",
"message.delete-website": "Aby usunąć tę stronę, wpisz {confirmation} w polu poniżej, aby potwierdzić.",
"message.delete-website-warning": "Wszystkie powiązane dane również zostaną usunięte.",
"message.error": "Coś poszło nie tak.",
"message.event-log": "{event} na {url}",
@ -170,7 +173,7 @@
"message.invalid-domain": "Nieprawidłowa witryna",
"message.min-password-length": "Minimalna długość {n} znaków",
"message.no-data-available": "Brak dostępnych danych.",
"message.no-event-data": "No event data is available.",
"message.no-event-data": "Brak dostępnych danych o zdarzeniach.",
"message.no-match-password": "Hasła się nie zgadzają",
"message.no-teams": "Nie stworzyłeś żadnych zespołów.",
"message.no-users": "Nie ma żadnych użytkowników.",
@ -184,8 +187,9 @@
"message.tracking-code": "Kod śledzenia",
"message.user-deleted": "Użytkownik usunięty.",
"message.visitor-log": "Odwiedzający z {country} używa {browser} na {os} {device}",
"messages.no-results-found": "No results were found.",
"messages.no-results-found": "Nie znaleziono wyników.",
"messages.no-team-websites": "Ten zespół nie ma żadnych witryn internetowych.",
"messages.no-websites-configured": "Nie masz skonfigurowanych żadnych witryn internetowych.",
"messages.team-websites-info": "Strony internetowe mogą być przeglądane przez każdego członka zespołu."
"messages.team-websites-info": "Strony internetowe mogą być przeglądane przez każdego członka zespołu.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Dispositivos",
"label.dismiss": "Dispensar",
"label.domain": "Domínio",
"label.dropoff": "Dropoff",
"label.edit": "Editar",
"label.edit-dashboard": "Editar painel",
"label.enable-share-url": "Ativar link de compartilhamento",
"label.event": "Evento",
"label.event-data": "Event data",
"label.events": "Eventos",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combinado",
"label.filter-raw": "Dados brutos",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Entrar",
"label.join-team": "Entrar no time",
"label.language": "Idioma",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "Este time não possui nenhum site.",
"messages.no-websites-configured": "Nenhum site foi configurado ainda.",
"messages.team-websites-info": "Os sites podem ser visualizados por qualquer membro da equipe."
"messages.team-websites-info": "Os sites podem ser visualizados por qualquer membro da equipe.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Dispositivos",
"label.dismiss": "Ignorar",
"label.domain": "Domínio",
"label.dropoff": "Dropoff",
"label.edit": "Editar",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Ativar link de partilha",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Eventos",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combinado",
"label.filter-raw": "Dados brutos",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Língua",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Não tens nenhum website configurado.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Dispozitive",
"label.dismiss": "Renunță",
"label.domain": "Domeniu",
"label.dropoff": "Dropoff",
"label.edit": "Editare",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Activare adresă URL de distribuire",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Evenimente",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combinat",
"label.filter-raw": "Brut",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Nu aveți niciun site web configurat.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Устройства",
"label.dismiss": "Отклонить",
"label.domain": "Домен",
"label.dropoff": "Dropoff",
"label.edit": "Изменить",
"label.edit-dashboard": "Редактировать дашборд",
"label.enable-share-url": "Разрешить делиться ссылкой",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "События",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Объединенные",
"label.filter-raw": "Сырые данные",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Присоединиться",
"label.join-team": "Присоединиться к команде",
"label.language": "Язык",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "У этой команды нет ни одного сайта.",
"messages.no-websites-configured": "У вас нет настроенных сайтов.",
"messages.team-websites-info": "Сайты могут просматривать все члены команды."
"messages.team-websites-info": "Сайты могут просматривать все члены команды.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Devices",
"label.dismiss": "මගහරින්න",
"label.domain": "වසම",
"label.dropoff": "Dropoff",
"label.edit": "සංස්කරණය කරන්න",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "බෙදාගැනීමේ URL සබල කරන්න",
"label.event": "Event",
"label.event-data": "සිදුවීම් දත්ත",
"label.events": "Events",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Combined",
"label.filter-raw": "Raw",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "භාෂාව",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "You do not have any websites configured.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Zariadenie",
"label.dismiss": "Odísť",
"label.domain": "Doména",
"label.dropoff": "Dropoff",
"label.edit": "Upraviť",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Povoliť zdielanie URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Udalosti",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Kombinácie",
"label.filter-raw": "Nezpracované",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Nemáte nastavený žiadny web.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Naprave",
"label.dismiss": "Opusti",
"label.domain": "Domena",
"label.dropoff": "Dropoff",
"label.edit": "Uredi",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Omogoči URL za skupno rabo",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Dogodki",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Skupno",
"label.filter-raw": "Neobdelane meritve",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Ni nastavljenih spletnih mest.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Enheter",
"label.dismiss": "Avbryt",
"label.domain": "Domän",
"label.dropoff": "Dropoff",
"label.edit": "Redigera",
"label.edit-dashboard": "Redigera översikt",
"label.enable-share-url": "Aktivera delnings-URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Händelser",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Kombinerade",
"label.filter-raw": "Rådata",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Gå med",
"label.join-team": "gå med i team",
"label.language": "Språk",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "Det här teamet har inga webbsajter.",
"messages.no-websites-configured": "Du har inga webbsajter.",
"messages.team-websites-info": "Websajter kan ses av alla i teamet."
"messages.team-websites-info": "Websajter kan ses av alla i teamet.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "சாதனங்கள்",
"label.dismiss": "நீக்கு",
"label.domain": "கள முகவரி",
"label.dropoff": "Dropoff",
"label.edit": "திருத்துதல்",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "கள முகவரியை பகிரலாம்",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "நிகழ்வுகள்",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "ஒருங்கிணைந்த",
"label.filter-raw": "மூல",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "உங்களிடம் எந்த வலைத்தளங்களும் கட்டமைக்கப்படவில்லை.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "อุปกรณ์",
"label.dismiss": "ยกเลิก",
"label.domain": "โดเมน",
"label.dropoff": "Dropoff",
"label.edit": "แก้ไข",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "เปิดใช้งานการแชร์ลิงก์",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "เหตุการณ์",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "ข้อมูลรวม",
"label.filter-raw": "ข้อมูลดิบ",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "ภาษา",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "คุณยังไม่ได้ตั้งค่าเว็บไซต์ใด ๆ ไว้.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Cihazlar",
"label.dismiss": "Reddet",
"label.domain": "Alan adı",
"label.dropoff": "Dropoff",
"label.edit": "Düzenle",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Anonim paylaşım URL'i aktif",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Olaylar",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Birleşik",
"label.filter-raw": "Ham",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Henüz hiç web sitesi tanımlamadınız",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Пристрої",
"label.dismiss": "Відхилити",
"label.domain": "Домен",
"label.dropoff": "Dropoff",
"label.edit": "Редагувати",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Дозволити ділитися посиланням",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Події",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Об'єднані",
"label.filter-raw": "Сирі дані",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "У вас немає налаштованих сайтів.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "آلات",
"label.dismiss": "مسترد کریں",
"label.domain": "ڈومین",
"label.dropoff": "Dropoff",
"label.edit": "ترمیم",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "شیئر یو آر ایل کو فعال کریں",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "واقعات",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "مشترکہ",
"label.filter-raw": "خام",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "آپ کے پاس کوئی ویب سائٹ کنفیگر نہیں ہے۔",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -39,9 +39,11 @@
"label.devices": "Thiết bị",
"label.dismiss": "Loại trừ",
"label.domain": "Tên miền",
"label.dropoff": "Dropoff",
"label.edit": "Chỉnh sửa",
"label.edit-dashboard": "Edit dashboard",
"label.enable-share-url": "Bật khả năng chia sẻ URL",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "Sự kiện",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "Kết hợp",
"label.filter-raw": "Gốc",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
@ -187,5 +190,6 @@
"messages.no-results-found": "No results were found.",
"messages.no-team-websites": "This team does not have any websites.",
"messages.no-websites-configured": "Bạn chưa có bất cứ website nào.",
"messages.team-websites-info": "Websites can be viewed by anyone on the team."
"messages.team-websites-info": "Websites can be viewed by anyone on the team.",
"new-version-available": "A new version of Umami {version} is available!"
}

View File

@ -2,8 +2,8 @@
"label.access-code": "访问代码",
"label.actions": "用户行为",
"label.activity-log": "活动日志",
"label.add": "Add",
"label.add-description": "Add description",
"label.add": "添加",
"label.add-description": "添加描述",
"label.add-website": "添加网站",
"label.admin": "管理员",
"label.all": "所有",
@ -39,9 +39,11 @@
"label.devices": "设备",
"label.dismiss": "关闭",
"label.domain": "域名",
"label.dropoff": "Dropoff",
"label.edit": "编辑",
"label.edit-dashboard": "编辑仪表板",
"label.enable-share-url": "启用共享链接",
"label.event": "Event",
"label.event-data": "Event data",
"label.events": "行为类别",
"label.field": "Field",
@ -49,6 +51,7 @@
"label.filter-combined": "合并",
"label.filter-raw": "原始",
"label.funnel": "Funnel",
"label.insights": "Insights",
"label.join": "加入",
"label.join-team": "加入团队",
"label.language": "语言",
@ -127,15 +130,15 @@
"label.website": "Website",
"label.website-id": "网站 ID",
"label.websites": "网站",
"label.window": "Window",
"label.window": "窗口",
"label.yesterday": "昨天",
"labels.after": "After",
"labels.average": "Average",
"labels.before": "Before",
"labels.breakdown": "Breakdown",
"labels.contains": "Contains",
"labels.create-report": "Create report",
"labels.description": "Description",
"labels.create-report": "创建报告",
"labels.description": "描述",
"labels.does-not-contain": "Does not contain",
"labels.does-not-equal": "Does not equal",
"labels.equals": "Equals",
@ -154,14 +157,14 @@
"labels.true": "True",
"labels.type": "Type",
"labels.unique": "Unique",
"labels.untitled": "Untitled",
"labels.untitled": "未命名",
"labels.value": "Value",
"message.active-users": "当前在线 {x} 人",
"message.confirm-delete": "你确定要删除 {target} 吗?",
"message.confirm-leave": "你确定要离开 {target} 吗?",
"message.confirm-reset": "您确定要重置 {target} 的数据吗?",
"message.delete-account": "To delete this account, type {confirmation} in the box below to confirm.",
"message.delete-website": "To delete this website, type {confirmation} in the box below to confirm.",
"message.delete-account": "确定删除该账户, 请在下面的输入框中输入 {confirmation} 进行二次确认。",
"message.delete-website": "确定删除该网站, 请在下面的输入框中输入 {confirmation} 进行二次确认。",
"message.delete-website-warning": "所有相关数据将会被删除。",
"message.error": "出现错误。",
"message.event-log": "{event} on {url}",
@ -175,7 +178,7 @@
"message.no-teams": "你还没有创建任何团队。",
"message.no-users": "没有任何用户。",
"message.page-not-found": "网页未找到。",
"message.reset-website": "To reset this website, type {confirmation} in the box below to confirm.",
"message.reset-website": "确定重置该网站, 请在下面的输入框中输入 {confirmation} 进行二次确认。",
"message.reset-website-warning": "本网站的所有统计数据将被删除,但您的跟踪代码将保持不变。",
"message.saved": "保存成功。",
"message.share-url": "这是 {target} 的共享链接。",
@ -184,8 +187,9 @@
"message.tracking-code": "跟踪代码",
"message.user-deleted": "User detected.",
"message.visitor-log": "来自{country}的访客在搭载 {os} 的{device}上使用 {browser} 浏览器进行访问。",
"messages.no-results-found": "No results were found.",
"messages.no-results-found": "没有找到任何结果。",
"messages.no-team-websites": "这个团队没有任何网站。",
"messages.no-websites-configured": "你还没有设置任何网站。",
"messages.team-websites-info": "团队中的任何人都可查看网站。"
"messages.team-websites-info": "团队中的任何人都可查看网站。",
"new-version-available": "A new version of Umami {version} is available!"
}

Some files were not shown because too many files have changed in this diff Show More