Add formatjs/intl locale support

This commit is contained in:
Jamie Curnow
2021-07-26 12:04:48 +10:00
parent bc2bd67cda
commit 7530fc7602
9 changed files with 185 additions and 68 deletions

View File

@@ -39,9 +39,10 @@
"node-sass": "^5.0.0",
"prettier": "2.3.2",
"query-string": "7.0.1",
"react": "17.0.2",
"react": "^17.0.2",
"react-async": "10.0.1",
"react-dom": "17.0.2",
"react-intl": "^5.20.6",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"rooks": "5.0.2",
@@ -60,7 +61,9 @@
"eject": "react-scripts eject",
"prettier": "prettier \"**/*.+(js|json|yml|css|ts|tsx)\"",
"format": "yarn prettier -- --write",
"lint:fix": "eslint --fix --ext .ts --ext .tsx ."
"lint:fix": "eslint --fix --ext .ts --ext .tsx .",
"locale-extract": "formatjs extract 'src/**/*.tsx' --out-file src/locale/src/en.json",
"locale-compile": "formatjs compile-folder src/locale/src src/locale/lang --ast"
},
"browserslist": {
"production": [
@@ -88,5 +91,8 @@
"statements": 0
}
}
},
"devDependencies": {
"@formatjs/cli": "^4.2.29"
}
}

View File

@@ -2,14 +2,18 @@ import React from "react";
import Router from "components/Router";
import { AuthProvider, HealthProvider } from "context";
import { intl } from "locale";
import { RawIntlProvider } from "react-intl";
function App() {
return (
<HealthProvider>
<AuthProvider>
<Router />
</AuthProvider>
</HealthProvider>
<RawIntlProvider value={intl}>
<HealthProvider>
<AuthProvider>
<Router />
</AuthProvider>
</HealthProvider>
</RawIntlProvider>
);
}

View File

@@ -0,0 +1,37 @@
import { createIntl, createIntlCache } from "react-intl";
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) => {
switch (locale) {
/*
case 'fr':
return import("./lang/fr.json");
*/
default:
return langEn;
}
};
export const initialLocale = "en-US";
export const cache = createIntlCache();
const initialMessages = loadMessages(initialLocale);
console.log("MESSAGES:", initialMessages);
export const intl = createIntl(
// @ts-ignore messages file typings are correct
{ locale: initialLocale, messages: initialMessages },
cache,
);
export const fmt = intl.formatMessage;

View File

@@ -0,0 +1 @@
export * from "./IntlProvider";

View File

@@ -0,0 +1,20 @@
{
"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"
}
}

View File

@@ -3,6 +3,8 @@ import React, { useEffect, useRef, useState, ChangeEvent } from "react";
import { createUser } from "api/npm";
import { Alert, Button } from "components";
import { useAuthState, useHealthState } from "context";
import { fmt } from "locale";
import { FormattedMessage } from "react-intl";
import logo from "../../img/logo-text-vertical-grey.png";
@@ -81,7 +83,10 @@ function Setup() {
onSubmit={onSubmit}>
<div className="card-body">
<h2 className="card-title text-center mb-4">
Create your first Account
<FormattedMessage
id="setup.title"
defaultMessage="Create your first Account"
/>
</h2>
{errorMessage ? (
<Alert type="danger" className="text-center">
@@ -90,7 +95,9 @@ function Setup() {
) : null}
<div className="mb-3">
<label className="form-label">Name</label>
<label className="form-label">
<FormattedMessage id="user.name" defaultMessage="Name" />
</label>
<input
ref={nameRef}
onChange={onChange}
@@ -98,24 +105,34 @@ function Setup() {
name="name"
value={formData.name}
disabled={loading}
placeholder="Name"
placeholder={fmt({ id: "user.name", defaultMessage: "Name" })}
required
/>
</div>
<div className="mb-3">
<label className="form-label">Nickname</label>
<label className="form-label">
<FormattedMessage
id="user.nickname"
defaultMessage="Nickname"
/>
</label>
<input
onChange={onChange}
className="form-control"
name="nickname"
value={formData.nickname}
disabled={loading}
placeholder="Nickname"
placeholder={fmt({
id: "user.nickname",
defaultMessage: "Nickname",
})}
required
/>
</div>
<div className="mb-3">
<label className="form-label">Email</label>
<label className="form-label">
<FormattedMessage id="user.email" defaultMessage="Email" />
</label>
<input
type="email"
onChange={onChange}
@@ -123,13 +140,21 @@ function Setup() {
name="email"
value={formData.email}
disabled={loading}
placeholder="Email"
placeholder={fmt({
id: "user.email",
defaultMessage: "Email",
})}
maxLength={150}
required
/>
</div>
<div className="mb-3">
<label className="form-label">Password</label>
<label className="form-label">
<FormattedMessage
id="user.password"
defaultMessage="Password"
/>
</label>
<input
type="password"
onChange={onChange}
@@ -137,7 +162,10 @@ function Setup() {
name="password"
value={formData.password}
disabled={loading}
placeholder="Password"
placeholder={fmt({
id: "user.password",
defaultMessage: "Password",
})}
minLength={8}
maxLength={100}
autoComplete="off"
@@ -146,7 +174,10 @@ function Setup() {
</div>
<div className="form-footer">
<Button color="cyan" loading={loading} className="w-100">
Create Account
<FormattedMessage
id="setup.create"
defaultMessage="Create Account"
/>
</Button>
</div>
</div>