Added langauge localization files to use masterdata and futureproof translations.

This commit is contained in:
Patrick Fic
2019-12-31 12:57:17 -08:00
parent 14147ded53
commit 226933f2d7
11 changed files with 170 additions and 73 deletions

View File

@@ -1,59 +1,58 @@
import React from "react"; import React from "react";
import { Icon, Button, Input, AutoComplete } from "antd"; // import { Icon, Button, Input, AutoComplete } from "antd";
const { Option } = AutoComplete; // const { Option } = AutoComplete;
function onSelect(value) { // function onSelect(value) {
console.log("onSelect", value); // console.log("onSelect", value);
} // }
function getRandomInt(max, min = 0) { // function getRandomInt(max, min = 0) {
return Math.floor(Math.random() * (max - min + 1)) + min; // eslint-disable-line no-mixed-operators // return Math.floor(Math.random() * (max - min + 1)) + min; // eslint-disable-line no-mixed-operators
} // }
function searchResult(query) { // function searchResult(query) {
return new Array(getRandomInt(5)) // return new Array(getRandomInt(5))
.join(".") // .join(".")
.split(".") // .split(".")
.map((item, idx) => ({ // .map((item, idx) => ({
query, // query,
category: `${query}${idx}`, // category: `${query}${idx}`,
count: getRandomInt(200, 100) // count: getRandomInt(200, 100)
})); // }));
} // }
function renderOption(item) { // function renderOption(item) {
return ( // return (
<Option key={item.category} text={item.category}> // <Option key={item.category} text={item.category}>
<div className='global-search-item'> // <div className='global-search-item'>
<span className='global-search-item-desc'> // <span className='global-search-item-desc'>
Found {item.query} on // Found {item.query} on
<a // <a
href={`https://s.taobao.com/search?q=${item.query}`} // href={`https://s.taobao.com/search?q=${item.query}`}
target='_blank' // target='_blank'
rel='noopener noreferrer'> // rel='noopener noreferrer'>
{item.category} // {item.category}
</a> // </a>
</span> // </span>
<span className='global-search-item-count'>{item.count} results</span> // <span className='global-search-item-count'>{item.count} results</span>
</div> // </div>
</Option> // </Option>
); // );
} // }
export default class GlobalSearch extends React.Component { export default class GlobalSearch extends React.Component {
state = { state = {
dataSource: [] dataSource: []
}; };
handleSearch = value => { // handleSearch = value => {
this.setState({ // this.setState({
dataSource: value ? searchResult(value) : [] // dataSource: value ? searchResult(value) : []
}); // });
}; // };
render() { render() {
const { dataSource } = this.state;
return ( return (
<div /> <div />
// <div style={{ width: 300 }}> // <div style={{ width: 300 }}>

View File

@@ -1,27 +1,28 @@
import React from "react"; import React from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useApolloClient } from "@apollo/react-hooks";
import { Menu, Icon } from "antd"; import { Menu, Icon } from "antd";
import "./header.styles.scss"; import "./header.styles.scss";
import SignOut from "../sign-out/sign-out.component"; import SignOut from "../sign-out/sign-out.component";
import ManageSignInButton from "../manage-sign-in-button/manage-sign-in-button.component"; import ManageSignInButton from "../manage-sign-in-button/manage-sign-in-button.component";
import { useApolloClient } from "@apollo/react-hooks";
import GlobalSearch from "../global-search/global-search.component"; import GlobalSearch from "../global-search/global-search.component";
import LanguageSelector from "../language-selector/langauge-selector.component";
export default ({ landingHeader, navItems, selectedNavItem }) => { export default ({ landingHeader, navItems, selectedNavItem }) => {
const apolloClient = useApolloClient(); const apolloClient = useApolloClient();
const handleClick = e => { const handleClick = e => {
apolloClient.writeData({ data: { selectedNavItem: e.key } }); apolloClient.writeData({ data: { selectedNavItem: e.key } });
}; };
return ( return (
<Menu <Menu
theme="dark" theme='dark'
className="header" className='header'
onClick={handleClick} onClick={handleClick}
selectedKeys={selectedNavItem} selectedKeys={selectedNavItem}
mode="horizontal" mode='horizontal'>
>
<Menu.Item> <Menu.Item>
<GlobalSearch /> <GlobalSearch />
</Menu.Item> </Menu.Item>
@@ -43,6 +44,8 @@ export default ({ landingHeader, navItems, selectedNavItem }) => {
<ManageSignInButton /> <ManageSignInButton />
</Menu.Item> </Menu.Item>
)} )}
{!landingHeader ? <LanguageSelector /> : null}
</Menu> </Menu>
); );
}; };

View File

@@ -0,0 +1,29 @@
import React from "react";
import { useTranslation } from "react-i18next";
import i18next from "i18next";
import { Dropdown, Menu, Icon } from "antd";
export default function LanguageSelector() {
const { t } = useTranslation();
const handleMenuClick = e => {
console.log("e", e);
i18next.changeLanguage(e.key, (err, t) => {
if (err)
return console.log("Error encountered when changing languages.", err);
});
};
const menu = (
<Menu onClick={handleMenuClick}>
<Menu.Item key='en_us'>{t("general.languages.english")}</Menu.Item>
<Menu.Item key='fr'>{t("general.languages.french")}</Menu.Item>
<Menu.Item key='es'>{t("general.languages.spanish")}</Menu.Item>
</Menu>
);
return (
<Dropdown overlay={menu}>
<Icon type='global' />
</Dropdown>
);
}

View File

@@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Menu, Dropdown, Card, Icon, Avatar, Button } from "antd"; import { Menu, Dropdown, Card, Icon, Avatar } from "antd";
import { useTranslation } from "react-i18next";
export default function WhiteBoardCard({ metadata }) { export default function WhiteBoardCard({ metadata }) {
// const { // const {
// onClick, // onClick,
@@ -18,31 +18,33 @@ export default function WhiteBoardCard({ metadata }) {
// showDeleteButton, // showDeleteButton,
// onDelete // onDelete
// } = this.props; // } = this.props;
const { t } = useTranslation();
const menu = ( const menu = (
<Menu> <Menu>
<Menu.Item key='images'> <Menu.Item key='images'>
<Icon type='file-image' /> <Icon type='file-image' />
View Job Images {t("whiteboard.viewJobImages")}
</Menu.Item> </Menu.Item>
<Menu.Item key='printing'> <Menu.Item key='printing'>
<Icon type='printer' /> <Icon type='printer' />
Printing {t("whiteboard.printCenter")}
</Menu.Item> </Menu.Item>
<Menu.Item key='notes'> <Menu.Item key='notes'>
<Icon type='edit' /> <Icon type='edit' />
Job Notes {t("whiteboard.notes")}
</Menu.Item> </Menu.Item>
<Menu.Item key='postinvoices'> <Menu.Item key='postinvoices'>
<Icon type='shopping-cart' /> <Icon type='shopping-cart' />
Post Invoices {t("whiteboard.postInvoices")}
</Menu.Item> </Menu.Item>
<Menu.Item key='receiveparts'> <Menu.Item key='receiveparts'>
<Icon type='inbox' /> <Icon type='inbox' />
Receive Parts {t("whiteboard.receiveParts")}
</Menu.Item> </Menu.Item>
<Menu.Item key='partstatus'> <Menu.Item key='partstatus'>
<Icon type='tool' /> <Icon type='tool' />
Parts Status {t("whiteboard.partStatus")}
</Menu.Item> </Menu.Item>
</Menu> </Menu>
); );

View File

@@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom";
import "./translations/i18n";
import * as serviceWorker from "./serviceWorker"; import * as serviceWorker from "./serviceWorker";
import "./index.css"; import "./index.css";

View File

@@ -1,4 +1,4 @@
import React from "react"; import React, { useEffect } from "react";
import { useSubscription } from "@apollo/react-hooks"; import { useSubscription } from "@apollo/react-hooks";
import AlertComponent from "../../components/alert/alert.component"; import AlertComponent from "../../components/alert/alert.component";
import { Col } from "antd"; import { Col } from "antd";
@@ -10,10 +10,10 @@ export default function JobsPage() {
const { loading, error, data } = useSubscription(SUBSCRIPTION_ALL_OPEN_JOBS, { const { loading, error, data } = useSubscription(SUBSCRIPTION_ALL_OPEN_JOBS, {
fetchPolicy: "network-only" fetchPolicy: "network-only"
}); });
useEffect(() => { useEffect(() => {
document.title = "new title" document.title = "new title";
}, []); }, []);
if (error) return <AlertComponent message={error.message} />; if (error) return <AlertComponent message={error.message} />;

View File

@@ -1,6 +0,0 @@
{
"welcome": {
"title": "Welcome to {{framework}}",
"intro": "To get started, edit <1><0></0></1> and save to reload."
}
}

View File

@@ -0,0 +1,22 @@
{
"translation": {
"general": {
"languages": {
"english": "English",
"french": "French",
"spanish": "Spanish"
},
"title": "Welcome to {{framework}}",
"greetings": "Hello2!",
"intro": "To get started, edit <1><0></0></1> and save to reload."
},
"whiteboard": {
"viewJobImages": "View Job Images",
"printCenter": "Print Center",
"postInvoices": "Post Invoices",
"notes": "Job Notes",
"partStatus": "Part Status",
"receiveParts": "Receive Parts"
}
}
}

View File

@@ -1,6 +1,9 @@
{ {
"welcome": { "translation": {
"title": "Welcome to {{framework}}", "general": {
"intro": "To get started, edit <1><0></0></1> and save to reload." "title": "Hola a {{framework}}",
"greetings": "Hola!",
"intro": "To get started, edit <1><0></0></1> and save to reload."
} }
} }
}

View File

@@ -1,6 +1,22 @@
{ {
"welcome": { "translation": {
"general": {
"languages": {
"english": "Anglais",
"french": "Francais",
"spanish": "Espanol"
},
"title": "Welcome to {{framework}}", "title": "Welcome to {{framework}}",
"greetings": "Hello2!",
"intro": "To get started, edit <1><0></0></1> and save to reload." "intro": "To get started, edit <1><0></0></1> and save to reload."
},
"whiteboard": {
"viewJobImages": "Viewez le Job Images",
"printCenter": "Printez Centre",
"postInvoices": "Postez le Invoices",
"notes": "Le Job Notes",
"partStatus": "Status de Parts",
"receiveParts": "Receive Parts"
}
} }
} }

View File

@@ -0,0 +1,29 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import en_Translation from "./en_us/common.json";
import fr_Translation from "./fr/common.json";
import es_Translation from "./es/common.json";
// the translations
// (tip move them in a JSON file and import them)
const resources = {
en_us: en_Translation,
fr: fr_Translation,
es: es_Translation
};
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
resources,
lng: "en_us",
fallbackLng: "en-us",
debug: true,
//keySeparator: false, // we do not use keys in form messages.welcome
interpolation: {
escapeValue: false // react already safes from xss
}
});
export default i18n;