mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-08-27 19:20:04 +00:00
Added more languages and picker
This commit is contained in:
@@ -1,18 +1,20 @@
|
||||
import React from "react";
|
||||
|
||||
import Router from "components/Router";
|
||||
import { AuthProvider, HealthProvider } from "context";
|
||||
import { AuthProvider, HealthProvider, LocaleProvider } from "context";
|
||||
import { intl } from "locale";
|
||||
import { RawIntlProvider } from "react-intl";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<RawIntlProvider value={intl}>
|
||||
<HealthProvider>
|
||||
<AuthProvider>
|
||||
<Router />
|
||||
</AuthProvider>
|
||||
</HealthProvider>
|
||||
<LocaleProvider>
|
||||
<HealthProvider>
|
||||
<AuthProvider>
|
||||
<Router />
|
||||
</AuthProvider>
|
||||
</HealthProvider>
|
||||
</LocaleProvider>
|
||||
</RawIntlProvider>
|
||||
);
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@ export const DropdownItem: React.FC<DropdownItemProps> = ({
|
||||
icon,
|
||||
href,
|
||||
onClick,
|
||||
...rest
|
||||
}) => {
|
||||
return divider ? (
|
||||
<div className={cn("dropdown-divider", className)} />
|
||||
@@ -57,7 +58,8 @@ export const DropdownItem: React.FC<DropdownItemProps> = ({
|
||||
className,
|
||||
)}
|
||||
href={href}
|
||||
onClick={onClick}>
|
||||
onClick={onClick}
|
||||
{...rest}>
|
||||
{icon && <span className="dropdown-item-icon">{icon}</span>}
|
||||
{children}
|
||||
</a>
|
||||
|
28
frontend/src/components/Flag/Flag.tsx
Normal file
28
frontend/src/components/Flag/Flag.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from "react";
|
||||
|
||||
import cn from "classnames";
|
||||
|
||||
export interface FlagProps {
|
||||
/**
|
||||
* Additional Class
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Country code of flag
|
||||
*/
|
||||
country: string;
|
||||
/**
|
||||
* Size of the flag
|
||||
*/
|
||||
size?: string;
|
||||
}
|
||||
export const Flag: React.FC<FlagProps> = ({ className, country, size }) => {
|
||||
const classes = [
|
||||
`flag-country-${country.toLowerCase()}`,
|
||||
{
|
||||
[`flag-${size}`]: !!size,
|
||||
},
|
||||
];
|
||||
|
||||
return <span className={cn("flag", classes, className)} />;
|
||||
};
|
1
frontend/src/components/Flag/index.ts
Normal file
1
frontend/src/components/Flag/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./Flag";
|
67
frontend/src/components/LocalePicker.tsx
Normal file
67
frontend/src/components/LocalePicker.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { Button, Dropdown, Flag } from "components";
|
||||
import { useLocaleState } from "context";
|
||||
import { changeLocale, getFlagCodeForLocale, getLocale, intl } from "locale";
|
||||
|
||||
export interface LocalPickerProps {
|
||||
/**
|
||||
* On click handler
|
||||
*/
|
||||
onChange?: any;
|
||||
}
|
||||
|
||||
export const LocalePicker: React.FC<LocalPickerProps> = ({
|
||||
onChange,
|
||||
...rest
|
||||
}) => {
|
||||
const { locale, setLocale } = useLocaleState();
|
||||
|
||||
// const [locale, setLocale] = useState(getLocale());
|
||||
const [localeShown, setLocaleShown] = useState(false);
|
||||
|
||||
const handleOnChange = (e: any) => {
|
||||
changeLocale(e.currentTarget.rel);
|
||||
setLocale(e.currentTarget.rel);
|
||||
setLocaleShown(false);
|
||||
onChange && onChange(locale);
|
||||
};
|
||||
|
||||
const options = [
|
||||
["us", "en-US"],
|
||||
["de", "de-DE"],
|
||||
["ir", "fa-IR"],
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="dropdown" {...rest}>
|
||||
<Button
|
||||
shape="ghost"
|
||||
onClick={(e: any) => {
|
||||
setLocaleShown(!localeShown);
|
||||
e.preventDefault();
|
||||
}}
|
||||
iconOnly>
|
||||
<Flag country={getFlagCodeForLocale(locale)} />
|
||||
</Button>
|
||||
<Dropdown
|
||||
className="dropdown-menu-end dropdown-menu-card"
|
||||
show={localeShown}>
|
||||
{options.map((item) => {
|
||||
return (
|
||||
<Dropdown.Item
|
||||
key={`locale-${item[0]}`}
|
||||
rel={item[1]}
|
||||
icon={<Flag country={item[0]} />}
|
||||
onClick={handleOnChange}>
|
||||
{intl.formatMessage({
|
||||
id: `locale-${item[1]}`,
|
||||
defaultMessage: item[1],
|
||||
})}
|
||||
</Dropdown.Item>
|
||||
);
|
||||
})}
|
||||
</Dropdown>
|
||||
</div>
|
||||
);
|
||||
};
|
@@ -2,9 +2,9 @@ import React, { ReactNode } from "react";
|
||||
|
||||
import { Footer } from "components";
|
||||
import { Avatar, Dropdown, Navigation } from "components";
|
||||
import { LocalePicker } from "components";
|
||||
import { useAuthState, useUserState } from "context";
|
||||
import { intl } from "locale";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { NavMenu } from "./NavMenu";
|
||||
@@ -45,16 +45,20 @@ function SiteWrapper({ children }: Props) {
|
||||
defaultMessage: "Standard User",
|
||||
})
|
||||
}
|
||||
buttons={[<LocalePicker key="lp1" />]}
|
||||
profileItems={[
|
||||
<Dropdown.Item key="m1-2">
|
||||
<FormattedMessage
|
||||
id="profile.title"
|
||||
defaultMessage="Profile settings"
|
||||
/>
|
||||
{intl.formatMessage({
|
||||
id: "profile.title",
|
||||
defaultMessage: "Profile settings",
|
||||
})}
|
||||
</Dropdown.Item>,
|
||||
<Dropdown.Item divider key="m1-4" />,
|
||||
<Dropdown.Item key="m1-6" onClick={logout}>
|
||||
<FormattedMessage id="profile.logout" defaultMessage="Logout" />
|
||||
{intl.formatMessage({
|
||||
id: "profile.logout",
|
||||
defaultMessage: "Logout",
|
||||
})}
|
||||
</Dropdown.Item>,
|
||||
]}
|
||||
/>
|
||||
|
@@ -5,9 +5,11 @@ export * from "./Badge";
|
||||
export * from "./Button";
|
||||
export * from "./ButtonList";
|
||||
export * from "./Dropdown";
|
||||
export * from "./Flag";
|
||||
export * from "./Footer";
|
||||
export * from "./Loader";
|
||||
export * from "./Loading";
|
||||
export * from "./LocalePicker";
|
||||
export * from "./Navigation";
|
||||
export * from "./NavMenu";
|
||||
export * from "./Router";
|
||||
|
43
frontend/src/context/LocaleContext.tsx
Normal file
43
frontend/src/context/LocaleContext.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import React, { ReactNode, useState } from "react";
|
||||
|
||||
import { getLocale } from "locale";
|
||||
|
||||
// Context
|
||||
export interface LocaleContextType {
|
||||
setLocale: (locale: string) => void;
|
||||
locale?: string;
|
||||
}
|
||||
|
||||
const initalValue = null;
|
||||
const LocaleContext = React.createContext<LocaleContextType | null>(
|
||||
initalValue,
|
||||
);
|
||||
|
||||
// Provider
|
||||
interface Props {
|
||||
children?: ReactNode;
|
||||
}
|
||||
function LocaleProvider({ children }: Props) {
|
||||
const [locale, setLocaleValue] = useState(getLocale());
|
||||
|
||||
const setLocale = async (locale: string) => {
|
||||
setLocaleValue(locale);
|
||||
};
|
||||
|
||||
const value = { locale, setLocale };
|
||||
|
||||
return (
|
||||
<LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function useLocaleState() {
|
||||
const context = React.useContext(LocaleContext);
|
||||
if (!context) {
|
||||
throw new Error(`useLocaleState must be used within a LocaleProvider`);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
export { LocaleProvider, useLocaleState };
|
||||
export default LocaleContext;
|
@@ -1,3 +1,4 @@
|
||||
export * from "./AuthContext";
|
||||
export * from "./HealthContext";
|
||||
export * from "./LocaleContext";
|
||||
export * from "./UserContext";
|
||||
|
@@ -1,25 +1,53 @@
|
||||
import { createIntl, createIntlCache } from "react-intl";
|
||||
|
||||
import langDe from "./lang/de.json";
|
||||
import langEn from "./lang/en.json";
|
||||
import langFa from "./lang/fa.json";
|
||||
|
||||
const loadMessages = (locale: string) => {
|
||||
switch (locale) {
|
||||
/*
|
||||
case 'fr':
|
||||
return import("./lang/fr.json");
|
||||
*/
|
||||
const loadMessages = (locale?: string) => {
|
||||
locale = locale || "en";
|
||||
switch (locale.substr(0, 2)) {
|
||||
case "de":
|
||||
return Object.assign({}, langEn, langDe);
|
||||
case "fa":
|
||||
return Object.assign({}, langEn, langFa);
|
||||
default:
|
||||
return langEn;
|
||||
}
|
||||
};
|
||||
|
||||
export const initialLocale = "en-US";
|
||||
export const cache = createIntlCache();
|
||||
export const getFlagCodeForLocale = (locale?: string) => {
|
||||
switch (locale) {
|
||||
case "de-DE":
|
||||
case "de":
|
||||
return "de";
|
||||
case "fa-IR":
|
||||
case "fa":
|
||||
return "ir";
|
||||
default:
|
||||
return "us";
|
||||
}
|
||||
};
|
||||
|
||||
const initialMessages = loadMessages(initialLocale);
|
||||
export const getLocale = () => {
|
||||
let loc = window.localStorage.getItem("locale");
|
||||
if (!loc) {
|
||||
loc = document.documentElement.lang;
|
||||
}
|
||||
return loc;
|
||||
};
|
||||
|
||||
export const intl = createIntl(
|
||||
// @ts-ignore messages file typings are correct
|
||||
{ locale: initialLocale, messages: initialMessages },
|
||||
const cache = createIntlCache();
|
||||
|
||||
const initialMessages = loadMessages(getLocale());
|
||||
export let intl = createIntl(
|
||||
{ locale: getLocale(), messages: initialMessages },
|
||||
cache,
|
||||
);
|
||||
|
||||
export const changeLocale = (locale: string): void => {
|
||||
const messages = loadMessages(locale);
|
||||
intl = createIntl({ locale, messages }, cache);
|
||||
window.localStorage.setItem("locale", locale);
|
||||
document.documentElement.lang = locale;
|
||||
};
|
||||
|
20
frontend/src/locale/src/de.json
Normal file
20
frontend/src/locale/src/de.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"accesslists.title": {
|
||||
"defaultMessage": "Zugriffslisten"
|
||||
},
|
||||
"auditlog.title": {
|
||||
"defaultMessage": "Audit-Log"
|
||||
},
|
||||
"setup.create": {
|
||||
"defaultMessage": "Benutzerkonto erstellen"
|
||||
},
|
||||
"setup.title": {
|
||||
"defaultMessage": "Erstellen Sie Ihr erstes Konto"
|
||||
},
|
||||
"user.nickname": {
|
||||
"defaultMessage": "Spitzname"
|
||||
},
|
||||
"user.password": {
|
||||
"defaultMessage": "Passwort"
|
||||
}
|
||||
}
|
@@ -1,80 +1,89 @@
|
||||
{
|
||||
"accesslists.title": {
|
||||
"defaultMessage": "Access Lists"
|
||||
},
|
||||
"auditlog.title": {
|
||||
"defaultMessage": "Audit Log"
|
||||
},
|
||||
"certificates.title": {
|
||||
"defaultMessage": "Certificates"
|
||||
},
|
||||
"column.description": {
|
||||
"defaultMessage": "Description"
|
||||
},
|
||||
"column.id": {
|
||||
"defaultMessage": "ID"
|
||||
},
|
||||
"column.name": {
|
||||
"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"
|
||||
}
|
||||
"accesslists.title": {
|
||||
"defaultMessage": "Access Lists"
|
||||
},
|
||||
"auditlog.title": {
|
||||
"defaultMessage": "Audit Log"
|
||||
},
|
||||
"certificates.title": {
|
||||
"defaultMessage": "Certificates"
|
||||
},
|
||||
"column.description": {
|
||||
"defaultMessage": "Description"
|
||||
},
|
||||
"column.id": {
|
||||
"defaultMessage": "ID"
|
||||
},
|
||||
"column.name": {
|
||||
"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"
|
||||
},
|
||||
"locale-de-DE": {
|
||||
"defaultMessage": "Deutsche"
|
||||
},
|
||||
"locale-en-US": {
|
||||
"defaultMessage": "English"
|
||||
},
|
||||
"locale-fa-IR": {
|
||||
"defaultMessage": "Persian"
|
||||
},
|
||||
"login.login": {
|
||||
"defaultMessage": "Sign in"
|
||||
},
|
||||
"profile.logout": {
|
||||
"defaultMessage": "Logout"
|
||||
},
|
||||
"profile.title": {
|
||||
"defaultMessage": "Profile settings"
|
||||
},
|
||||
"settings.title": {
|
||||
"defaultMessage": "Settings"
|
||||
},
|
||||
"setup.create": {
|
||||
"defaultMessage": "Sign up"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
77
frontend/src/locale/src/fa.json
Normal file
77
frontend/src/locale/src/fa.json
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"accesslists.title": {
|
||||
"defaultMessage": "دسترسی به لیست ها"
|
||||
},
|
||||
"auditlog.title": {
|
||||
"defaultMessage": "گزارش حسابرسی"
|
||||
},
|
||||
"certificates.title": {
|
||||
"defaultMessage": "گواهینامه ها"
|
||||
},
|
||||
"column.description": {
|
||||
"defaultMessage": "شرح"
|
||||
},
|
||||
"column.id": {
|
||||
"defaultMessage": "شناسه"
|
||||
},
|
||||
"column.name": {
|
||||
"defaultMessage": "نام"
|
||||
},
|
||||
"dashboard.title": {
|
||||
"defaultMessage": "داشبورد"
|
||||
},
|
||||
"footer.changelog": {
|
||||
"defaultMessage": "ورود به سیستم را تغییر دهید"
|
||||
},
|
||||
"footer.copyright": {
|
||||
"defaultMessage": "حق چاپ © حق چاپ © {year} jc21.com"
|
||||
},
|
||||
"footer.theme": {
|
||||
"defaultMessage": "قالب توسط Tabler"
|
||||
},
|
||||
"footer.userguide": {
|
||||
"defaultMessage": "راهنمای کاربر"
|
||||
},
|
||||
"hosts.title": {
|
||||
"defaultMessage": "میزبان"
|
||||
},
|
||||
"login.login": {
|
||||
"defaultMessage": "ورود"
|
||||
},
|
||||
"profile.logout": {
|
||||
"defaultMessage": "خروج"
|
||||
},
|
||||
"profile.title": {
|
||||
"defaultMessage": "تنظیمات نمایه"
|
||||
},
|
||||
"settings.title": {
|
||||
"defaultMessage": "تنظیمات"
|
||||
},
|
||||
"setup.create": {
|
||||
"defaultMessage": "ثبت نام"
|
||||
},
|
||||
"setup.title": {
|
||||
"defaultMessage": "اولین حساب خود را ایجاد کنید"
|
||||
},
|
||||
"user.email": {
|
||||
"defaultMessage": "پست الکترونیک"
|
||||
},
|
||||
"user.name": {
|
||||
"defaultMessage": "نام"
|
||||
},
|
||||
"user.nickname": {
|
||||
"defaultMessage": "کنیه"
|
||||
},
|
||||
"user.password": {
|
||||
"defaultMessage": "کلمه عبور"
|
||||
},
|
||||
"users.admin": {
|
||||
"defaultMessage": "مدیر"
|
||||
},
|
||||
"users.standard": {
|
||||
"defaultMessage": "کاربر استاندارد"
|
||||
},
|
||||
"users.title": {
|
||||
"defaultMessage": "کاربران"
|
||||
}
|
||||
}
|
@@ -2,9 +2,9 @@ import React, { useEffect, useRef, useState, ChangeEvent } from "react";
|
||||
|
||||
import { createUser } from "api/npm";
|
||||
import { Alert, Button } from "components";
|
||||
import { LocalePicker } from "components";
|
||||
import { useAuthState, useHealthState } from "context";
|
||||
import { intl } from "locale";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import logo from "../../img/logo-text-vertical-grey.png";
|
||||
|
||||
@@ -13,6 +13,7 @@ function Setup() {
|
||||
const { refreshHealth } = useHealthState();
|
||||
const { login } = useAuthState();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [renderCount, setRenderCount] = useState(0);
|
||||
const [errorMessage, setErrorMessage] = useState("");
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
@@ -82,12 +83,24 @@ function Setup() {
|
||||
autoComplete="off"
|
||||
onSubmit={onSubmit}>
|
||||
<div className="card-body">
|
||||
<h2 className="card-title text-center mb-4">
|
||||
<FormattedMessage
|
||||
id="setup.title"
|
||||
defaultMessage="Create your first Account"
|
||||
/>
|
||||
</h2>
|
||||
<div className="row mb-4">
|
||||
<div className="col">
|
||||
<h2 className="card-title">
|
||||
{intl.formatMessage({
|
||||
id: "setup.title",
|
||||
defaultMessage: "Create your first Account",
|
||||
})}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="col col-md-2">
|
||||
<LocalePicker
|
||||
onChange={() => {
|
||||
setRenderCount(renderCount + 1);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{errorMessage ? (
|
||||
<Alert type="danger" className="text-center">
|
||||
{errorMessage}
|
||||
@@ -96,7 +109,10 @@ function Setup() {
|
||||
|
||||
<div className="mb-3">
|
||||
<label className="form-label">
|
||||
<FormattedMessage id="user.name" defaultMessage="Name" />
|
||||
{intl.formatMessage({
|
||||
id: "user.name",
|
||||
defaultMessage: "Name",
|
||||
})}
|
||||
</label>
|
||||
<input
|
||||
ref={nameRef}
|
||||
@@ -114,10 +130,10 @@ function Setup() {
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">
|
||||
<FormattedMessage
|
||||
id="user.nickname"
|
||||
defaultMessage="Nickname"
|
||||
/>
|
||||
{intl.formatMessage({
|
||||
id: "user.nickname",
|
||||
defaultMessage: "Nickname",
|
||||
})}
|
||||
</label>
|
||||
<input
|
||||
onChange={onChange}
|
||||
@@ -134,7 +150,10 @@ function Setup() {
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">
|
||||
<FormattedMessage id="user.email" defaultMessage="Email" />
|
||||
{intl.formatMessage({
|
||||
id: "user.email",
|
||||
defaultMessage: "Email",
|
||||
})}
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
@@ -153,10 +172,10 @@ function Setup() {
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">
|
||||
<FormattedMessage
|
||||
id="user.password"
|
||||
defaultMessage="Password"
|
||||
/>
|
||||
{intl.formatMessage({
|
||||
id: "user.password",
|
||||
defaultMessage: "Password",
|
||||
})}
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
@@ -177,10 +196,10 @@ function Setup() {
|
||||
</div>
|
||||
<div className="form-footer">
|
||||
<Button color="cyan" loading={loading} className="w-100">
|
||||
<FormattedMessage
|
||||
id="setup.create"
|
||||
defaultMessage="Create Account"
|
||||
/>
|
||||
{intl.formatMessage({
|
||||
id: "setup.create",
|
||||
defaultMessage: "Create Account",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user