mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-17 17:55:42 +00:00
feat: add i18n with ttag
This commit is contained in:
parent
05baaf911f
commit
df0a93b8e6
@ -31,6 +31,7 @@ import LoginPage, {AuthenticatedContext} from "./pages/LoginPage";
|
||||
import ConnectorsPage from "./pages/tracking/ConnectorsPage";
|
||||
import NotFoundPage from "./pages/NotFoundPage";
|
||||
import {ItemType, MenuItemType} from "antd/lib/menu/interface";
|
||||
import {t} from 'ttag'
|
||||
|
||||
export default function App() {
|
||||
const {
|
||||
@ -67,36 +68,36 @@ export default function App() {
|
||||
const menuItems: ItemType<MenuItemType>[] = [
|
||||
{
|
||||
key: 'home',
|
||||
label: 'Home',
|
||||
label: t`Home`,
|
||||
icon: <HomeOutlined/>,
|
||||
onClick: () => navigate('/home')
|
||||
},
|
||||
{
|
||||
key: 'search',
|
||||
label: 'Search',
|
||||
label: t`Search`,
|
||||
icon: <SearchOutlined/>,
|
||||
children: [
|
||||
{
|
||||
key: 'domain-finder',
|
||||
icon: <CompassOutlined/>,
|
||||
label: 'Domain',
|
||||
title: 'Domain Finder',
|
||||
label: t`Domain`,
|
||||
title: t`Domain Finder`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/search/domain')
|
||||
},
|
||||
{
|
||||
key: 'entity-finder',
|
||||
icon: <TeamOutlined/>,
|
||||
label: 'Entity',
|
||||
title: 'Entity Finder',
|
||||
label: t`Entity`,
|
||||
title: t`Entity Finder`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/search/entity')
|
||||
},
|
||||
{
|
||||
key: 'ns-finder',
|
||||
icon: <CloudServerOutlined/>,
|
||||
label: 'Nameserver',
|
||||
title: 'Nameserver Finder',
|
||||
label: t`Nameserver`,
|
||||
title: t`Nameserver Finder`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/search/nameserver')
|
||||
}
|
||||
@ -104,21 +105,21 @@ export default function App() {
|
||||
},
|
||||
{
|
||||
key: 'info',
|
||||
label: 'Information',
|
||||
label: t`Information`,
|
||||
icon: <InfoCircleOutlined/>,
|
||||
children: [
|
||||
{
|
||||
key: 'tld-list',
|
||||
icon: <BankOutlined/>,
|
||||
label: 'TLD',
|
||||
title: 'TLD list',
|
||||
label: t`TLD`,
|
||||
title: t`TLD list`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/info/tld')
|
||||
},
|
||||
{
|
||||
key: 'stats',
|
||||
icon: <LineChartOutlined/>,
|
||||
label: 'Statistics',
|
||||
label: t`Statistics`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/info/stats')
|
||||
}
|
||||
@ -126,20 +127,20 @@ export default function App() {
|
||||
},
|
||||
{
|
||||
key: 'tracking',
|
||||
label: 'Tracking',
|
||||
label: t`Tracking`,
|
||||
icon: <FileSearchOutlined/>,
|
||||
children: [
|
||||
{
|
||||
key: 'watchlist',
|
||||
icon: <Badge count={0} size="small"><FileSearchOutlined/></Badge>,
|
||||
label: 'My Watchlists',
|
||||
label: t`My Watchlists`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/tracking/watchlist')
|
||||
},
|
||||
{
|
||||
key: 'connectors',
|
||||
icon: <ApiOutlined/>,
|
||||
label: 'My connectors',
|
||||
label: t`My connectors`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/tracking/connectors')
|
||||
}
|
||||
@ -147,26 +148,26 @@ export default function App() {
|
||||
},
|
||||
{
|
||||
key: 'watchdog',
|
||||
label: 'My Watchdog',
|
||||
label: t`My Watchdog`,
|
||||
icon: <UserOutlined/>,
|
||||
children: [
|
||||
{
|
||||
key: 'account',
|
||||
icon: <UserOutlined/>,
|
||||
label: 'My Account',
|
||||
label: t`My Account`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/user')
|
||||
},
|
||||
{
|
||||
key: 'tos',
|
||||
icon: <InfoCircleOutlined/>,
|
||||
label: 'TOS',
|
||||
label: t`TOS`,
|
||||
onClick: () => navigate('/tos')
|
||||
},
|
||||
{
|
||||
key: 'privacy',
|
||||
icon: <FileProtectOutlined/>,
|
||||
label: 'Privacy Policy',
|
||||
label: t`Privacy Policy`,
|
||||
onClick: () => navigate('/privacy')
|
||||
}
|
||||
]
|
||||
@ -174,7 +175,7 @@ export default function App() {
|
||||
{
|
||||
key: '5',
|
||||
icon: <QuestionCircleOutlined/>,
|
||||
label: 'FAQ',
|
||||
label: t`FAQ`,
|
||||
onClick: () => navigate('/faq')
|
||||
},
|
||||
|
||||
@ -192,13 +193,13 @@ export default function App() {
|
||||
items={[...menuItems, isAuthenticated ? {
|
||||
key: '8',
|
||||
icon: <LogoutOutlined/>,
|
||||
label: 'Log out',
|
||||
label: t`Log out`,
|
||||
danger: true,
|
||||
onClick: () => window.location.replace("/logout")
|
||||
} : {
|
||||
key: '8',
|
||||
icon: <LoginOutlined/>,
|
||||
label: 'Log in',
|
||||
label: t`Log in`,
|
||||
onClick: () => navigate('/login')
|
||||
}]}
|
||||
/>
|
||||
|
||||
13
assets/i18n/index.ts
Normal file
13
assets/i18n/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import {addLocale, useLocale} from 'ttag'
|
||||
|
||||
const locale = navigator.language.split('-')[0];
|
||||
|
||||
if (locale !== 'en') {
|
||||
fetch(`/locales/${locale}.po.json`).then(response => {
|
||||
if (!response.ok) throw new Error(`Failed to load translations for locale ${locale}`);
|
||||
response.json().then(translationsObj => {
|
||||
addLocale(locale, translationsObj);
|
||||
useLocale(locale);
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -4,6 +4,7 @@ import App from "./App";
|
||||
import {HashRouter} from "react-router-dom";
|
||||
|
||||
import 'antd/dist/reset.css';
|
||||
import './i18n'
|
||||
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement)
|
||||
|
||||
@ -2,6 +2,7 @@ import React, {createContext, useContext, useState} from "react";
|
||||
import {Alert, Button, Card, Flex, Form, Input} from "antd";
|
||||
import {login} from "../utils/api";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
import {t} from 'ttag'
|
||||
|
||||
type FieldType = {
|
||||
username: string;
|
||||
@ -14,7 +15,7 @@ export default function Page() {
|
||||
|
||||
const [error, setError] = useState()
|
||||
const navigate = useNavigate()
|
||||
const {isAuthenticated, setIsAuthenticated} = useContext(AuthenticatedContext)
|
||||
const {setIsAuthenticated} = useContext(AuthenticatedContext)
|
||||
|
||||
const onFinish = (data: FieldType) => {
|
||||
login(data.username, data.password).then(() => {
|
||||
@ -27,12 +28,12 @@ export default function Page() {
|
||||
}
|
||||
|
||||
return <Flex gap="middle" align="center" justify="center" vertical><Card
|
||||
title="Log in"
|
||||
title={t`Log in`}
|
||||
>
|
||||
{error &&
|
||||
<Alert
|
||||
type='error'
|
||||
message='Error'
|
||||
message={t`Error`}
|
||||
banner={true}
|
||||
role='role'
|
||||
description={error}
|
||||
@ -47,29 +48,29 @@ export default function Page() {
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item
|
||||
label="Username"
|
||||
label={t`Username`}
|
||||
name="username"
|
||||
rules={[{required: true, message: 'Required'}]}
|
||||
rules={[{required: true, message: t`Required`}]}
|
||||
>
|
||||
<Input/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<FieldType>
|
||||
label="Password"
|
||||
label={t`Password`}
|
||||
name="password"
|
||||
rules={[{required: true, message: 'Required'}]}
|
||||
rules={[{required: true, message: t`Required`}]}
|
||||
>
|
||||
<Input.Password/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item wrapperCol={{offset: 8, span: 16}}>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Submit
|
||||
{t`Submit`}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<Form.Item wrapperCol={{offset: 8, span: 16}}>
|
||||
<Button type="primary" htmlType="button" href="/login/oauth">
|
||||
Log in with SSO
|
||||
{t`Log in with SSO`}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import {Result} from "antd";
|
||||
import React from "react";
|
||||
import { t } from 'ttag'
|
||||
|
||||
|
||||
export default function NotFoundPage() {
|
||||
return <Result
|
||||
status="404"
|
||||
title="404"
|
||||
subTitle="Sorry, the page you visited does not exist."
|
||||
subTitle={t`Sorry, the page you visited does not exist.`}
|
||||
/>
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {Collapse, Divider, Table, Typography} from "antd";
|
||||
import {getTldList, Tld} from "../../utils/api";
|
||||
import {t} from 'ttag'
|
||||
|
||||
const {Text, Paragraph} = Typography
|
||||
|
||||
@ -60,24 +61,24 @@ function TldTable(filters: FiltersType) {
|
||||
|
||||
let columns = [
|
||||
{
|
||||
title: "TLD",
|
||||
title: t`TLD`,
|
||||
dataIndex: "TLD",
|
||||
width: 20
|
||||
}
|
||||
]
|
||||
|
||||
if (filters.type === 'ccTLD') columns = [...columns, {
|
||||
title: "Flag",
|
||||
title: t`Flag`,
|
||||
dataIndex: "Flag",
|
||||
width: 20
|
||||
}, {
|
||||
title: "Country",
|
||||
title: t`Country`,
|
||||
dataIndex: "Country",
|
||||
width: 200
|
||||
}]
|
||||
|
||||
if (filters.type === 'gTLD') columns = [...columns, {
|
||||
title: "Registry Operator",
|
||||
title: t`Registry Operator`,
|
||||
dataIndex: "Operator",
|
||||
width: 50
|
||||
}]
|
||||
@ -102,16 +103,13 @@ function TldTable(filters: FiltersType) {
|
||||
export default function TldPage() {
|
||||
return <>
|
||||
<Paragraph>
|
||||
This page presents all active TLDs in the root zone database.
|
||||
{t`This page presents all active TLDs in the root zone database.`}
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
IANA provides the list of currently active
|
||||
TLDs, regardless of their type, and ICANN provides the list of gTLDs.
|
||||
In most cases, the two-letter ccTLD assigned to a country is made in accordance with the ISO 3166-1
|
||||
standard.
|
||||
This data is updated every month. Three HTTP requests are needed for the complete update of TLDs in Domain
|
||||
Watchdog (two requests to IANA and one to ICANN).
|
||||
At the same time, the list of root RDAP servers is updated.
|
||||
{t`IANA provides the list of currently active TLDs, regardless of their type, and ICANN provides the list of gTLDs.
|
||||
In most cases, the two-letter ccTLD assigned to a country is made in accordance with the ISO 3166-1 standard.
|
||||
This data is updated every month. Three HTTP requests are needed for the complete update of TLDs in Domain Watchdog (two requests to IANA and one to ICANN).
|
||||
At the same time, the list of root RDAP servers is updated.`}
|
||||
</Paragraph>
|
||||
<Divider/>
|
||||
<Collapse
|
||||
@ -119,41 +117,36 @@ export default function TldPage() {
|
||||
items={[
|
||||
{
|
||||
key: 'sTLD',
|
||||
label: 'Sponsored Top-Level-Domains',
|
||||
label: t`Sponsored Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>Top-level domains sponsored by specific organizations that set rules for
|
||||
registration and use, often related to particular interest groups or
|
||||
industries.</Text>
|
||||
<Text>{t`Top - level domains sponsored by specific organizations that set rules for registration and use, often related to particular interest groups or industries.`}</Text>
|
||||
<Divider/>
|
||||
<TldTable type='sTLD'/>
|
||||
</>
|
||||
},
|
||||
{
|
||||
key: 'gTLD',
|
||||
label: 'Generic Top-Level-Domains',
|
||||
label: t`Generic Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>Generic top-level domains open to everyone, not restricted by specific
|
||||
criteria, representing various themes or industries.</Text>
|
||||
<Text>{t`Generic top-level domains open to everyone, not restricted by specific criteria, representing various themes or industries.`}</Text>
|
||||
<Divider/>
|
||||
<TldTable type='gTLD' contractTerminated={false} specification13={false}/>
|
||||
</>
|
||||
},
|
||||
{
|
||||
key: 'ngTLD',
|
||||
label: 'Brand Generic Top-Level-Domains',
|
||||
label: t`Brand Generic Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>Generic top-level domains associated with specific brands, allowing companies
|
||||
to use their own brand names as domains.</Text>
|
||||
<Text>{t`Generic top-level domains associated with specific brands, allowing companies to use their own brand names as domains.`}</Text>
|
||||
<Divider/>
|
||||
<TldTable type='gTLD' contractTerminated={false} specification13={true}/>
|
||||
</>
|
||||
},
|
||||
{
|
||||
key: 'ccTLD',
|
||||
label: 'Country-Code Top-Level-Domains',
|
||||
label: t`Country-Code Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>Top-level domains based on country codes, identifying websites according to
|
||||
their country of origin.</Text>
|
||||
<Text>{`Top-level domains based on country codes, identifying websites according to their country of origin.`}</Text>
|
||||
<Divider/><TldTable type='ccTLD'/>
|
||||
</>
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ import {
|
||||
import {Domain, getDomain} from "../../utils/api";
|
||||
import {AxiosError} from "axios"
|
||||
import vCard from 'vcf'
|
||||
import {t} from 'ttag'
|
||||
|
||||
|
||||
type FieldType = {
|
||||
@ -48,16 +49,16 @@ export default function DomainSearchPage() {
|
||||
setDomain(null)
|
||||
getDomain(values.ldhName).then(d => {
|
||||
setDomain(d)
|
||||
messageApi.success('Found !')
|
||||
messageApi.success(t`Found !`)
|
||||
}).catch((e: AxiosError) => {
|
||||
const data = e?.response?.data as { detail: string }
|
||||
setDomain(undefined)
|
||||
messageApi.error(data.detail ?? 'An error occurred')
|
||||
messageApi.error(data.detail ?? t`An error occurred`)
|
||||
})
|
||||
}
|
||||
|
||||
return <Flex gap="middle" align="center" justify="center" vertical>
|
||||
<Card title="Domain finder" style={{width: '100%'}}>
|
||||
<Card title={t`Domain finder`} style={{width: '100%'}}>
|
||||
{contextHolder}
|
||||
<Form
|
||||
name="basic"
|
||||
@ -70,10 +71,10 @@ export default function DomainSearchPage() {
|
||||
name="ldhName"
|
||||
rules={[{
|
||||
required: true,
|
||||
message: 'Required'
|
||||
message: t`Required`
|
||||
}, {
|
||||
pattern: /^(?=.*\.)\S*[^.\s]$/,
|
||||
message: 'This domain name does not appear to be valid',
|
||||
message: t`This domain name does not appear to be valid`,
|
||||
max: 63,
|
||||
min: 2
|
||||
}]}
|
||||
@ -189,8 +190,7 @@ export default function DomainSearchPage() {
|
||||
: <Empty
|
||||
description={
|
||||
<Typography.Text>
|
||||
Although the domain exists in my database, it has been deleted from the WHOIS by its
|
||||
registrar.
|
||||
{t`Although the domain exists in my database, it has been deleted from the WHOIS by its registrar.`}
|
||||
</Typography.Text>
|
||||
}/>)
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import {Button, Card, Divider, Flex, Form, Input, message, Popconfirm, Select, S
|
||||
import {DeleteFilled, MinusCircleOutlined, PlusOutlined, ThunderboltFilled} from "@ant-design/icons";
|
||||
import {deleteWatchlist, EventAction, getWatchlists, postWatchlist} from "../../utils/api";
|
||||
import {AxiosError} from "axios";
|
||||
import {t} from 'ttag'
|
||||
|
||||
|
||||
const formItemLayout = {
|
||||
@ -26,42 +27,42 @@ const formItemLayoutWithOutLabel = {
|
||||
|
||||
const triggerEventItems: { label: string, value: EventAction }[] = [
|
||||
{
|
||||
label: 'When a domain is expired',
|
||||
label: t`When a domain is expired`,
|
||||
value: 'expiration'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is updated',
|
||||
label: t`When a domain is updated`,
|
||||
value: 'last changed'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is deleted',
|
||||
label: t`When a domain is deleted`,
|
||||
value: 'deletion'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is transferred',
|
||||
label: t`When a domain is transferred`,
|
||||
value: 'transfer'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is locked',
|
||||
label: t`When a domain is locked`,
|
||||
value: 'locked'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is unlocked',
|
||||
label: t`When a domain is unlocked`,
|
||||
value: 'unlocked'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is reregistered',
|
||||
label: t`When a domain is reregistered`,
|
||||
value: 'reregistration'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is reinstantiated',
|
||||
label: t`When a domain is reinstantiated`,
|
||||
value: 'reinstantiation'
|
||||
}
|
||||
]
|
||||
|
||||
const trigerActionItems = [
|
||||
{
|
||||
label: 'Send me an email',
|
||||
label: t`Send me an email`,
|
||||
value: 'email'
|
||||
}
|
||||
]
|
||||
@ -78,10 +79,10 @@ export default function WatchlistPage() {
|
||||
postWatchlist(domainsURI, values.triggers).then((w) => {
|
||||
form.resetFields()
|
||||
refreshWatchlists()
|
||||
messageApi.success('Watchlist created !')
|
||||
messageApi.success(t`Watchlist created !`)
|
||||
}).catch((e: AxiosError) => {
|
||||
const data = e?.response?.data as { detail: string }
|
||||
messageApi.error(data.detail ?? 'An error occurred')
|
||||
messageApi.error(data.detail ?? t`An error occurred`)
|
||||
})
|
||||
}
|
||||
|
||||
@ -94,7 +95,7 @@ export default function WatchlistPage() {
|
||||
}, [])
|
||||
|
||||
return <Flex gap="middle" align="center" justify="center" vertical>
|
||||
<Card title="Create a watchlist" style={{width: '100%'}}>
|
||||
<Card title={t`Create a watchlist`} style={{width: '100%'}}>
|
||||
{contextHolder}
|
||||
<Form
|
||||
{...formItemLayoutWithOutLabel}
|
||||
@ -107,7 +108,7 @@ export default function WatchlistPage() {
|
||||
{
|
||||
validator: async (_, domains) => {
|
||||
if (!domains || domains.length < 1) {
|
||||
return Promise.reject(new Error('At least one domain name'));
|
||||
return Promise.reject(new Error(t`At least one domain name`));
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -118,7 +119,7 @@ export default function WatchlistPage() {
|
||||
{fields.map((field, index) => (
|
||||
<Form.Item
|
||||
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
|
||||
label={index === 0 ? 'Domain names' : ''}
|
||||
label={index === 0 ? t`Domain names` : ''}
|
||||
required={true}
|
||||
key={field.key}
|
||||
>
|
||||
@ -127,16 +128,16 @@ export default function WatchlistPage() {
|
||||
validateTrigger={['onChange', 'onBlur']}
|
||||
rules={[{
|
||||
required: true,
|
||||
message: 'Required'
|
||||
message: t`Required`
|
||||
}, {
|
||||
pattern: /^(?=.*\.)\S*[^.\s]$/,
|
||||
message: 'This domain name does not appear to be valid',
|
||||
message: t`This domain name does not appear to be valid`,
|
||||
max: 63,
|
||||
min: 2
|
||||
}]}
|
||||
noStyle
|
||||
>
|
||||
<Input placeholder="Domain name" style={{width: '60%'}} autoComplete='off'/>
|
||||
<Input placeholder={t`Domain name`} style={{width: '60%'}} autoComplete='off'/>
|
||||
</Form.Item>
|
||||
{fields.length > 1 ? (
|
||||
<MinusCircleOutlined
|
||||
@ -153,7 +154,7 @@ export default function WatchlistPage() {
|
||||
style={{width: '60%'}}
|
||||
icon={<PlusOutlined/>}
|
||||
>
|
||||
Add a Domain name
|
||||
{t`Add a Domain name`}
|
||||
</Button>
|
||||
<Form.ErrorList errors={errors}/>
|
||||
</Form.Item>
|
||||
@ -166,7 +167,7 @@ export default function WatchlistPage() {
|
||||
{
|
||||
validator: async (_, domains) => {
|
||||
if (!domains || domains.length < 1) {
|
||||
return Promise.reject(new Error('At least one domain trigger'));
|
||||
return Promise.reject(new Error(t`At least one domain trigger`));
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -177,7 +178,7 @@ export default function WatchlistPage() {
|
||||
{fields.map((field, index) => (
|
||||
<Form.Item
|
||||
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
|
||||
label={index === 0 ? 'Domain trigger' : ''}
|
||||
label={index === 0 ? t`Domain trigger` : ''}
|
||||
required={true}
|
||||
key={field.key}
|
||||
>
|
||||
@ -187,21 +188,21 @@ export default function WatchlistPage() {
|
||||
validateTrigger={['onChange', 'onBlur']}
|
||||
rules={[{
|
||||
required: true,
|
||||
message: 'Required'
|
||||
message: t`Required`
|
||||
}]}
|
||||
noStyle name={[field.name, 'event']}>
|
||||
<Select style={{minWidth: 300}} options={triggerEventItems} showSearch
|
||||
placeholder="If this happens" optionFilterProp="label"/>
|
||||
placeholder={t`If this happens`} optionFilterProp="label"/>
|
||||
</Form.Item>
|
||||
<Form.Item {...field}
|
||||
validateTrigger={['onChange', 'onBlur']}
|
||||
rules={[{
|
||||
required: true,
|
||||
message: 'Required'
|
||||
message: t`Required`
|
||||
}]}
|
||||
noStyle name={[field.name, 'action']}>
|
||||
<Select style={{minWidth: 300}} options={trigerActionItems} showSearch
|
||||
placeholder="Then do that"
|
||||
placeholder={t`Then do that`}
|
||||
optionFilterProp="label"/>
|
||||
</Form.Item>
|
||||
</Space>
|
||||
@ -222,7 +223,7 @@ export default function WatchlistPage() {
|
||||
style={{width: '60%'}}
|
||||
icon={<ThunderboltFilled/>}
|
||||
>
|
||||
Add a Trigger
|
||||
{t`Add a Trigger`}
|
||||
</Button>
|
||||
<Form.ErrorList errors={errors}/>
|
||||
</Form.Item>
|
||||
@ -232,10 +233,10 @@ export default function WatchlistPage() {
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Create
|
||||
{t`Create`}
|
||||
</Button>
|
||||
<Button type="default" htmlType="reset">
|
||||
Reset
|
||||
{t`Reset`}
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
@ -247,19 +248,19 @@ export default function WatchlistPage() {
|
||||
{watchlists && watchlists.length > 0 && <Card title="My Watchlists" style={{width: '100%'}}>
|
||||
{watchlists.map(watchlist =>
|
||||
<>
|
||||
<Card title={"Watchlist " + watchlist.token} extra={<Popconfirm
|
||||
title="Delete the Watchlist"
|
||||
description="Are you sure to delete this Watchlist ?"
|
||||
<Card title={t`Watchlist ${watchlist.token}`} extra={<Popconfirm
|
||||
title={t`"Delete the Watchlist"`}
|
||||
description={t`Are you sure to delete this Watchlist?`}
|
||||
onConfirm={() => deleteWatchlist(watchlist.token).then(refreshWatchlists)}
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
okText={t`"Yes"`}
|
||||
cancelText={t`No`}
|
||||
><DeleteFilled/> </Popconfirm>}>
|
||||
<Typography.Paragraph>
|
||||
Domains : {watchlist?.domains.map(d => d.ldhName).join(',')}
|
||||
{t`Domain name`} : {watchlist?.domains.map(d => d.ldhName).join(',')}
|
||||
</Typography.Paragraph>
|
||||
{
|
||||
watchlist.triggers && <Typography.Paragraph>
|
||||
Triggers : {watchlist.triggers.map(t => `${t.event} => ${t.action}`).join(',')}
|
||||
{t`Domain triggers`} : {watchlist.triggers.map(t => `${t.event} => ${t.action}`).join(',')}
|
||||
</Typography.Paragraph>
|
||||
}
|
||||
</Card>
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
"regenerator-runtime": "^0.13.9",
|
||||
"snarkdown": "^2.0.0",
|
||||
"ts-loader": "^9.5.1",
|
||||
"ttag": "^1.8.7",
|
||||
"typescript": "^5.5.3",
|
||||
"vcf": "^2.1.2",
|
||||
"webpack": "^5.74.0",
|
||||
|
||||
1
public/locales/.gitignore
vendored
Normal file
1
public/locales/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.po.json
|
||||
318
public/locales/fr.po
Normal file
318
public/locales/fr.po
Normal file
@ -0,0 +1,318 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Plural-Forms: nplurals = 2; plural = (n > 1);\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: assets/pages/NotFoundPage.tsx:10
|
||||
msgid "Sorry, the page you visited does not exist."
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:114
|
||||
#: assets/pages/info/TldPage.tsx:64
|
||||
msgid "TLD"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:71
|
||||
msgid "Flag"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:75
|
||||
msgid "Country"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:81
|
||||
msgid "Registry Operator"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:106
|
||||
msgid "This page presents all active TLDs in the root zone database."
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:109
|
||||
msgid ""
|
||||
"IANA provides the list of currently active TLDs, regardless of their type, and ICANN provides the list of gTLDs.\n"
|
||||
"In most cases, the two-letter ccTLD assigned to a country is made in accordance with the ISO 3166-1 standard.\n"
|
||||
"This data is updated every month. Three HTTP requests are needed for the complete update of TLDs in Domain Watchdog (two requests to IANA and one to ICANN).\n"
|
||||
"At the same time, the list of root RDAP servers is updated."
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:120
|
||||
msgid "Sponsored Top-Level-Domains"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:122
|
||||
msgid "Top - level domains sponsored by specific organizations that set rules for registration and use, often related to particular interest groups or industries."
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:129
|
||||
msgid "Generic Top-Level-Domains"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:131
|
||||
msgid "Generic top-level domains open to everyone, not restricted by specific criteria, representing various themes or industries."
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:138
|
||||
msgid "Brand Generic Top-Level-Domains"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:140
|
||||
msgid "Generic top-level domains associated with specific brands, allowing companies to use their own brand names as domains."
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/info/TldPage.tsx:147
|
||||
msgid "Country-Code Top-Level-Domains"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:202
|
||||
#: assets/pages/LoginPage.tsx:31
|
||||
msgid "Log in"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/LoginPage.tsx:36
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/LoginPage.tsx:51
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/LoginPage.tsx:53
|
||||
#: assets/pages/LoginPage.tsx:61
|
||||
#: assets/pages/search/DomainSearchPage.tsx:74
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:131
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:191
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:201
|
||||
msgid "Required"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/LoginPage.tsx:59
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/LoginPage.tsx:68
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/LoginPage.tsx:73
|
||||
msgid "Log in with SSO"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/search/DomainSearchPage.tsx:52
|
||||
msgid "Found !"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/search/DomainSearchPage.tsx:56
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:85
|
||||
msgid "An error occurred"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/search/DomainSearchPage.tsx:61
|
||||
msgid "Domain finder"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/search/DomainSearchPage.tsx:77
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:134
|
||||
msgid "This domain name does not appear to be valid"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/search/DomainSearchPage.tsx:193
|
||||
msgid "Although the domain exists in my database, it has been deleted from the WHOIS by its registrar."
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:30
|
||||
msgid "When a domain is expired"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:34
|
||||
msgid "When a domain is updated"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:38
|
||||
msgid "When a domain is deleted"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:42
|
||||
msgid "When a domain is transferred"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:46
|
||||
msgid "When a domain is locked"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:50
|
||||
msgid "When a domain is unlocked"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:54
|
||||
msgid "When a domain is reregistered"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:58
|
||||
msgid "When a domain is reinstantiated"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:65
|
||||
msgid "Send me an email"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:82
|
||||
msgid "Watchlist created !"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:98
|
||||
msgid "Create a watchlist"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:111
|
||||
msgid "At least one domain name"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:122
|
||||
msgid "Domain names"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:140
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:259
|
||||
msgid "Domain name"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:157
|
||||
msgid "Add a Domain name"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:170
|
||||
msgid "At least one domain trigger"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:181
|
||||
msgid "Domain trigger"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:195
|
||||
msgid "If this happens"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:205
|
||||
msgid "Then do that"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:226
|
||||
msgid "Add a Trigger"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:236
|
||||
msgid "Create"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:239
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:251
|
||||
#, javascript-format
|
||||
msgid "Watchlist ${ watchlist.token }"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:252
|
||||
msgid "\"Delete the Watchlist\""
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:253
|
||||
msgid "Are you sure to delete this Watchlist?"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:255
|
||||
msgid "\"Yes\""
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:256
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: assets/pages/tracking/WatchlistPage.tsx:263
|
||||
msgid "Domain triggers"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:71
|
||||
msgid "Home"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:77
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:83
|
||||
msgid "Domain"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:84
|
||||
msgid "Domain Finder"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:91
|
||||
msgid "Entity"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:92
|
||||
msgid "Entity Finder"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:99
|
||||
msgid "Nameserver"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:100
|
||||
msgid "Nameserver Finder"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:108
|
||||
msgid "Information"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:115
|
||||
msgid "TLD list"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:122
|
||||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:130
|
||||
msgid "Tracking"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:136
|
||||
msgid "My Watchlists"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:143
|
||||
msgid "My connectors"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:151
|
||||
msgid "My Watchdog"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:157
|
||||
msgid "My Account"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:164
|
||||
msgid "TOS"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:170
|
||||
msgid "Privacy Policy"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:178
|
||||
msgid "FAQ"
|
||||
msgstr ""
|
||||
|
||||
#: assets/App.tsx:196
|
||||
msgid "Log out"
|
||||
msgstr ""
|
||||
18
yarn.lock
18
yarn.lock
@ -2522,6 +2522,11 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.3.1:
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
dedent@1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff"
|
||||
integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==
|
||||
|
||||
default-gateway@^6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71"
|
||||
@ -4267,6 +4272,11 @@ pkg-up@^3.1.0:
|
||||
dependencies:
|
||||
find-up "^3.0.0"
|
||||
|
||||
plural-forms@^0.5.3:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.yarnpkg.com/plural-forms/-/plural-forms-0.5.5.tgz#d15ca5597aff37373c97edc039ba11659461120e"
|
||||
integrity sha512-rJw4xp22izsfJOVqta5Hyvep2lR3xPkFUtj7dyQtpf/FbxUiX7PQCajTn2EHDRylizH5N/Uqqodfdu22I0ju+g==
|
||||
|
||||
possible-typed-array-names@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f"
|
||||
@ -5687,6 +5697,14 @@ tslib@^2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
|
||||
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
||||
|
||||
ttag@^1.8.7:
|
||||
version "1.8.7"
|
||||
resolved "https://registry.yarnpkg.com/ttag/-/ttag-1.8.7.tgz#0a5621f18f727379cbe21df2a02dab66a2d9b614"
|
||||
integrity sha512-k9Ym8cvG7SHwikudT6GHe0Qmy1D+Ib1q87lKRQbQIGxUdHbaXgbU5p1gv2wcO5ouhjMorm/X0MvMNgr3iyI1JA==
|
||||
dependencies:
|
||||
dedent "1.5.1"
|
||||
plural-forms "^0.5.3"
|
||||
|
||||
type-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user