parent
c6cbc4eba8
commit
eab2d3a2cf
45 changed files with 344 additions and 93 deletions
|
|
@ -228,7 +228,10 @@ function AlertForm(props) {
|
|||
<div className="w-4/6 flex items-center">
|
||||
<Select
|
||||
placeholder={t('Select Condition')}
|
||||
options={conditions}
|
||||
options={conditions.map((c) => ({
|
||||
...c,
|
||||
label: t(c.label),
|
||||
}))}
|
||||
name="operator"
|
||||
defaultValue={instance.query.operator}
|
||||
// onChange={ writeQueryOption }
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@ import { useStore } from 'App/mstore';
|
|||
import { observer } from 'mobx-react-lite';
|
||||
import { Badge, Button, Tooltip } from 'antd';
|
||||
import { BellOutlined } from '@ant-design/icons';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const AUTOREFRESH_INTERVAL = 5 * 60 * 1000;
|
||||
|
||||
function Notifications() {
|
||||
const { t } = useTranslation();
|
||||
const { showModal } = useModal();
|
||||
const { notificationStore } = useStore();
|
||||
const count = notificationStore.notificationsCount;
|
||||
|
|
@ -28,7 +30,7 @@ function Notifications() {
|
|||
|
||||
return (
|
||||
<Badge dot={count > 0} size="small">
|
||||
<Tooltip title="Alerts">
|
||||
<Tooltip title={t('Alerts')}>
|
||||
<Button
|
||||
icon={<BellOutlined />}
|
||||
onClick={() => showModal(<AlertTriggersModal />, { right: true })}
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ function AssistActions({ userId, isCallActive, agentIds }: Props) {
|
|||
<ScreenRecorder />
|
||||
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip title="Call user to initiate remote control" disabled={livePlay}>
|
||||
<Tooltip title={t('Call user to initiate remote control')} disabled={livePlay}>
|
||||
<div
|
||||
className={cn('cursor-pointer p-2 flex items-center', {
|
||||
[stl.disabled]:
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { Pagination, NoContent, Icon } from "UI";
|
||||
import ErrorListItem from "App/components/Dashboard/components/Errors/ErrorListItem";
|
||||
import { withRouter, RouteComponentProps } from "react-router-dom";
|
||||
import { useModal } from "App/components/Modal";
|
||||
import ErrorDetailsModal from "App/components/Dashboard/components/Errors/ErrorDetailsModal";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React, { useEffect } from 'react';
|
||||
import { Pagination, NoContent, Icon } from 'UI';
|
||||
import ErrorListItem from 'App/components/Dashboard/components/Errors/ErrorListItem';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import ErrorDetailsModal from 'App/components/Dashboard/components/Errors/ErrorDetailsModal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
metric: any;
|
||||
|
|
@ -14,9 +14,10 @@ interface Props {
|
|||
location: any;
|
||||
}
|
||||
function CustomMetricTableErrors(props: RouteComponentProps & Props) {
|
||||
const { metric, data } = props;
|
||||
const errorId = new URLSearchParams(props.location.search).get("errorId");
|
||||
const { showModal, hideModal } = useModal();
|
||||
const { t } = useTranslation();
|
||||
const { metric, data } = props;
|
||||
const errorId = new URLSearchParams(props.location.search).get('errorId');
|
||||
const { showModal, hideModal } = useModal();
|
||||
|
||||
const onErrorClick = (e: any, error: any) => {
|
||||
e.stopPropagation();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { Input } from 'UI';
|
||||
import Select from 'Shared/Select';
|
||||
import { alertConditions as conditions } from 'App/constants';
|
||||
|
|
@ -41,7 +41,13 @@ function Condition({
|
|||
unit,
|
||||
changeUnit,
|
||||
}: ICondition) {
|
||||
const { t } = useTranslation();
|
||||
const { t, i18n } = useTranslation();
|
||||
|
||||
const localizedConditions = useMemo(() => conditions.map((c) => ({
|
||||
...c,
|
||||
label: t(c.label),
|
||||
})), [i18n.language]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{!isThreshold && (
|
||||
|
|
@ -85,10 +91,10 @@ function Condition({
|
|||
<div className="w-2/6 flex items-center">
|
||||
<Select
|
||||
placeholder={t('Select Condition')}
|
||||
options={conditions}
|
||||
options={localizedConditions}
|
||||
name="operator"
|
||||
value={
|
||||
conditions.find((c) => c.value === instance.query.operator) || ''
|
||||
localizedConditions.find((c) => c.value === instance.query.operator) || ''
|
||||
}
|
||||
onChange={({ value }) =>
|
||||
writeQueryOption(null, { name: 'operator', value: value.value })
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ function DashboardOptions(props: Props) {
|
|||
{
|
||||
icon: <Icon name="trash" />,
|
||||
key: 'delete',
|
||||
label: 'Delete',
|
||||
label: t('Delete'),
|
||||
onClick: deleteHandler,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { Button, Popover, Tooltip } from 'antd';
|
|||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Loader } from 'UI';
|
||||
import AddCardSection from '../AddCardSection/AddCardSection';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
siteId: string;
|
||||
|
|
@ -53,6 +54,7 @@ function DashboardWidgetGrid(props: Props) {
|
|||
}
|
||||
|
||||
function GridItem({ item, index, dashboard, dashboardId, siteId }: any) {
|
||||
const { t } = useTranslation();
|
||||
const [popoverOpen, setPopoverOpen] = React.useState(false);
|
||||
const handleOpenChange = (open: boolean) => {
|
||||
setPopoverOpen(open);
|
||||
|
|
@ -92,7 +94,7 @@ function GridItem({ item, index, dashboard, dashboardId, siteId }: any) {
|
|||
content={<AddCardSection handleOpenChange={handleOpenChange} />}
|
||||
trigger="click"
|
||||
>
|
||||
<Tooltip title="Add Card">
|
||||
<Tooltip title={t('Add Card')}>
|
||||
<Button
|
||||
icon={<PlusOutlined size={14} />}
|
||||
shape="circle"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { Input, Tooltip } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
|
|
@ -9,6 +10,7 @@ interface Props {
|
|||
}
|
||||
|
||||
function SeriesName(props: Props) {
|
||||
const { t } = useTranslation();
|
||||
const { seriesIndex = 1 } = props;
|
||||
const [editing, setEditing] = useState(false);
|
||||
const [name, setName] = useState(props.name);
|
||||
|
|
@ -56,7 +58,7 @@ function SeriesName(props: Props) {
|
|||
size="small"
|
||||
/>
|
||||
) : (
|
||||
<Tooltip title="Click to rename">
|
||||
<Tooltip title={t('Click to rename')}>
|
||||
<div
|
||||
className="text-lg font-medium h-8 flex items-center border-transparent p-2 hover:bg-teal/10 cursor-pointer rounded-lg btn-input-rename-series"
|
||||
onClick={() => setEditing(true)}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Tooltip } from 'UI';
|
||||
|
||||
const MIN_WIDTH = '20px';
|
||||
|
|
@ -6,6 +7,7 @@ interface Props {
|
|||
issue: any;
|
||||
}
|
||||
function FunnelIssueGraph(props: Props) {
|
||||
const { t } = useTranslation();
|
||||
const { issue } = props;
|
||||
|
||||
return (
|
||||
|
|
@ -17,7 +19,7 @@ function FunnelIssueGraph(props: Props) {
|
|||
}}
|
||||
className="relative"
|
||||
>
|
||||
<Tooltip title="Unaffected sessions" placement="top">
|
||||
<Tooltip title={t('Unaffected sessions')} placement="top">
|
||||
<div
|
||||
className="w-full relative rounded-tl-sm rounded-bl-sm"
|
||||
style={{
|
||||
|
|
@ -34,7 +36,7 @@ function FunnelIssueGraph(props: Props) {
|
|||
style={{ width: `${issue.affectedSessionsPer}%`, minWidth: MIN_WIDTH }}
|
||||
className="border-l relative"
|
||||
>
|
||||
<Tooltip title="Affected sessions" placement="top">
|
||||
<Tooltip title={t('Affected sessions')} placement="top">
|
||||
<div
|
||||
className="w-full relative"
|
||||
style={{
|
||||
|
|
@ -51,7 +53,7 @@ function FunnelIssueGraph(props: Props) {
|
|||
style={{ width: `${issue.lostConversionsPer}%`, minWidth: MIN_WIDTH }}
|
||||
className="border-l relative"
|
||||
>
|
||||
<Tooltip title="Conversion lost" placement="top">
|
||||
<Tooltip title={t('Conversion lost')} placement="top">
|
||||
<div
|
||||
className="w-full relative rounded-tr-sm rounded-br-sm"
|
||||
style={{ height: '18px', backgroundColor: 'rgba(204, 0, 0, 0.26)' }}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ function WidgetName(props: Props) {
|
|||
/>
|
||||
) : (
|
||||
// @ts-ignore
|
||||
<Tooltip mouseEnterDelay={1} title="Click to edit" disabled={!canEdit}>
|
||||
<Tooltip mouseEnterDelay={1} title={t('Click to edit')} disabled={!canEdit}>
|
||||
<div
|
||||
onClick={() => setEditing(true)}
|
||||
className={cn(
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ import React from 'react';
|
|||
import { useModal } from 'Components/ModalContext';
|
||||
import AlertFormModal from 'Components/Alerts/AlertFormModal/AlertFormModal';
|
||||
import { showAddToDashboardModal } from 'Components/Dashboard/components/AddToDashboardButton';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function CardViewMenu() {
|
||||
const { t } = useTranslation();
|
||||
const history = useHistory();
|
||||
const { alertsStore, metricStore, dashboardStore } = useStore();
|
||||
const widget = metricStore.instance;
|
||||
|
|
@ -32,29 +34,29 @@ function CardViewMenu() {
|
|||
const items: MenuProps['items'] = [
|
||||
{
|
||||
key: 'add-to-dashboard',
|
||||
label: 'Add to Dashboard',
|
||||
label: t('Add to Dashboard'),
|
||||
icon: <Grid2x2Plus size={16} />,
|
||||
disabled: !widget.exists(),
|
||||
onClick: () => showAddToDashboardModal(widget.metricId, dashboardStore),
|
||||
},
|
||||
{
|
||||
key: 'alert',
|
||||
label: 'Set Alerts',
|
||||
label: t('Set Alerts'),
|
||||
icon: <BellIcon size={16} />,
|
||||
disabled: !widget.exists() || widget.metricType !== 'timeseries',
|
||||
onClick: showAlertModal,
|
||||
},
|
||||
{
|
||||
key: 'remove',
|
||||
label: 'Delete',
|
||||
label: t('Delete'),
|
||||
icon: <TrashIcon size={15} />,
|
||||
disabled: !widget.exists(),
|
||||
onClick: () => {
|
||||
Modal.confirm({
|
||||
title: 'Confirm Card Deletion',
|
||||
title: t('Confirm Card Deletion'),
|
||||
icon: null,
|
||||
content:
|
||||
'Are you sure you want to remove this card? This action is permanent and cannot be undone.',
|
||||
t('Are you sure you want to remove this card? This action is permanent and cannot be undone.'),
|
||||
footer: (_, { OkBtn, CancelBtn }) => (
|
||||
<>
|
||||
<CancelBtn />
|
||||
|
|
@ -68,7 +70,7 @@ function CardViewMenu() {
|
|||
history.goBack();
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error('Failed to remove card');
|
||||
toast.error(t('Failed to remove card'));
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ function WidgetView({
|
|||
{
|
||||
value: 'flex-row',
|
||||
icon: (
|
||||
<Tooltip title="Filters on Left">
|
||||
<Tooltip title={t('Filters on Left')}>
|
||||
<LayoutPanelLeft size={16} />
|
||||
</Tooltip>
|
||||
),
|
||||
|
|
@ -213,7 +213,7 @@ function WidgetView({
|
|||
{
|
||||
value: 'flex-col',
|
||||
icon: (
|
||||
<Tooltip title="Filters on Top">
|
||||
<Tooltip title={t('Filters on Top')}>
|
||||
<LayoutPanelTop size={16} />
|
||||
</Tooltip>
|
||||
),
|
||||
|
|
@ -221,7 +221,7 @@ function WidgetView({
|
|||
{
|
||||
value: 'flex-row-reverse',
|
||||
icon: (
|
||||
<Tooltip title="Filters on Right">
|
||||
<Tooltip title={t('Filters on Right')}>
|
||||
<div className="rotate-180">
|
||||
<LayoutPanelLeft size={16} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Button, Space, Tooltip } from 'antd';
|
|||
import CardViewMenu from 'Components/Dashboard/components/WidgetView/CardViewMenu';
|
||||
import { Link2 } from 'lucide-react';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
onClick?: () => void;
|
||||
|
|
@ -17,15 +18,16 @@ interface Props {
|
|||
isPreview?: boolean;
|
||||
}
|
||||
|
||||
const defaultText = 'Copy link to clipboard';
|
||||
|
||||
function WidgetViewHeader({
|
||||
onClick,
|
||||
onSave,
|
||||
layoutControl,
|
||||
isPreview,
|
||||
}: Props) {
|
||||
const { t } = useTranslation();
|
||||
const defaultText = t('Copy link to clipboard');
|
||||
const [tooltipText, setTooltipText] = React.useState(defaultText);
|
||||
|
||||
const { metricStore } = useStore();
|
||||
const widget = metricStore.instance;
|
||||
|
||||
|
|
@ -39,7 +41,7 @@ function WidgetViewHeader({
|
|||
const copyUrl = () => {
|
||||
const url = window.location.href;
|
||||
copy(url);
|
||||
setTooltipText('Link copied to clipboard!');
|
||||
setTooltipText(t('Link copied to clipboard!'));
|
||||
setTimeout(() => setTooltipText(defaultText), 2000);
|
||||
};
|
||||
return (
|
||||
|
|
@ -73,7 +75,7 @@ function WidgetViewHeader({
|
|||
className="font-medium btn-update-card"
|
||||
size="small"
|
||||
>
|
||||
{widget.exists() ? 'Update' : 'Create'}
|
||||
{widget.exists() ? t('Update') : t('Create')}
|
||||
</Button>
|
||||
|
||||
{/* <MetricTypeSelector /> */}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import cn from 'classnames';
|
||||
import { Icon, Tooltip } from 'UI';
|
||||
import stl from './funnelMenuItem.module.css';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function FunnelMenuItem({
|
||||
iconName = 'info',
|
||||
|
|
@ -12,6 +13,7 @@ function FunnelMenuItem({
|
|||
isPublic = false,
|
||||
onClick,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
|
@ -41,7 +43,7 @@ function FunnelMenuItem({
|
|||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className={cn('mx-2', { invisible: !isPublic })}>
|
||||
<Tooltip title="Shared with team">
|
||||
<Tooltip title={t('Shared with team')}>
|
||||
<div
|
||||
className={cn(
|
||||
'bg-gray-light h-8 w-8 rounded-full flex items-center justify-center',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Tooltip } from 'UI';
|
|||
function IssueGraph({ issue }) {
|
||||
return (
|
||||
<div className="flex rounded-sm" style={{ width: '600px' }}>
|
||||
<Tooltip title="Unaffected sessions">
|
||||
<Tooltip title={t('Unaffected sessions')}>
|
||||
<div
|
||||
style={{ width: `${issue.unaffectedSessionsPer}%` }}
|
||||
className="relative"
|
||||
|
|
@ -21,7 +21,7 @@ function IssueGraph({ issue }) {
|
|||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Tooltip title="Affected sessions">
|
||||
<Tooltip title={t('Affected sessions')}>
|
||||
<div
|
||||
style={{ width: `${issue.affectedSessionsPer}%` }}
|
||||
className="border-l relative"
|
||||
|
|
@ -39,7 +39,7 @@ function IssueGraph({ issue }) {
|
|||
{/* <div className="absolute left-0 ml-1 text-xs">{issue.affectedSessionsPer}</div> */}
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Tooltip title="Conversion lost">
|
||||
<Tooltip title={t('Conversion lost')}>
|
||||
<div
|
||||
style={{ width: `${issue.lostConversionsPer}%` }}
|
||||
className="border-l relative"
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ function HighlightsListHeader({
|
|||
: 'capitalize'
|
||||
}
|
||||
>
|
||||
{tag.toLowerCase()}
|
||||
{(t(tag.toLowerCase()))}
|
||||
</div>
|
||||
),
|
||||
})),
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ import {
|
|||
CaretRightOutlined,
|
||||
PauseOutlined,
|
||||
} from './.store/@ant-design-icons-virtual-de151eefe5/package';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function AutoplayToggle() {
|
||||
const { t } = useTranslation();
|
||||
const { clipStore } = useStore();
|
||||
const playerContext = React.useContext<IPlayerContext>(PlayerContext);
|
||||
// const { player, store } = playerContext;
|
||||
|
|
@ -22,7 +24,7 @@ function AutoplayToggle() {
|
|||
};
|
||||
|
||||
return (
|
||||
<Tooltip title="Toggle Autoplay" placement="bottom">
|
||||
<Tooltip title={t('Toggle Autoplay')} placement="bottom">
|
||||
<Switch
|
||||
className="custom-switch"
|
||||
onChange={handleToggle}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import * as routes from '@/routes';
|
|||
import { useStore } from '@/mstore';
|
||||
import { LinkIcon, X } from 'lucide-react';
|
||||
import { PartialSessionBadge } from 'Components/Session_/WarnBadge';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
session: Session;
|
||||
|
|
@ -18,6 +19,7 @@ interface Props {
|
|||
}
|
||||
|
||||
function ClipPlayerHeader(props: Props) {
|
||||
const { t } = useTranslation();
|
||||
const { projectsStore } = useStore();
|
||||
const { session, range, onClose, isHighlight } = props;
|
||||
const { siteId } = projectsStore;
|
||||
|
|
@ -35,7 +37,7 @@ function ClipPlayerHeader(props: Props) {
|
|||
<UserCard session={props.session} />
|
||||
|
||||
<Space>
|
||||
<Tooltip title="Copy link to clipboard" placement="bottom">
|
||||
<Tooltip title={t('Copy link to clipboard')} placement="bottom">
|
||||
<Button
|
||||
onClick={copyHandler}
|
||||
size="small"
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ import { Link2 } from 'lucide-react';
|
|||
import { PlayerContext } from 'App/components/Session/playerContext';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import SessionTabs from 'Components/Session/Player/SharedComponents/SessionTabs';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function SubHeader() {
|
||||
const { t } = useTranslation();
|
||||
const { store } = React.useContext(PlayerContext);
|
||||
const { location: currentLocation = 'loading...' } = store.get();
|
||||
|
||||
|
|
@ -23,7 +25,7 @@ function SubHeader() {
|
|||
<div className="w-full bg-white border-b border-gray-lighter">
|
||||
<div className="flex w-fit items-center cursor-pointer color-gray-medium text-sm p-1">
|
||||
<Link2 className="mx-2" size={16} />
|
||||
<Tooltip title="Open in new tab" delay={0} placement="bottom">
|
||||
<Tooltip title={t('Open in new tab')} delay={0} placement="bottom">
|
||||
<a href={location} target="_blank" rel="noreferrer">
|
||||
{location}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { useModal } from 'Components/ModalContext';
|
|||
import { PlayerContext } from 'Components/Session/playerContext';
|
||||
import HighlightButton from 'Components/Session_/Highlight/HighlightButton';
|
||||
import IssueForm from 'Components/Session_/Issues/IssueForm';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
setActiveTab: (tab: string) => void;
|
||||
|
|
@ -18,6 +19,7 @@ interface Props {
|
|||
}
|
||||
|
||||
function SubHeader(props: Props) {
|
||||
const { t } = useTranslation();
|
||||
const { sessionStore, integrationsStore, issueReportingStore } = useStore();
|
||||
const integrations = integrationsStore.issues.list;
|
||||
const isIOS = sessionStore.current.platform === 'ios';
|
||||
|
|
@ -66,7 +68,7 @@ function SubHeader(props: Props) {
|
|||
<HighlightButton onClick={() => props.setActiveTab('HIGHLIGHT')} />
|
||||
{enabledIntegration && <Issues sessionId={props.sessionId} />}
|
||||
<Bookmark sessionId={props.sessionId} />
|
||||
<Tooltip title="Share Session" placement="bottom">
|
||||
<Tooltip title={t('Share Session')} placement="bottom">
|
||||
<AntButton
|
||||
size="small"
|
||||
className="flex items-center justify-center"
|
||||
|
|
@ -77,7 +79,7 @@ function SubHeader(props: Props) {
|
|||
hideModal={closeModal}
|
||||
time={store?.get().time}
|
||||
/>,
|
||||
{ title: 'Share Session' },
|
||||
{ title: t('Share Session') },
|
||||
)
|
||||
}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const CopyableTextArea: React.FC<CopyableTextAreaProps> = ({
|
|||
style={{ paddingRight: '40px' }}
|
||||
placeholder={t('Enter selector to tag elements. E.g. .btn-primary')}
|
||||
/>
|
||||
<Tooltip title="Copy">
|
||||
<Tooltip title={t('Copy')}>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<CopyOutlined />}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ const MODES = {
|
|||
}
|
||||
|
||||
function EventsBlock(props: IProps) {
|
||||
const defaultFramework = getDefaultFramework();
|
||||
const [mode, setMode] = React.useState(MODES.SELECT);
|
||||
const { t } = useTranslation();
|
||||
const { notesStore, uxtestingStore, uiPlayerStore, sessionStore } =
|
||||
useStore();
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@ import React from 'react';
|
|||
import { Button, Tooltip } from 'antd';
|
||||
import { MessageSquareQuote } from 'lucide-react';
|
||||
import { Icon } from 'UI';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function HighlightButton({ onClick }: { onClick: () => void }) {
|
||||
const { t } = useTranslation();
|
||||
const openPanel = () => {
|
||||
onClick();
|
||||
};
|
||||
return (
|
||||
<Tooltip title="Highlight a moment" placement="bottom">
|
||||
<Tooltip title={t('Highlight a moment')} placement="bottom">
|
||||
<Button onClick={openPanel} size="small">
|
||||
<Icon name="chat-square-quote" color="inherit" size={15} />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ function Issues({ sessionId }) {
|
|||
)}
|
||||
>
|
||||
<div>
|
||||
<Tooltip title="Create Issue" placement="bottom">
|
||||
<Tooltip title={t('Create Issue')} placement="bottom">
|
||||
<Button size="small" className="flex items-center justify-center">
|
||||
<Icon name={`integrations/${provider ?? 'github'}`} />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -277,20 +277,21 @@ function Storage() {
|
|||
style={{ paddingRight: 30, marginLeft: 'auto' }}
|
||||
className="font-semibold"
|
||||
>
|
||||
<Tooltip title="Time to execute">{t('TTE')}</Tooltip>
|
||||
<Tooltip title={t('Time to execute')}>{t('TTE')}</Tooltip>
|
||||
</h3>
|
||||
<Segmented options={[{ label: 'Current Tab', value: 'all' }]} />
|
||||
</div>
|
||||
</BottomBlock.Header>
|
||||
<BottomBlock.Content className="flex">
|
||||
<NoContent
|
||||
title="Nothing to display yet"
|
||||
title={t('Nothing to display yet')}
|
||||
subtext={
|
||||
!hintIsHidden ? (
|
||||
<>
|
||||
{
|
||||
'Inspect your application state while you’re replaying your users sessions. OpenReplay supports '
|
||||
}
|
||||
{t(
|
||||
'Inspect your application state while you’re replaying your users sessions. OpenReplay supports',
|
||||
)}
|
||||
|
||||
<a
|
||||
className="underline color-teal"
|
||||
href="https://docs.openreplay.com/plugins/redux"
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ function SubHeader(props) {
|
|||
<div className="w-full bg-white border-b border-gray-lighter">
|
||||
<div className="flex w-fit items-center cursor-pointer color-gray-medium text-sm p-1">
|
||||
<Link2 className="mx-2" size={16} />
|
||||
<Tooltip title="Open in new tab" delay={0} placement="bottom">
|
||||
<Tooltip title={t('Open in new tab')} delay={0} placement="bottom">
|
||||
<a
|
||||
href={currentLocation}
|
||||
target="_blank"
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ import { Tooltip } from 'antd';
|
|||
import { Icon } from 'UI';
|
||||
import { Link2 } from 'lucide-react';
|
||||
import spotPlayerStore from '../spotPlayerStore';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function SpotLocation() {
|
||||
const { t } = useTranslation();
|
||||
const currUrl = spotPlayerStore.getClosestLocation(
|
||||
spotPlayerStore.time,
|
||||
)?.location;
|
||||
|
|
@ -15,7 +17,7 @@ function SpotLocation() {
|
|||
<div className="w-full bg-white border-b border-gray-lighter">
|
||||
<div className="flex w-fit items-center cursor-pointer color-gray-medium text-sm p-1">
|
||||
<Link2 className="mx-2" size={16} />
|
||||
<Tooltip title="Open in new tab" placement="bottom">
|
||||
<Tooltip title={t('Open in new tab')} placement="bottom">
|
||||
<a
|
||||
href={currUrl}
|
||||
target="_blank"
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import { spot as spotUrl, withSiteId } from 'App/routes';
|
|||
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
||||
|
||||
import EditItemModal from './EditItemModal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const backgroundUrl = '/assets/img/spotThumbBg.svg';
|
||||
|
||||
|
|
@ -42,9 +43,10 @@ function SpotListItem({
|
|||
onSelect,
|
||||
isSelected,
|
||||
}: ISpotListItem) {
|
||||
const { t } = useTranslation();
|
||||
const [isEdit, setIsEdit] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [tooltipText, setTooltipText] = useState('Copy link to clipboard');
|
||||
const [tooltipText, setTooltipText] = useState(t('Copy link to clipboard'));
|
||||
const history = useHistory();
|
||||
const { siteId } = useParams<{ siteId: string }>();
|
||||
|
||||
|
|
@ -52,17 +54,17 @@ function SpotListItem({
|
|||
{
|
||||
key: 'rename',
|
||||
icon: <EditOutlined />,
|
||||
label: 'Rename',
|
||||
label: t('Rename'),
|
||||
},
|
||||
{
|
||||
key: 'download',
|
||||
label: 'Download Video',
|
||||
label: t('Download Video'),
|
||||
icon: <DownloadOutlined />,
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
icon: <DeleteOutlined />,
|
||||
label: 'Delete',
|
||||
label: t('Delete'),
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -70,7 +72,7 @@ function SpotListItem({
|
|||
menuItems.splice(1, 0, {
|
||||
key: 'slack',
|
||||
icon: <SlackOutlined />,
|
||||
label: 'Share via Slack',
|
||||
label: t('Share via Slack'),
|
||||
});
|
||||
}, []);
|
||||
const onMenuClick = async ({ key }: any) => {
|
||||
|
|
@ -88,7 +90,7 @@ function SpotListItem({
|
|||
siteId,
|
||||
)}`,
|
||||
);
|
||||
return toast.success('Spot URL copied to clipboard');
|
||||
return toast.success(t('Spot URL copied to clipboard'));
|
||||
case 'delete':
|
||||
return onDelete();
|
||||
case 'slack':
|
||||
|
|
@ -114,12 +116,12 @@ function SpotListItem({
|
|||
navigator.clipboard
|
||||
.writeText(fullLink)
|
||||
.then(() => {
|
||||
setTooltipText('Link copied to clipboard!');
|
||||
setTimeout(() => setTooltipText('Copy link to clipboard'), 2000); // Reset tooltip text after 2 seconds
|
||||
setTooltipText(t('Link copied to clipboard!'));
|
||||
setTimeout(() => setTooltipText(t('Copy link to clipboard')), 2000); // Reset tooltip text after 2 seconds
|
||||
})
|
||||
.catch(() => {
|
||||
setTooltipText('Failed to copy URL');
|
||||
setTimeout(() => setTooltipText('Copy link to clipboard'), 2000); // Reset tooltip text after 2 seconds
|
||||
setTooltipText(t('Failed to copy URL'));
|
||||
setTimeout(() => setTooltipText(t('Copy link to clipboard')), 2000); // Reset tooltip text after 2 seconds
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import React from 'react';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { Tooltip } from 'UI';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const withCopy = (WrappedComponent: React.ComponentType) => {
|
||||
function ComponentWithCopy(props: any) {
|
||||
const { t } = useTranslation();
|
||||
const [copied, setCopied] = React.useState(false);
|
||||
const { value, tooltip } = props;
|
||||
const copyToClipboard = (text: string) => {
|
||||
|
|
@ -18,7 +20,7 @@ const withCopy = (WrappedComponent: React.ComponentType) => {
|
|||
onClick={() => copyToClipboard(value)}
|
||||
className="w-fit cursor-pointer"
|
||||
>
|
||||
<Tooltip title={copied ? tooltip : 'Click to copy'} delay={0}>
|
||||
<Tooltip title={copied ? tooltip : t('Click to copy')} delay={0}>
|
||||
<WrappedComponent {...props} copyToClipboard={copyToClipboard} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,22 +4,24 @@ import { observer } from 'mobx-react-lite';
|
|||
import { Switch, Tooltip, message } from 'antd';
|
||||
import { CaretRightOutlined, PauseOutlined } from '@ant-design/icons';
|
||||
import './AutoplayToggle.css';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const AutoplayToggle: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const { player, store } = useContext(PlayerContext);
|
||||
const { autoplay } = store.get();
|
||||
|
||||
const handleToggle = () => {
|
||||
player.toggleAutoplay();
|
||||
if (!autoplay) {
|
||||
message.success('Autoplay is ON');
|
||||
message.success(t('Autoplay is ON'));
|
||||
} else {
|
||||
message.info('Autoplay is OFF');
|
||||
message.info(t('Autoplay is OFF'));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Tooltip title="Toggle Autoplay" placement="bottom">
|
||||
<Tooltip title={t('Toggle Autoplay')} placement="bottom">
|
||||
<Switch
|
||||
className="custom-switch"
|
||||
onChange={handleToggle}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
label?: string;
|
||||
|
|
@ -9,10 +10,11 @@ interface Props {
|
|||
content: string;
|
||||
}
|
||||
function CopyText(props: Props) {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
children,
|
||||
label = 'Click to copy',
|
||||
afterLabel = 'Copied',
|
||||
label = t('Click to copy'),
|
||||
afterLabel = t('Copied'),
|
||||
content = '',
|
||||
} = props;
|
||||
const [isCopied, setIsCopied] = useState(false);
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ const EventsPanel = observer(
|
|||
{ label: 'All Tabs', value: 'all' },
|
||||
{
|
||||
label: (
|
||||
<Tooltip title="Stack Events overview is available only for all tabs combined.">
|
||||
<Tooltip title={t('Stack Events overview is available only for all tabs combined.')}>
|
||||
<span>{t('Current Tab')}</span>
|
||||
</Tooltip>
|
||||
),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { JSONTree, Tabs, NoContent } from 'UI';
|
|||
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
||||
import Headers from '../Headers';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { TFunction } from 'i18next';
|
||||
|
||||
const HEADERS = 'HEADERS';
|
||||
const REQUEST = 'REQUEST';
|
||||
|
|
@ -23,8 +24,8 @@ function parseRequestResponse(
|
|||
setHeaders: (hs: Record<string, string> | null) => void,
|
||||
setJSONBody: (body: Record<string, unknown> | null) => void,
|
||||
setStringBody: (body: string) => void,
|
||||
t: TFunction,
|
||||
): void {
|
||||
const { t } = useTranslation();
|
||||
try {
|
||||
if (!r) {
|
||||
setHeaders(null);
|
||||
|
|
@ -100,12 +101,14 @@ function FetchTabs({ resource, isSpot }: Props) {
|
|||
setRequestHeaders,
|
||||
setJsonRequest,
|
||||
setStringRequest,
|
||||
t,
|
||||
);
|
||||
parseRequestResponse(
|
||||
response,
|
||||
setResponseHeaders,
|
||||
setJsonResponse,
|
||||
setStringResponse,
|
||||
t,
|
||||
);
|
||||
}, [resource]);
|
||||
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ export function AutocompleteModal({
|
|||
</Button>
|
||||
</div>
|
||||
|
||||
<Tooltip title="Clear all selection">
|
||||
<Tooltip title={t('Clear all selection')}>
|
||||
<Button
|
||||
onClick={clearSelection}
|
||||
type="text"
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ const EventsOrder = observer(
|
|||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<Tooltip
|
||||
title="Select the operator to be applied between events."
|
||||
title={t('Select the operator to be applied between events.')}
|
||||
placement="bottom"
|
||||
>
|
||||
<div className="text-neutral-500/90 text-sm font-normal cursor-default">
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ function LiveSearchBar(props: Props) {
|
|||
<LiveSessionSearchField />
|
||||
</div>
|
||||
<div className="flex items-center" style={{ width: '40%' }}>
|
||||
<Tooltip title="Clear Steps">
|
||||
<Tooltip title={t('Clear Steps')}>
|
||||
<Button
|
||||
type="text"
|
||||
disabled={!hasFilters}
|
||||
|
|
|
|||
|
|
@ -47,14 +47,18 @@ function SelectDateRange(props: Props) {
|
|||
const dateRangeOptions = props.comparison
|
||||
? DATE_RANGE_COMPARISON_OPTIONS
|
||||
: DATE_RANGE_OPTIONS;
|
||||
const dateRangeOptionsLocalized = dateRangeOptions.map((obj: any) => ({
|
||||
...obj,
|
||||
label: t(obj.label),
|
||||
}));
|
||||
const selectedValue = usedPeriod?.rangeName
|
||||
? dateRangeOptions.find(
|
||||
? dateRangeOptionsLocalized.find(
|
||||
(obj: any) => obj.value === usedPeriod?.rangeName,
|
||||
)
|
||||
: null;
|
||||
const options = dateRangeOptions.filter((obj: any) =>
|
||||
const options = dateRangeOptionsLocalized.filter((obj: any) =>
|
||||
disableCustom ? obj.value !== CUSTOM_RANGE : true,
|
||||
);
|
||||
).map((obj) => ({ ...obj, label: t(obj.label) }));
|
||||
|
||||
const onChange = (value: any) => {
|
||||
if (value === CUSTOM_RANGE) {
|
||||
|
|
@ -215,6 +219,7 @@ function AndDateRange({
|
|||
onApplyDateRange,
|
||||
isTileDisabled,
|
||||
}: Props) {
|
||||
const { t } = useTranslation();
|
||||
const menuProps = {
|
||||
items: options.map((opt: any) => ({
|
||||
label: opt.label,
|
||||
|
|
@ -245,7 +250,7 @@ function AndDateRange({
|
|||
>
|
||||
<span>{`Compare to ${comparisonValue || ''}`}</span>
|
||||
{selectedValue && (
|
||||
<Tooltip title="Reset">
|
||||
<Tooltip title={t('Reset')}>
|
||||
<SyncOutlined
|
||||
className="cursor-pointer p-2 py-1.5 hover:bg-neutral-200/50 text-sm"
|
||||
onClick={(e) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
import stl from './ErrorBars.module.css';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const GOOD = 'Good';
|
||||
const LESS_CRITICAL = 'Few Issues';
|
||||
|
|
@ -19,6 +20,7 @@ interface Props {
|
|||
count?: number;
|
||||
}
|
||||
export default function ErrorBars(props: Props) {
|
||||
const { t } = useTranslation();
|
||||
const { count = 2 } = props;
|
||||
const state = React.useMemo(() => getErrorState(count), [count]);
|
||||
const isGood = state === GOOD;
|
||||
|
|
@ -50,7 +52,7 @@ export default function ErrorBars(props: Props) {
|
|||
{/* <div className={cn("rounded-tr rounded-br", bgColor, stl.bar)}></div> */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-1 color-gray-medium text-sm">{state}</div>
|
||||
<div className="mt-1 color-gray-medium text-sm">{t(state)}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ import React from 'react';
|
|||
import SessionSettings from 'Shared/SessionSettings';
|
||||
import { Icon, Tooltip } from 'UI';
|
||||
import { Button } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function SessionSettingButton(props: any) {
|
||||
const { t } = useTranslation();
|
||||
const { showModal } = useModal();
|
||||
|
||||
const handleClick = () => {
|
||||
|
|
@ -13,7 +15,7 @@ function SessionSettingButton(props: any) {
|
|||
|
||||
return (
|
||||
<div className="cursor-pointer ml-4" onClick={handleClick}>
|
||||
<Tooltip title="Session Settings">
|
||||
<Tooltip title={t('Session Settings')}>
|
||||
<Button
|
||||
icon={<Icon name="sliders" />}
|
||||
type="text"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { Icon, TextEllipsis } from 'UI';
|
|||
import { Tooltip } from 'antd';
|
||||
import { countries } from 'App/constants';
|
||||
import CountryFlagIcon from 'Shared/CountryFlagIcon';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface CountryFlagProps {
|
||||
userCity?: string;
|
||||
|
|
@ -26,9 +27,10 @@ const CountryFlag: FC<CountryFlagProps> = ({
|
|||
height = 15,
|
||||
showLabel = false,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const knownCountry = !!country && country !== 'UN';
|
||||
const countryFlag = knownCountry ? country.toLowerCase() : '';
|
||||
const countryName = knownCountry ? countries[country] : 'Unknown Country';
|
||||
const countryName = knownCountry ? countries[country] : t('Unknown Country');
|
||||
|
||||
const displayGeoInfo = userCity || userState || countryName;
|
||||
|
||||
|
|
|
|||
|
|
@ -1448,5 +1448,43 @@
|
|||
"Select Series": "Select Series",
|
||||
"Integrate Github": "Integrate Github",
|
||||
"Integrate GraphQL": "Integrate GraphQL",
|
||||
"Installation Docs": "Installation Docs"
|
||||
"Installation Docs": "Installation Docs",
|
||||
"Good": "Good",
|
||||
"Few Issues": "Few Issues",
|
||||
"Many Issues": "Many Issues",
|
||||
"Past 24 Hours": "Past 24 Hours",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Custom Range": "Custom Range",
|
||||
"Unknown Country": "Unknown Country",
|
||||
"design": "Design",
|
||||
"note": "Note",
|
||||
"issue": "Issue",
|
||||
"Set Alerts": "Set Alerts",
|
||||
"Confirm Card Deletion": "Confirm Card Deletion",
|
||||
"Are you sure you want to remove this card? This action is permanent and cannot be undone.": "Are you sure you want to remove this card? This action is permanent and cannot be undone.",
|
||||
"Failed to remove card": "Failed to remove card",
|
||||
"Filters on Left": "Filters on Left",
|
||||
"Filters on Top": "Filters on Top",
|
||||
"Filters on Right": "Filters on Right",
|
||||
"Call user to initiate remote control": "Call user to initiate remote control",
|
||||
"Click to rename": "Click to rename",
|
||||
"Shared with team": "Shared with team",
|
||||
"Conversion lost": "Conversion lost",
|
||||
"Toggle Autoplay": "Toggle Autoplay",
|
||||
"Open in new tab": "Open in new tab",
|
||||
"Highlight a moment": "Highlight a moment",
|
||||
"Time to execute": "Time to execute",
|
||||
"Inspect your application state while you’re replaying your users sessions. OpenReplay supports": "Inspect your application state while you’re replaying your users' sessions. OpenReplay supports",
|
||||
"Autoplay is ON": "Autoplay is ON",
|
||||
"Autoplay is OFF": "Autoplay is OFF",
|
||||
"Click to copy": "Click to copy",
|
||||
"Stack Events overview is available only for all tabs combined.": "Stack Events overview is available only for all tabs combined.",
|
||||
"Clear all selection": "Clear all selection",
|
||||
"Clear Steps": "Clear Steps",
|
||||
"Session Settings": "Session Settings",
|
||||
"Select the operator to be applied between events.": "Select the operator to be applied between events.",
|
||||
"above": "above",
|
||||
"above or equal to": "above or equal to",
|
||||
"below": "below",
|
||||
"below or equal to": "below or equal to"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1448,5 +1448,43 @@
|
|||
"Select Series": "Seleccionar Serie",
|
||||
"Integrate Github": "Integrar con Github",
|
||||
"Integrate GraphQL": "Integrar con GraphQL",
|
||||
"Installation Docs": "Documentación de Instalación"
|
||||
"Installation Docs": "Documentación de Instalación",
|
||||
"Good": "Bueno",
|
||||
"Few Issues": "Algunos problemas",
|
||||
"Many Issues": "Muchos problemas",
|
||||
"Past 24 Hours": "Últimas 24 horas",
|
||||
"Past 30 Days": "Últimos 30 días",
|
||||
"Custom Range": "Rango personalizado",
|
||||
"Unknown Country": "País desconocido",
|
||||
"design": "Diseño",
|
||||
"note": "Nota",
|
||||
"issue": "Problema",
|
||||
"Set Alerts": "Configurar alertas",
|
||||
"Confirm Card Deletion": "Confirmar eliminación de tarjeta",
|
||||
"Are you sure you want to remove this card? This action is permanent and cannot be undone.": "¿Estás seguro de que quieres eliminar esta tarjeta? Esta acción es permanente y no se puede deshacer.",
|
||||
"Failed to remove card": "No se pudo eliminar la tarjeta",
|
||||
"Filters on Left": "Filtros a la izquierda",
|
||||
"Filters on Top": "Filtros en la parte superior",
|
||||
"Filters on Right": "Filtros a la derecha",
|
||||
"Call user to initiate remote control": "Llamar al usuario para iniciar el control remoto",
|
||||
"Click to rename": "Haz clic para renombrar",
|
||||
"Shared with team": "Compartido con el equipo",
|
||||
"Conversion lost": "Conversión perdida",
|
||||
"Toggle Autoplay": "Activar/desactivar reproducción automática",
|
||||
"Open in new tab": "Abrir en una nueva pestaña",
|
||||
"Highlight a moment": "Resaltar un momento",
|
||||
"Time to execute": "Tiempo de ejecución",
|
||||
"Inspect your application state while you’re replaying your users sessions. OpenReplay supports": "Inspecciona el estado de tu aplicación mientras reproduces las sesiones de los usuarios. OpenReplay admite",
|
||||
"Autoplay is ON": "La reproducción automática está activada",
|
||||
"Autoplay is OFF": "La reproducción automática está desactivada",
|
||||
"Click to copy": "Haz clic para copiar",
|
||||
"Stack Events overview is available only for all tabs combined.": "El resumen de eventos de la pila está disponible solo para todas las pestañas combinadas.",
|
||||
"Clear all selection": "Borrar todas las selecciones",
|
||||
"Clear Steps": "Borrar pasos",
|
||||
"Session Settings": "Configuración de sesión",
|
||||
"Select the operator to be applied between events.": "Seleccione el operador que se aplicará entre los eventos.",
|
||||
"above": "por encima de",
|
||||
"above or equal to": "por encima o igual a",
|
||||
"below": "por debajo de",
|
||||
"below or equal to": "por debajo o igual a"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1448,5 +1448,43 @@
|
|||
"Select Series": "Sélectionner la série",
|
||||
"Integrate Github": "Intégrer avec Github",
|
||||
"Integrate GraphQL": "Intégrer avec GraphQL",
|
||||
"Installation Docs": "Documentation d'installation"
|
||||
"Installation Docs": "Documentation d'installation",
|
||||
"Good": "Bon",
|
||||
"Few Issues": "Quelques problèmes",
|
||||
"Many Issues": "De nombreux problèmes",
|
||||
"Past 24 Hours": "Dernières 24 heures",
|
||||
"Past 30 Days": "Derniers 30 jours",
|
||||
"Custom Range": "Plage personnalisée",
|
||||
"Unknown Country": "Pays inconnu",
|
||||
"design": "Design",
|
||||
"note": "Note",
|
||||
"issue": "Problème",
|
||||
"Set Alerts": "Définir des alertes",
|
||||
"Confirm Card Deletion": "Confirmer la suppression de la carte",
|
||||
"Are you sure you want to remove this card? This action is permanent and cannot be undone.": "Êtes-vous sûr de vouloir supprimer cette carte ? Cette action est permanente et ne peut pas être annulée.",
|
||||
"Failed to remove card": "Échec de la suppression de la carte",
|
||||
"Filters on Left": "Filtres à gauche",
|
||||
"Filters on Top": "Filtres en haut",
|
||||
"Filters on Right": "Filtres à droite",
|
||||
"Call user to initiate remote control": "Appeler l'utilisateur pour initier le contrôle à distance",
|
||||
"Click to rename": "Cliquer pour renommer",
|
||||
"Shared with team": "Partagé avec l'équipe",
|
||||
"Conversion lost": "Conversion perdue",
|
||||
"Toggle Autoplay": "Activer/désactiver la lecture automatique",
|
||||
"Open in new tab": "Ouvrir dans un nouvel onglet",
|
||||
"Highlight a moment": "Mettre en avant un moment",
|
||||
"Time to execute": "Temps d'exécution",
|
||||
"Inspect your application state while you’re replaying your users sessions. OpenReplay supports": "Inspectez l'état de votre application pendant la lecture des sessions des utilisateurs. OpenReplay prend en charge",
|
||||
"Autoplay is ON": "La lecture automatique est activée",
|
||||
"Autoplay is OFF": "La lecture automatique est désactivée",
|
||||
"Click to copy": "Cliquer pour copier",
|
||||
"Stack Events overview is available only for all tabs combined.": "L'aperçu des événements de la pile est disponible uniquement pour toutes les onglets combinés.",
|
||||
"Clear all selection": "Effacer toutes les sélections",
|
||||
"Clear Steps": "Effacer les étapes",
|
||||
"Session Settings": "Paramètres de session",
|
||||
"Select the operator to be applied between events.": "Sélectionnez l'opérateur à appliquer entre les événements.",
|
||||
"above": "au-dessus de",
|
||||
"above or equal to": "supérieur ou égal à",
|
||||
"below": "en dessous de",
|
||||
"below or equal to": "inférieur ou égal à"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -579,7 +579,7 @@
|
|||
"Add Exclusion": "Добавить исключение",
|
||||
"Significant issues": "Значительные проблемы",
|
||||
"in this funnel": "в этой воронке",
|
||||
"Click Rage": "Rage-клик",
|
||||
"Click Rage": "Click Rage",
|
||||
"Dead Click": "Мёртвый клик",
|
||||
"Bad Request": "Некорректный запрос",
|
||||
"Missing Image": "Отсутствующее изображение",
|
||||
|
|
@ -944,7 +944,7 @@
|
|||
"s to enter a value in this input field.": "c, чтобы ввести значение в это поле.",
|
||||
"View": "Просмотр",
|
||||
"Mouse Thrashing": "Беспорядочные движения мыши",
|
||||
"Speed Index": "Инденс скорости",
|
||||
"Speed Index": "Индекс скорости",
|
||||
"Copy CSS": "Копировать CSS",
|
||||
"Copy URL": "Копировать URL",
|
||||
"Referrer:": "Реферер:",
|
||||
|
|
@ -1448,5 +1448,43 @@
|
|||
"Select Series": "Выбрать серию",
|
||||
"Integrate Github": "Интеграция с Github",
|
||||
"Integrate GraphQL": "Интеграция с GraphQL",
|
||||
"Installation Docs": "Документация по установке"
|
||||
"Installation Docs": "Документация по установке",
|
||||
"Good": "Хорошо",
|
||||
"Few Issues": "Есть проблемы",
|
||||
"Many Issues": "Много проблем",
|
||||
"Past 24 Hours": "Последние 24 часа",
|
||||
"Past 30 Days": "Последние 30 дней",
|
||||
"Custom Range": "Произвольный диапазон",
|
||||
"Unknown Country": "Неизвестная страна",
|
||||
"design": "Дизайн",
|
||||
"note": "Заметка",
|
||||
"issue": "Проблема",
|
||||
"Set Alerts": "Установить уведомления",
|
||||
"Confirm Card Deletion": "Подтвердить удаление карточки",
|
||||
"Are you sure you want to remove this card? This action is permanent and cannot be undone.": "Вы уверены, что хотите удалить эту карточку? Это действие необратимо.",
|
||||
"Failed to remove card": "Не удалось удалить карточку",
|
||||
"Filters on Left": "Фильтры слева",
|
||||
"Filters on Top": "Фильтры сверху",
|
||||
"Filters on Right": "Фильтры справа",
|
||||
"Call user to initiate remote control": "Позвонить пользователю для начала удаленного управления",
|
||||
"Click to rename": "Нажмите, чтобы переименовать",
|
||||
"Shared with team": "Доступно команде",
|
||||
"Conversion lost": "Потерянные конверсии",
|
||||
"Toggle Autoplay": "Включить автовоспроизведение",
|
||||
"Open in new tab": "Открыть в новой вкладке",
|
||||
"Highlight a moment": "Выделить момент",
|
||||
"Time to execute": "Время выполнения",
|
||||
"Inspect your application state while you’re replaying your users sessions. OpenReplay supports": "Изучайте состояние вашего приложения во время воспроизведения сессий пользователей. OpenReplay поддерживает",
|
||||
"Autoplay is ON": "Автовоспроизведение включено",
|
||||
"Autoplay is OFF": "Автовоспроизведение выключено",
|
||||
"Click to copy": "Нажмите, чтобы скопировать",
|
||||
"Stack Events overview is available only for all tabs combined.": "Обзор событий стека доступен только для всех вкладок вместе.",
|
||||
"Clear all selection": "Очистить все выборы",
|
||||
"Clear Steps": "Очистить шаги",
|
||||
"Session Settings": "Настройки сессии",
|
||||
"Select the operator to be applied between events.": "Выберите оператор, который будет применен между событиями.",
|
||||
"above": "выше",
|
||||
"above or equal to": "выше или равно",
|
||||
"below": "ниже",
|
||||
"below or equal to": "ниже или равно"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1448,5 +1448,43 @@
|
|||
"Select Series": "选择系列",
|
||||
"Integrate Github": "集成 Github",
|
||||
"Integrate GraphQL": "集成 GraphQL",
|
||||
"Installation Docs": "安装文档"
|
||||
"Installation Docs": "安装文档",
|
||||
"Good": "良好",
|
||||
"Few Issues": "少量问题",
|
||||
"Many Issues": "大量问题",
|
||||
"Past 24 Hours": "过去 24 小时",
|
||||
"Past 30 Days": "过去 30 天",
|
||||
"Custom Range": "自定义范围",
|
||||
"Unknown Country": "未知国家",
|
||||
"design": "设计",
|
||||
"note": "备注",
|
||||
"issue": "问题",
|
||||
"Set Alerts": "设置提醒",
|
||||
"Confirm Card Deletion": "确认删除卡片",
|
||||
"Are you sure you want to remove this card? This action is permanent and cannot be undone.": "您确定要删除此卡片吗?此操作是永久性的,无法撤销。",
|
||||
"Failed to remove card": "删除卡片失败",
|
||||
"Filters on Left": "左侧筛选器",
|
||||
"Filters on Top": "顶部筛选器",
|
||||
"Filters on Right": "右侧筛选器",
|
||||
"Call user to initiate remote control": "呼叫用户以启动远程控制",
|
||||
"Click to rename": "点击重命名",
|
||||
"Shared with team": "已与团队共享",
|
||||
"Conversion lost": "转化丢失",
|
||||
"Toggle Autoplay": "切换自动播放",
|
||||
"Open in new tab": "在新标签页中打开",
|
||||
"Highlight a moment": "突出显示时刻",
|
||||
"Time to execute": "执行时间",
|
||||
"Inspect your application state while you’re replaying your users sessions. OpenReplay supports": "在回放用户会话时检查您的应用程序状态。OpenReplay 支持",
|
||||
"Autoplay is ON": "自动播放已开启",
|
||||
"Autoplay is OFF": "自动播放已关闭",
|
||||
"Click to copy": "点击复制",
|
||||
"Stack Events overview is available only for all tabs combined.": "堆栈事件概览仅适用于所有选项卡的组合视图。",
|
||||
"Clear all selection": "清除所有选择",
|
||||
"Clear Steps": "清除步骤",
|
||||
"Session Settings": "会话设置",
|
||||
"Select the operator to be applied between events.": "选择要应用于事件之间的运算符。",
|
||||
"above": "大于",
|
||||
"above or equal to": "大于或等于",
|
||||
"below": "小于",
|
||||
"below or equal to": "小于或等于"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue