Converted over all text to i18n

This commit is contained in:
Jamie Curnow
2021-07-26 13:38:28 +10:00
parent 7530fc7602
commit 93721ef2d8
15 changed files with 273 additions and 80 deletions

View File

@@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import { useHealthState } from "context"; import { useHealthState } from "context";
import { FormattedMessage } from "react-intl";
import styled from "styled-components"; import styled from "styled-components";
const FixedFooterWrapper = styled.div` const FixedFooterWrapper = styled.div`
@@ -28,7 +29,10 @@ function Footer({ fixed }: Props) {
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="link-secondary"> className="link-secondary">
User Guide <FormattedMessage
id="footer.userguide"
defaultMessage="User Guide"
/>
</a> </a>
</li> </li>
<li className="list-inline-item"> <li className="list-inline-item">
@@ -37,7 +41,10 @@ function Footer({ fixed }: Props) {
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="link-secondary"> className="link-secondary">
Changelog <FormattedMessage
id="footer.changelog"
defaultMessage="Change Log"
/>
</a> </a>
</li> </li>
<li className="list-inline-item"> <li className="list-inline-item">
@@ -46,7 +53,10 @@ function Footer({ fixed }: Props) {
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="link-secondary"> className="link-secondary">
Github <FormattedMessage
id="footer.github"
defaultMessage="Github"
/>
</a> </a>
</li> </li>
</ul> </ul>
@@ -54,13 +64,20 @@ function Footer({ fixed }: Props) {
<div className="col-12 col-lg-auto mt-3 mt-lg-0"> <div className="col-12 col-lg-auto mt-3 mt-lg-0">
<ul className="list-inline list-inline-dots mb-0"> <ul className="list-inline list-inline-dots mb-0">
<li className="list-inline-item"> <li className="list-inline-item">
Copyright © {new Date().getFullYear()} jc21.com. Theme by{" "} <FormattedMessage
id="footer.copyright"
defaultMessage="Copyright © {year} jc21.com."
values={{ year: new Date().getFullYear() }}
/>{" "}
<a <a
className="link-secondary" className="link-secondary"
href="https://preview.tabler.io/" href="https://preview.tabler.io/"
target="_blank" target="_blank"
rel="noreferrer"> rel="noreferrer">
Tabler <FormattedMessage
id="footer.theme"
defaultMessage="Theme by Tabler"
/>
</a> </a>
</li> </li>
<li className="list-inline-item"> <li className="list-inline-item">

View File

@@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import { Navigation } from "components"; import { Navigation } from "components";
import { intl } from "locale";
import { import {
Book, Book,
DeviceDesktop, DeviceDesktop,
@@ -18,37 +19,58 @@ function NavMenu() {
className="mb-3" className="mb-3"
items={[ items={[
{ {
title: "Home", title: intl.formatMessage({
id: "dashboard.title",
defaultMessage: "Dashboard",
}),
icon: <Home />, icon: <Home />,
to: "/", to: "/",
}, },
{ {
title: "Hosts", title: intl.formatMessage({
id: "hosts.title",
defaultMessage: "Hosts",
}),
icon: <DeviceDesktop />, icon: <DeviceDesktop />,
to: "/hosts", to: "/hosts",
}, },
{ {
title: "Access Lists", title: intl.formatMessage({
id: "accesslists.title",
defaultMessage: "Access Lists",
}),
icon: <Lock />, icon: <Lock />,
to: "/access-lists", to: "/access-lists",
}, },
{ {
title: "Certificates", title: intl.formatMessage({
id: "certificates.title",
defaultMessage: "Certificates",
}),
icon: <Shield />, icon: <Shield />,
to: "/certificates", to: "/certificates",
}, },
{ {
title: "Users", title: intl.formatMessage({
id: "users.title",
defaultMessage: "Users",
}),
icon: <Users />, icon: <Users />,
to: "/users", to: "/users",
}, },
{ {
title: "Audit Log", title: intl.formatMessage({
id: "auditlog.title",
defaultMessage: "Audit Log",
}),
icon: <Book />, icon: <Book />,
to: "/audit-log", to: "/audit-log",
}, },
{ {
title: "Settings", title: intl.formatMessage({
id: "settings.title",
defaultMessage: "Settings",
}),
icon: <Settings />, icon: <Settings />,
to: "/settings", to: "/settings",
}, },

View File

@@ -3,6 +3,8 @@ import React, { ReactNode } from "react";
import { Footer } from "components"; import { Footer } from "components";
import { Avatar, Dropdown, Navigation } from "components"; import { Avatar, Dropdown, Navigation } from "components";
import { useAuthState, useUserState } from "context"; import { useAuthState, useUserState } from "context";
import { intl } from "locale";
import { FormattedMessage } from "react-intl";
import styled from "styled-components"; import styled from "styled-components";
import { NavMenu } from "./NavMenu"; import { NavMenu } from "./NavMenu";
@@ -33,13 +35,26 @@ function SiteWrapper({ children }: Props) {
avatar={<Avatar size="sm" url={user.gravatarUrl} />} avatar={<Avatar size="sm" url={user.gravatarUrl} />}
profileName={user.nickname} profileName={user.nickname}
profileSubName={ profileSubName={
user.roles.includes("admin") ? "Administrator" : "Standard User" user.roles.includes("admin")
? intl.formatMessage({
id: "users.admin",
defaultMessage: "Administrator",
})
: intl.formatMessage({
id: "users.standard",
defaultMessage: "Standard User",
})
} }
profileItems={[ profileItems={[
<Dropdown.Item key="m1-2">Profile settings</Dropdown.Item>, <Dropdown.Item key="m1-2">
<FormattedMessage
id="profile.title"
defaultMessage="Profile settings"
/>
</Dropdown.Item>,
<Dropdown.Item divider key="m1-4" />, <Dropdown.Item divider key="m1-4" />,
<Dropdown.Item key="m1-6" onClick={logout}> <Dropdown.Item key="m1-6" onClick={logout}>
Logout <FormattedMessage id="profile.logout" defaultMessage="Logout" />
</Dropdown.Item>, </Dropdown.Item>,
]} ]}
/> />

View File

@@ -29,10 +29,6 @@ export interface TablePagination {
} }
export interface TableProps { export interface TableProps {
/**
*
*/
title?: string;
/** /**
* Columns * Columns
*/ */
@@ -50,13 +46,7 @@ export interface TableProps {
*/ */
sortBy?: string; sortBy?: string;
} }
export const Table = ({ export const Table = ({ columns, data, pagination, sortBy }: TableProps) => {
title,
columns,
data,
pagination,
sortBy,
}: TableProps) => {
const getFormatter = (given: any) => { const getFormatter = (given: any) => {
if (typeof given === "string") { if (typeof given === "string") {
switch (given) { switch (given) {
@@ -177,11 +167,6 @@ export const Table = ({
return ( return (
<> <>
{title ? (
<div className="card-header">
<h3 className="card-title">{title}</h3>
</div>
) : null}
<div className="table-responsive"> <div className="table-responsive">
<table className="table card-table table-vcenter text-nowrap datatable"> <table className="table card-table table-vcenter text-nowrap datatable">
<thead> <thead>

View File

@@ -2,15 +2,6 @@ import { createIntl, createIntlCache } from "react-intl";
import langEn from "./lang/en.json"; import langEn from "./lang/en.json";
// todo
/*
const messages: Record<string, Record<string, string>> = {
"en-US": { selectalanguage: "Select a language" },
"pt-BR": { selectalanguage: "Selecione uma linguagem" },
};
*/
// end todo
const loadMessages = (locale: string) => { const loadMessages = (locale: string) => {
switch (locale) { switch (locale) {
/* /*
@@ -27,11 +18,8 @@ export const cache = createIntlCache();
const initialMessages = loadMessages(initialLocale); const initialMessages = loadMessages(initialLocale);
console.log("MESSAGES:", initialMessages);
export const intl = createIntl( export const intl = createIntl(
// @ts-ignore messages file typings are correct // @ts-ignore messages file typings are correct
{ locale: initialLocale, messages: initialMessages }, { locale: initialLocale, messages: initialMessages },
cache, cache,
); );
export const fmt = intl.formatMessage;

View File

@@ -1,20 +1,80 @@
{ {
"setup.create": { "accesslists.title": {
"defaultMessage": "Create Account" "defaultMessage": "Access Lists"
}, },
"setup.title": { "auditlog.title": {
"defaultMessage": "Create your first Account" "defaultMessage": "Audit Log"
}, },
"user.email": { "certificates.title": {
"defaultMessage": "Email" "defaultMessage": "Certificates"
}, },
"user.name": { "column.description": {
"defaultMessage": "Name" "defaultMessage": "Description"
}, },
"user.nickname": { "column.id": {
"defaultMessage": "Nickname" "defaultMessage": "ID"
}, },
"user.password": { "column.name": {
"defaultMessage": "Password" "defaultMessage": "Name"
} },
"dashboard.title": {
"defaultMessage": "Dashboard"
},
"footer.changelog": {
"defaultMessage": "Change Log"
},
"footer.copyright": {
"defaultMessage": "Copyright © {year} jc21.com."
},
"footer.github": {
"defaultMessage": "Github"
},
"footer.theme": {
"defaultMessage": "Theme by Tabler"
},
"footer.userguide": {
"defaultMessage": "User Guide"
},
"hosts.title": {
"defaultMessage": "Hosts"
},
"login.login": {
"defaultMessage": "Sign in"
},
"profile.logout": {
"defaultMessage": "Logout"
},
"profile.title": {
"defaultMessage": "Profile settings"
},
"settings.title": {
"defaultMessage": "Settings"
},
"setup.create": {
"defaultMessage": "Create Account"
},
"setup.title": {
"defaultMessage": "Create your first Account"
},
"user.email": {
"defaultMessage": "Email"
},
"user.name": {
"defaultMessage": "Name"
},
"user.nickname": {
"defaultMessage": "Nickname"
},
"user.password": {
"defaultMessage": "Password"
},
"users.admin": {
"defaultMessage": "Administrator"
},
"users.standard": {
"defaultMessage": "Standard User"
},
"users.title": {
"defaultMessage": "Users"
}
} }

View File

@@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl";
import styled from "styled-components"; import styled from "styled-components";
const Root = styled.div` const Root = styled.div`
@@ -8,7 +9,21 @@ const Root = styled.div`
`; `;
function AccessLists() { function AccessLists() {
return <Root>AccessLists</Root>; return (
<Root>
<div className="card">
<div className="card-status-top bg-cyan" />
<div className="card-header">
<h3 className="card-title">
<FormattedMessage
id="accesslists.title"
defaultMessage="Access Lists"
/>
</h3>
</div>
</div>
</Root>
);
} }
export default AccessLists; export default AccessLists;

View File

@@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl";
import styled from "styled-components"; import styled from "styled-components";
const Root = styled.div` const Root = styled.div`
@@ -8,7 +9,18 @@ const Root = styled.div`
`; `;
function AuditLog() { function AuditLog() {
return <Root>AuditLog</Root>; return (
<Root>
<div className="card">
<div className="card-status-top bg-cyan" />
<div className="card-header">
<h3 className="card-title">
<FormattedMessage id="auditlog.title" defaultMessage="Audit Log" />
</h3>
</div>
</div>
</Root>
);
} }
export default AuditLog; export default AuditLog;

View File

@@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl";
import styled from "styled-components"; import styled from "styled-components";
const Root = styled.div` const Root = styled.div`
@@ -8,7 +9,21 @@ const Root = styled.div`
`; `;
function Certificates() { function Certificates() {
return <Root>Certificates</Root>; return (
<Root>
<div className="card">
<div className="card-status-top bg-cyan" />
<div className="card-header">
<h3 className="card-title">
<FormattedMessage
id="certificates.title"
defaultMessage="Certificates"
/>
</h3>
</div>
</div>
</Root>
);
} }
export default Certificates; export default Certificates;

View File

@@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl";
import styled from "styled-components"; import styled from "styled-components";
const Root = styled.div` const Root = styled.div`
@@ -8,7 +9,18 @@ const Root = styled.div`
`; `;
function Dashboard() { function Dashboard() {
return <Root>Dashboard</Root>; return (
<Root>
<div className="card">
<div className="card-status-top bg-cyan" />
<div className="card-header">
<h3 className="card-title">
<FormattedMessage id="dashboard.title" defaultMessage="Dashboard" />
</h3>
</div>
</div>
</Root>
);
} }
export default Dashboard; export default Dashboard;

View File

@@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl";
import styled from "styled-components"; import styled from "styled-components";
const Root = styled.div` const Root = styled.div`
@@ -8,7 +9,18 @@ const Root = styled.div`
`; `;
function Hosts() { function Hosts() {
return <Root>Hosts</Root>; return (
<Root>
<div className="card">
<div className="card-status-top bg-cyan" />
<div className="card-header">
<h3 className="card-title">
<FormattedMessage id="hosts.title" defaultMessage="Hosts" />
</h3>
</div>
</div>
</Root>
);
} }
export default Hosts; export default Hosts;

View File

@@ -2,6 +2,8 @@ import React, { useEffect, useRef, useState, ChangeEvent } from "react";
import { Alert, Button } from "components"; import { Alert, Button } from "components";
import { useAuthState } from "context"; import { useAuthState } from "context";
import { intl } from "locale";
import { FormattedMessage } from "react-intl";
import logo from "../../img/logo-text-vertical-grey.png"; import logo from "../../img/logo-text-vertical-grey.png";
@@ -50,7 +52,9 @@ function Login() {
<div className="card-body"> <div className="card-body">
{errorMessage ? <Alert type="danger">{errorMessage}</Alert> : null} {errorMessage ? <Alert type="danger">{errorMessage}</Alert> : null}
<div className="mb-3"> <div className="mb-3">
<label className="form-label">Email address</label> <label className="form-label">
<FormattedMessage id="user.email" defaultMessage="Email" />
</label>
<input <input
ref={emailRef} ref={emailRef}
type="email" type="email"
@@ -59,13 +63,18 @@ function Login() {
name="email" name="email"
value={formData.email} value={formData.email}
disabled={loading} disabled={loading}
placeholder="Email" placeholder={intl.formatMessage({
id: "user.email",
defaultMessage: "Email",
})}
maxLength={150} maxLength={150}
required required
/> />
</div> </div>
<div className="mb-2"> <div className="mb-2">
<label className="form-label">Password</label> <label className="form-label">
<FormattedMessage id="user.password" defaultMessage="Password" />
</label>
<div className="input-group input-group-flat"> <div className="input-group input-group-flat">
<input <input
type="password" type="password"
@@ -74,7 +83,10 @@ function Login() {
name="password" name="password"
value={formData.password} value={formData.password}
disabled={loading} disabled={loading}
placeholder="Password" placeholder={intl.formatMessage({
id: "user.password",
defaultMessage: "Password",
})}
minLength={8} minLength={8}
maxLength={100} maxLength={100}
autoComplete="off" autoComplete="off"
@@ -84,7 +96,7 @@ function Login() {
</div> </div>
<div className="form-footer"> <div className="form-footer">
<Button color="cyan" loading={loading} className="w-100"> <Button color="cyan" loading={loading} className="w-100">
Sign in <FormattedMessage id="login.login" defaultMessage="Sign in" />
</Button> </Button>
</div> </div>
</div> </div>

View File

@@ -3,6 +3,8 @@ import React, { useState, useEffect, useCallback } from "react";
import { SettingsResponse, requestSettings } from "api/npm"; import { SettingsResponse, requestSettings } from "api/npm";
import { Table } from "components"; import { Table } from "components";
import { SuspenseLoader } from "components"; import { SuspenseLoader } from "components";
import { intl } from "locale";
import { FormattedMessage } from "react-intl";
import { useInterval } from "rooks"; import { useInterval } from "rooks";
import styled from "styled-components"; import styled from "styled-components";
@@ -33,13 +35,20 @@ function Settings() {
const cols = [ const cols = [
{ {
name: "id", name: "id",
title: "ID", title: intl.formatMessage({ id: "column.id", defaultMessage: "ID" }),
formatter: "id", formatter: "id",
className: "w-1", className: "w-1",
}, },
{ {
name: "name", name: "name",
title: "Name", title: intl.formatMessage({ id: "column.name", defaultMessage: "Name" }),
},
{
name: "description",
title: intl.formatMessage({
id: "column.description",
defaultMessage: "Description",
}),
}, },
]; ];
@@ -48,8 +57,12 @@ function Settings() {
<Root> <Root>
<div className="card"> <div className="card">
<div className="card-status-top bg-cyan" /> <div className="card-status-top bg-cyan" />
<div className="card-header">
<h3 className="card-title">
<FormattedMessage id="settings.title" defaultMessage="Settings" />
</h3>
</div>
<Table <Table
title="Settings"
columns={cols} columns={cols}
data={data.items} data={data.items}
sortBy={data.sort[0].field} sortBy={data.sort[0].field}

View File

@@ -3,7 +3,7 @@ import React, { useEffect, useRef, useState, ChangeEvent } from "react";
import { createUser } from "api/npm"; import { createUser } from "api/npm";
import { Alert, Button } from "components"; import { Alert, Button } from "components";
import { useAuthState, useHealthState } from "context"; import { useAuthState, useHealthState } from "context";
import { fmt } from "locale"; import { intl } from "locale";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import logo from "../../img/logo-text-vertical-grey.png"; import logo from "../../img/logo-text-vertical-grey.png";
@@ -105,7 +105,10 @@ function Setup() {
name="name" name="name"
value={formData.name} value={formData.name}
disabled={loading} disabled={loading}
placeholder={fmt({ id: "user.name", defaultMessage: "Name" })} placeholder={intl.formatMessage({
id: "user.name",
defaultMessage: "Name",
})}
required required
/> />
</div> </div>
@@ -122,7 +125,7 @@ function Setup() {
name="nickname" name="nickname"
value={formData.nickname} value={formData.nickname}
disabled={loading} disabled={loading}
placeholder={fmt({ placeholder={intl.formatMessage({
id: "user.nickname", id: "user.nickname",
defaultMessage: "Nickname", defaultMessage: "Nickname",
})} })}
@@ -140,7 +143,7 @@ function Setup() {
name="email" name="email"
value={formData.email} value={formData.email}
disabled={loading} disabled={loading}
placeholder={fmt({ placeholder={intl.formatMessage({
id: "user.email", id: "user.email",
defaultMessage: "Email", defaultMessage: "Email",
})} })}
@@ -162,7 +165,7 @@ function Setup() {
name="password" name="password"
value={formData.password} value={formData.password}
disabled={loading} disabled={loading}
placeholder={fmt({ placeholder={intl.formatMessage({
id: "user.password", id: "user.password",
defaultMessage: "Password", defaultMessage: "Password",
})} })}

View File

@@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl";
import styled from "styled-components"; import styled from "styled-components";
const Root = styled.div` const Root = styled.div`
@@ -8,7 +9,18 @@ const Root = styled.div`
`; `;
function Users() { function Users() {
return <Root>Users</Root>; return (
<Root>
<div className="card">
<div className="card-status-top bg-cyan" />
<div className="card-header">
<h3 className="card-title">
<FormattedMessage id="users.title" defaultMessage="Users" />
</h3>
</div>
</div>
</Root>
);
} }
export default Users; export default Users;