Translate dashboard to Vietnamese with i18n

This commit is contained in:
hoangnd
2018-10-25 13:52:03 +07:00
parent f8ee8a7907
commit e1069f6bd1
15 changed files with 240 additions and 59 deletions

View File

@@ -2,6 +2,7 @@ import React, { Component } from 'react';
import ReactTable from 'react-table';
import PropTypes from 'prop-types';
import map from 'lodash/map';
import { withNamespaces, Trans } from 'react-i18next';
import Card from '../ui/Card';
import Cell from '../ui/Cell';
@@ -29,7 +30,7 @@ class BlockedDomains extends Component {
);
},
}, {
Header: 'Requests count',
Header: <Trans>Requests count</Trans>,
accessor: 'domain',
maxWidth: 190,
Cell: ({ value }) => {
@@ -48,15 +49,16 @@ class BlockedDomains extends Component {
}];
render() {
const { t } = this.props;
return (
<Card title="Top blocked domains" subtitle="for the last 24 hours" bodyType="card-table" refresh={this.props.refreshButton}>
<Card title={ t('Top blocked domains') } subtitle={ t('for the last 24 hours') } bodyType="card-table" refresh={this.props.refreshButton}>
<ReactTable
data={map(this.props.topBlockedDomains, (value, prop) => (
{ ip: prop, domain: value }
))}
columns={this.columns}
showPagination={false}
noDataText="No domains found"
noDataText={ t('No domains found') }
minRows={6}
className="-striped -highlight card-table-overflow stats__table"
/>
@@ -71,6 +73,7 @@ BlockedDomains.propTypes = {
replacedSafebrowsing: PropTypes.number.isRequired,
replacedParental: PropTypes.number.isRequired,
refreshButton: PropTypes.node.isRequired,
t: PropTypes.func,
};
export default BlockedDomains;
export default withNamespaces()(BlockedDomains);

View File

@@ -2,6 +2,7 @@ import React, { Component } from 'react';
import ReactTable from 'react-table';
import PropTypes from 'prop-types';
import map from 'lodash/map';
import { Trans, withNamespaces } from 'react-i18next';
import Card from '../ui/Card';
import Cell from '../ui/Cell';
@@ -24,7 +25,7 @@ class Clients extends Component {
accessor: 'ip',
Cell: ({ value }) => (<div className="logs__row logs__row--overflow"><span className="logs__text" title={value}>{value}</span></div>),
}, {
Header: 'Requests count',
Header: <Trans>Requests count</Trans>,
accessor: 'count',
Cell: ({ value }) => {
const percent = getPercent(this.props.dnsQueries, value);
@@ -37,15 +38,16 @@ class Clients extends Component {
}];
render() {
const { t } = this.props;
return (
<Card title="Top clients" subtitle="for the last 24 hours" bodyType="card-table" refresh={this.props.refreshButton}>
<Card title={ t('Top clients') } subtitle={ t('for the last 24 hours') } bodyType="card-table" refresh={this.props.refreshButton}>
<ReactTable
data={map(this.props.topClients, (value, prop) => (
{ ip: prop, count: value }
))}
columns={this.columns}
showPagination={false}
noDataText="No clients found"
noDataText={ t('No clients found') }
minRows={6}
className="-striped -highlight card-table-overflow"
/>
@@ -58,6 +60,7 @@ Clients.propTypes = {
topClients: PropTypes.object.isRequired,
dnsQueries: PropTypes.number.isRequired,
refreshButton: PropTypes.node.isRequired,
t: PropTypes.func,
};
export default Clients;
export default withNamespaces()(Clients);

View File

@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Trans, withNamespaces } from 'react-i18next';
import Card from '../ui/Card';
import Tooltip from '../ui/Tooltip';
@@ -7,13 +8,13 @@ import Tooltip from '../ui/Tooltip';
const tooltipType = 'tooltip-custom--narrow';
const Counters = props => (
<Card title="General statistics" subtitle="for the last 24 hours" bodyType="card-table" refresh={props.refreshButton}>
<Card title={ props.t('General statistics') } subtitle={ props.t('for the last 24 hours') } bodyType="card-table" refresh={props.refreshButton}>
<table className="table card-table">
<tbody>
<tr>
<td>
DNS Queries
<Tooltip text="A number of DNS quieries processed for the last 24 hours" type={tooltipType} />
<Trans>DNS Queries</Trans>
<Tooltip text={ props.t('A number of DNS quieries processed for the last 24 hours') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
@@ -23,8 +24,8 @@ const Counters = props => (
</tr>
<tr>
<td>
Blocked by <a href="#filters">Filters</a>
<Tooltip text="A number of DNS requests blocked by adblock filters and hosts blocklists" type={tooltipType} />
<Trans>Blocked by</Trans> <a href="#filters"><Trans>Filters</Trans></a>
<Tooltip text={ props.t('A number of DNS requests blocked by adblock filters and hosts blocklists') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
@@ -34,8 +35,8 @@ const Counters = props => (
</tr>
<tr>
<td>
Blocked malware/phishing
<Tooltip text="A number of DNS requests blocked by the AdGuard browsing security module" type={tooltipType} />
<Trans>Blocked malware/phishing</Trans>
<Tooltip text={ props.t('A number of DNS requests blocked by the AdGuard browsing security module') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
@@ -45,8 +46,8 @@ const Counters = props => (
</tr>
<tr>
<td>
Blocked adult websites
<Tooltip text="A number of adult websites blocked" type={tooltipType} />
<Trans>Blocked adult websites</Trans>
<Tooltip text={ props.t('A number of adult websites blocked') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
@@ -56,8 +57,8 @@ const Counters = props => (
</tr>
<tr>
<td>
Enforced safe search
<Tooltip text="A number of DNS requests to search engines for which Safe Search was enforced" type={tooltipType} />
<Trans>Enforced safe search</Trans>
<Tooltip text={ props.t('A number of DNS requests to search engines for which Safe Search was enforced') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
@@ -67,8 +68,8 @@ const Counters = props => (
</tr>
<tr>
<td>
Average processing time
<Tooltip text="Average time in milliseconds on processing a DNS request" type={tooltipType} />
<Trans>Average processing time</Trans>
<Tooltip text={ props.t('Average time in milliseconds on processing a DNS request') } type={tooltipType} />
</td>
<td className="text-right">
<span className="text-muted">
@@ -89,6 +90,7 @@ Counters.propTypes = {
replacedSafesearch: PropTypes.number.isRequired,
avgProcessingTime: PropTypes.number.isRequired,
refreshButton: PropTypes.node.isRequired,
t: PropTypes.func,
};
export default Counters;
export default withNamespaces()(Counters);

View File

@@ -2,6 +2,7 @@ import React, { Component } from 'react';
import ReactTable from 'react-table';
import PropTypes from 'prop-types';
import map from 'lodash/map';
import { withNamespaces, Trans } from 'react-i18next';
import Card from '../ui/Card';
import Cell from '../ui/Cell';
@@ -38,7 +39,7 @@ class QueriedDomains extends Component {
);
},
}, {
Header: 'Requests count',
Header: <Trans>Requests count</Trans>,
accessor: 'count',
maxWidth: 190,
Cell: ({ value }) => {
@@ -52,15 +53,16 @@ class QueriedDomains extends Component {
}];
render() {
const { t } = this.props;
return (
<Card title="Top queried domains" subtitle="for the last 24 hours" bodyType="card-table" refresh={this.props.refreshButton}>
<Card title={ t('Top queried domains') } subtitle={ t('for the last 24 hours') } bodyType="card-table" refresh={this.props.refreshButton}>
<ReactTable
data={map(this.props.topQueriedDomains, (value, prop) => (
{ ip: prop, count: value }
))}
columns={this.columns}
showPagination={false}
noDataText="No domains found"
noDataText={ t('No domains found') }
minRows={6}
className="-striped -highlight card-table-overflow stats__table"
/>
@@ -73,6 +75,7 @@ QueriedDomains.propTypes = {
topQueriedDomains: PropTypes.object.isRequired,
dnsQueries: PropTypes.number.isRequired,
refreshButton: PropTypes.node.isRequired,
t: PropTypes.func,
};
export default QueriedDomains;
export default withNamespaces()(QueriedDomains);

View File

@@ -1,5 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Trans } from 'react-i18next';
import Card from '../ui/Card';
import Line from '../ui/Line';
@@ -30,7 +31,7 @@ class Statistics extends Component {
{dnsQueries}
</div>
<div className="card-title-stats">
DNS Queries
<Trans>DNS Queries</Trans>
</div>
</div>
<div className="card-chart-bg">
@@ -48,7 +49,7 @@ class Statistics extends Component {
{getPercent(dnsQueries, blockedFiltering)}
</div>
<div className="card-title-stats">
Blocked by <a href="#filters">Filters</a>
<Trans>Blocked by</Trans> <a href="#filters"><Trans>Filters</Trans></a>
</div>
</div>
<div className="card-chart-bg">
@@ -66,7 +67,7 @@ class Statistics extends Component {
{getPercent(dnsQueries, replacedSafebrowsing)}
</div>
<div className="card-title-stats">
Blocked malware/phishing
<Trans>Blocked malware/phishing</Trans>
</div>
</div>
<div className="card-chart-bg">
@@ -84,7 +85,7 @@ class Statistics extends Component {
{getPercent(dnsQueries, replacedParental)}
</div>
<div className="card-title-stats">
Blocked adult websites
<Trans>Blocked adult websites</Trans>
</div>
</div>
<div className="card-chart-bg">

View File

@@ -1,6 +1,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import 'whatwg-fetch';
import { Trans, withNamespaces } from 'react-i18next';
import Statistics from './Statistics';
import Counters from './Counters';
@@ -30,25 +31,25 @@ class Dashboard extends Component {
return (
<button type="button" className={`btn btn-sm mr-2 ${buttonClass}`} onClick={() => this.props.toggleProtection(protectionEnabled)}>
{buttonText} protection
<Trans>{buttonText} protection</Trans>
</button>
);
}
render() {
const { dashboard } = this.props;
const { dashboard, t } = this.props;
const dashboardProcessing =
dashboard.processing ||
dashboard.processingStats ||
dashboard.processingStatsHistory ||
dashboard.processingTopStats;
const refreshFullButton = <button type="button" className="btn btn-outline-primary btn-sm" onClick={() => this.getAllStats()}>Refresh statistics</button>;
const refreshFullButton = <button type="button" className="btn btn-outline-primary btn-sm" onClick={() => this.getAllStats()}><Trans>Refresh statistics</Trans></button>;
const refreshButton = <button type="button" className="btn btn-outline-primary btn-sm card-refresh" onClick={() => this.getAllStats()} />;
return (
<Fragment>
<PageTitle title="Dashboard">
<PageTitle title={ t('Dashboard') }>
<div className="page-title__actions">
{this.getToggleFilteringButton()}
{refreshFullButton}
@@ -124,6 +125,7 @@ Dashboard.propTypes = {
isCoreRunning: PropTypes.bool,
getFiltering: PropTypes.func,
toggleProtection: PropTypes.func,
t: PropTypes.func,
};
export default Dashboard;
export default withNamespaces()(Dashboard);

View File

@@ -3,7 +3,7 @@ import { NavLink } from 'react-router-dom';
import PropTypes from 'prop-types';
import enhanceWithClickOutside from 'react-click-outside';
import classnames from 'classnames';
import { Trans } from 'react-i18next';
import { REPOSITORY } from '../../helpers/constants';
class Menu extends Component {
@@ -28,37 +28,37 @@ class Menu extends Component {
<li className="nav-item border-bottom d-lg-none" onClick={this.toggleMenu}>
<div className="nav-link nav-link--back">
<svg className="nav-icon" fill="none" height="24" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m19 12h-14"/><path d="m12 19-7-7 7-7"/></svg>
Back
<Trans>Back</Trans>
</div>
</li>
<li className="nav-item">
<NavLink to="/" exact={true} className="nav-link">
<svg className="nav-icon" fill="none" height="24" stroke="#9aa0ac" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m3 9 9-7 9 7v11a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2-2z"/><path d="m9 22v-10h6v10"/></svg>
Dashboard
<Trans>Dashboard</Trans>
</NavLink>
</li>
<li className="nav-item">
<NavLink to="/settings" className="nav-link">
<svg className="nav-icon" fill="none" height="24" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="3"/><path d="m19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1 -2.83 0l-.06-.06a1.65 1.65 0 0 0 -1.82-.33 1.65 1.65 0 0 0 -1 1.51v.17a2 2 0 0 1 -2 2 2 2 0 0 1 -2-2v-.09a1.65 1.65 0 0 0 -1.08-1.51 1.65 1.65 0 0 0 -1.82.33l-.06.06a2 2 0 0 1 -2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0 -1.51-1h-.17a2 2 0 0 1 -2-2 2 2 0 0 1 2-2h.09a1.65 1.65 0 0 0 1.51-1.08 1.65 1.65 0 0 0 -.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33h.08a1.65 1.65 0 0 0 1-1.51v-.17a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0 -.33 1.82v.08a1.65 1.65 0 0 0 1.51 1h.17a2 2 0 0 1 2 2 2 2 0 0 1 -2 2h-.09a1.65 1.65 0 0 0 -1.51 1z"/></svg>
Settings
<Trans>Settings</Trans>
</NavLink>
</li>
<li className="nav-item">
<NavLink to="/filters" className="nav-link">
<svg className="nav-icon" fill="none" height="24" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m22 3h-20l8 9.46v6.54l4 2v-8.54z"/></svg>
Filters
<Trans>Filters</Trans>
</NavLink>
</li>
<li className="nav-item">
<NavLink to="/logs" className="nav-link">
<svg className="nav-icon" fill="none" height="24" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m14 2h-8a2 2 0 0 0 -2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-12z"/><path d="m14 2v6h6"/><path d="m16 13h-8"/><path d="m16 17h-8"/><path d="m10 9h-1-1"/></svg>
Query Log
<Trans>Query Log</Trans>
</NavLink>
</li>
<li className="nav-item">
<a href={`${REPOSITORY.URL}/wiki`} className="nav-link" target="_blank" rel="noopener noreferrer">
<svg className="nav-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#66b574" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12" y2="17"></line></svg>
FAQ
<Trans>FAQ</Trans>
</a>
</li>
</ul>

View File

@@ -1,15 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Trans } from 'react-i18next';
export default function Version(props) {
const { dnsVersion, dnsAddress, dnsPort } = props;
return (
<div className="nav-version">
<div className="nav-version__text">
version: <span className="nav-version__value">{dnsVersion}</span>
<Trans>version</Trans>: <span className="nav-version__value">{dnsVersion}</span>
</div>
<div className="nav-version__text">
address: <span className="nav-version__value">{dnsAddress}:{dnsPort}</span>
<Trans>address</Trans>: <span className="nav-version__value">{dnsAddress}:{dnsPort}</span>
</div>
</div>
);

View File

@@ -2,6 +2,7 @@ import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Trans } from 'react-i18next';
import Menu from './Menu';
import Version from './Version';
@@ -44,7 +45,7 @@ class Header extends Component {
</Link>
{!dashboard.proccessing && dashboard.isCoreRunning &&
<span className={badgeClass}>
{dashboard.protectionEnabled ? 'ON' : 'OFF'}
<Trans>{dashboard.protectionEnabled ? 'ON' : 'OFF'}</Trans>
</span>
}
</div>

View File

@@ -1,4 +1,5 @@
import React, { Component } from 'react';
import { Trans } from 'react-i18next';
import { REPOSITORY } from '../../helpers/constants';
class Footer extends Component {
@@ -20,13 +21,13 @@ class Footer extends Component {
<div className="col-auto">
<ul className="list-inline text-center mb-0">
<li className="list-inline-item">
<a href={REPOSITORY.URL} target="_blank" rel="noopener noreferrer">Homepage</a>
<a href={REPOSITORY.URL} target="_blank" rel="noopener noreferrer"><Trans>Homepage</Trans></a>
</li>
</ul>
</div>
<div className="col-auto">
<a href={`${REPOSITORY.URL}/issues/new`} className="btn btn-outline-primary btn-sm" target="_blank" rel="noopener noreferrer">
Report an issue
<Trans>Report an issue</Trans>
</a>
</div>
</div>