mirror of
https://github.com/DOI-DO/j40-cejst-2.git
synced 2025-07-31 20:31:16 -07:00
End-to-end working localization (#336)
* End-to-end localization working * Update package.json * fix FormattedMessage confusion by using the `FormattedMessage` from `gatsby-plugin-intl` NOT `react-intl` * TODO: `client/src/intl/es.json` should be generated from a translation tool. * Update package-lock.json
This commit is contained in:
parent
3cd6e06115
commit
cfce0dc826
8 changed files with 523 additions and 162 deletions
|
@ -10,17 +10,45 @@ import {
|
|||
} from '@trussworks/react-uswds';
|
||||
import {Helmet} from 'react-helmet';
|
||||
import {useFlags} from '../contexts/FlagContext';
|
||||
import {defineMessages} from 'react-intl';
|
||||
|
||||
const J40Header = () => {
|
||||
const flags = useFlags();
|
||||
const intl = useIntl();
|
||||
const title = intl.formatMessage({
|
||||
id: '71L0pp',
|
||||
defaultMessage: 'Justice40',
|
||||
description: 'Title of the project',
|
||||
});
|
||||
|
||||
const [mobileNavOpen, setMobileNavOpen] = useState(false);
|
||||
const messages = defineMessages({
|
||||
title: {
|
||||
id: 'header.title',
|
||||
defaultMessage: 'Justice40',
|
||||
description: 'Title in header',
|
||||
},
|
||||
about: {
|
||||
id: 'header.about',
|
||||
defaultMessage: 'About',
|
||||
description: 'Navigate to the about page',
|
||||
},
|
||||
explore: {
|
||||
id: 'header.explore',
|
||||
defaultMessage: 'Explore the tool',
|
||||
description: 'Navigate to the Explore the tool page',
|
||||
},
|
||||
methodology: {
|
||||
id: 'header.methodology',
|
||||
defaultMessage: 'Methodology',
|
||||
description: 'Navigate to the Methodology page',
|
||||
},
|
||||
contact: {
|
||||
id: 'header.contact',
|
||||
defaultMessage: 'Contact',
|
||||
description: 'Navigate to the Contact page',
|
||||
},
|
||||
timeline: {
|
||||
id: 'header.timeline',
|
||||
defaultMessage: 'Timeline',
|
||||
description: 'Navigate to the Timeline page',
|
||||
},
|
||||
});
|
||||
const title = intl.formatMessage(messages.title);
|
||||
|
||||
const toggleMobileNav = (): void =>
|
||||
setMobileNavOpen((prevOpen) => !prevOpen);
|
||||
|
@ -34,31 +62,31 @@ const J40Header = () => {
|
|||
to={'/'}
|
||||
key={'about'}
|
||||
activeClassName="usa-current"
|
||||
className={'j40-header'}>About</Link>],
|
||||
className={'j40-header'}>{intl.formatMessage(messages.about)}</Link>],
|
||||
['cejst',
|
||||
<Link
|
||||
to={'/cejst'}
|
||||
key={'cejst'}
|
||||
activeClassName="usa-current"
|
||||
className={'j40-header'}>Explore the tool</Link>],
|
||||
className={'j40-header'}>{intl.formatMessage(messages.explore)}</Link>],
|
||||
['methodology',
|
||||
<Link
|
||||
to={'/methodology'}
|
||||
key={'methodology'}
|
||||
activeClassName="usa-current"
|
||||
className={'j40-header'}>Methodology</Link>],
|
||||
className={'j40-header'}>{intl.formatMessage(messages.methodology)}</Link>],
|
||||
['contact',
|
||||
<Link
|
||||
to={'/contact'}
|
||||
key={'contact'}
|
||||
activeClassName="usa-current"
|
||||
className={'j40-header'}>Contact</Link>],
|
||||
className={'j40-header'}>{intl.formatMessage(messages.contact)}</Link>],
|
||||
['timeline',
|
||||
<Link
|
||||
to={'/timeline'}
|
||||
key={'timline'}
|
||||
activeClassName="usa-current"
|
||||
className={'j40-header'}>Timeline</Link>],
|
||||
className={'j40-header'}>{intl.formatMessage(messages.timeline)}</Link>],
|
||||
]);
|
||||
|
||||
// select which items from the above map to show, right now it's only two
|
||||
|
|
97
client/src/components/areasOfFocusList.tsx
Normal file
97
client/src/components/areasOfFocusList.tsx
Normal file
|
@ -0,0 +1,97 @@
|
|||
import * as React from 'react';
|
||||
// import * as styles from './areasOfFocusList.module.scss'; // TODO: move styles
|
||||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
import {defineMessages} from 'react-intl';
|
||||
|
||||
|
||||
// this section seems too verbose? must be a more readable way to do this.
|
||||
// this inlines the svg as data:image/svg+xml For larger images this
|
||||
// can cause page bloat, but it should be fine here.
|
||||
// @ts-ignore
|
||||
import ecoIcon from '/node_modules/uswds/dist/img/usa-icons/eco.svg';
|
||||
// @ts-ignore
|
||||
import busIcon from '/node_modules/uswds/dist/img/usa-icons/directions_bus.svg';
|
||||
// @ts-ignore
|
||||
import homeIcon from '/node_modules/uswds/dist/img/usa-icons/home.svg';
|
||||
// @ts-ignore
|
||||
import groupsIcon from '/node_modules/uswds/dist/img/usa-icons/groups.svg';
|
||||
import pollutionIcon // @ts-ignore
|
||||
from '/node_modules/uswds/dist/img/usa-icons/severe_weather.svg';
|
||||
// @ts-ignore
|
||||
import washIcon from '/node_modules/uswds/dist/img/usa-icons/wash.svg';
|
||||
// @ts-ignore
|
||||
import publicIcon from '/node_modules/uswds/dist/img/usa-icons/public.svg';
|
||||
|
||||
const AreasOfFocusList = () => {
|
||||
const intl = useIntl();
|
||||
const messages = defineMessages({
|
||||
climate: {
|
||||
id: 'areasOfInterest.climate',
|
||||
defaultMessage: 'Climate change',
|
||||
description: 'item in areasOfInterest list',
|
||||
},
|
||||
energy: {
|
||||
id: 'areasOfInterest.energy',
|
||||
defaultMessage: 'Clean energy and energy efficiency',
|
||||
description: 'item in areasOfInterest list',
|
||||
},
|
||||
transit: {
|
||||
id: 'areasOfInterest.transit',
|
||||
defaultMessage: 'Clean transit',
|
||||
description: 'item in areasOfInterest list',
|
||||
},
|
||||
housing: {
|
||||
id: 'areasOfInterest.housing',
|
||||
defaultMessage: 'Affordable and sustainable housing',
|
||||
description: 'item in areasOfInterest list',
|
||||
},
|
||||
training: {
|
||||
id: 'areasOfInterest.training',
|
||||
defaultMessage: 'Training and workforce development',
|
||||
description: 'item in areasOfInterest list',
|
||||
},
|
||||
pollution: {
|
||||
id: 'areasOfInterest.pollution',
|
||||
defaultMessage: 'Remediation of legacy pollution',
|
||||
description: 'item in areasOfInterest list',
|
||||
},
|
||||
water: {
|
||||
id: 'areasOfInterest.water',
|
||||
defaultMessage: 'Clean water infrastructure',
|
||||
description: 'item in areasOfInterest list',
|
||||
},
|
||||
});
|
||||
|
||||
const readMoreList: (any | string)[][] = [
|
||||
[publicIcon, intl.formatMessage(messages.climate)],
|
||||
[ecoIcon, intl.formatMessage(messages.energy)],
|
||||
[busIcon, intl.formatMessage(messages.transit)],
|
||||
[homeIcon, intl.formatMessage(messages.housing)],
|
||||
[groupsIcon, intl.formatMessage(messages.training)],
|
||||
[pollutionIcon, intl.formatMessage(messages.pollution)],
|
||||
[washIcon, intl.formatMessage(messages.water)],
|
||||
];
|
||||
return (
|
||||
<div className={'j40-two-column-confine'}>
|
||||
<ul className={'j40-two-column'}>
|
||||
{readMoreList.map((item, index) => {
|
||||
return (
|
||||
<li key={`readmore_li_${index}`}>
|
||||
<div className={'usa-icon-list__icon'}>
|
||||
<img
|
||||
className={'j40-two-column-icons-spacing'}
|
||||
key={`readmore_img_${index}`}
|
||||
src={item[0]} alt={item[1] + ' icon'}/>
|
||||
</div>
|
||||
<div
|
||||
className={'usa-icon-list__content'}> {item[1]} </div>
|
||||
</li>
|
||||
);
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AreasOfFocusList;
|
|
@ -4,6 +4,7 @@ import J40Header from './J40Header';
|
|||
import J40Footer from './J40Footer';
|
||||
import J40Aside from '../components/J40Aside';
|
||||
import {URLFlagProvider} from '../contexts/FlagContext';
|
||||
// this has to be wrong
|
||||
|
||||
interface ILayoutProps {
|
||||
children: ReactNode,
|
||||
|
@ -16,6 +17,7 @@ const Layout = ({children, location}: ILayoutProps) => {
|
|||
const gridCssClass = isWidthFullPage ? ' desktop:grid-col-12' :
|
||||
'desktop:grid-col-9';
|
||||
|
||||
// @ts-ignore
|
||||
return (
|
||||
<URLFlagProvider location={location}>
|
||||
<J40Header/>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue