feat: i18n user interface (#40306)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
} from '@freecodecamp/react-bootstrap';
|
||||
import { Link, navigate } from 'gatsby';
|
||||
import { createSelector } from 'reselect';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
projectMap,
|
||||
@@ -60,6 +61,7 @@ const propTypes = {
|
||||
isQaCertV7: PropTypes.bool,
|
||||
isRespWebDesignCert: PropTypes.bool,
|
||||
isSciCompPyCertV7: PropTypes.bool,
|
||||
t: PropTypes.func.isRequired,
|
||||
updateLegacyCert: PropTypes.func.isRequired,
|
||||
username: PropTypes.string,
|
||||
verifyCert: PropTypes.func.isRequired
|
||||
@@ -138,9 +140,8 @@ const isCertMapSelector = createSelector(
|
||||
|
||||
const honestyInfoMessage = {
|
||||
type: 'info',
|
||||
message:
|
||||
'To claim a certification, you must first accept our academic ' +
|
||||
'honesty policy'
|
||||
message: 'flash.msg-1',
|
||||
needsTranslating: true
|
||||
};
|
||||
|
||||
const initialState = {
|
||||
@@ -170,7 +171,7 @@ export class CertificationSettings extends Component {
|
||||
getUserIsCertMap = () => isCertMapSelector(this.props);
|
||||
|
||||
getProjectSolution = (projectId, projectTitle) => {
|
||||
const { completedChallenges } = this.props;
|
||||
const { completedChallenges, t } = this.props;
|
||||
const completedProject = find(
|
||||
completedChallenges,
|
||||
({ id }) => projectId === id
|
||||
@@ -197,7 +198,7 @@ export class CertificationSettings extends Component {
|
||||
id={`btn-for-${projectId}`}
|
||||
onClick={onClickHandler}
|
||||
>
|
||||
Show Code
|
||||
{t('buttons.show-code')}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
@@ -217,7 +218,7 @@ export class CertificationSettings extends Component {
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
Front End
|
||||
{t('buttons.frontend')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
bsStyle='primary'
|
||||
@@ -225,7 +226,7 @@ export class CertificationSettings extends Component {
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
Back End
|
||||
{t('buttons.backend')}
|
||||
</MenuItem>
|
||||
</DropdownButton>
|
||||
</div>
|
||||
@@ -242,7 +243,7 @@ export class CertificationSettings extends Component {
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
Show Solution
|
||||
{t('buttons.show-solution')}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
@@ -254,31 +255,42 @@ export class CertificationSettings extends Component {
|
||||
id={`btn-for-${projectId}`}
|
||||
onClick={onClickHandler}
|
||||
>
|
||||
Show Code
|
||||
{t('buttons.show-code')}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
renderCertifications = certName => (
|
||||
<FullWidthRow key={certName}>
|
||||
<Spacer />
|
||||
<h3 className='text-center'>{certName}</h3>
|
||||
<Table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Project Name</th>
|
||||
<th>Solution</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{this.renderProjectsFor(certName, this.getUserIsCertMap()[certName])}
|
||||
</tbody>
|
||||
</Table>
|
||||
</FullWidthRow>
|
||||
);
|
||||
|
||||
renderCertifications = certName => {
|
||||
const { t } = this.props;
|
||||
return (
|
||||
<FullWidthRow key={certName}>
|
||||
<Spacer />
|
||||
<h3 className='text-center'>{certName}</h3>
|
||||
<Table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t('settings.labels.project-name')}</th>
|
||||
<th>{t('settings.labels.solution')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{this.renderProjectsFor(
|
||||
certName,
|
||||
this.getUserIsCertMap()[certName]
|
||||
)}
|
||||
</tbody>
|
||||
</Table>
|
||||
</FullWidthRow>
|
||||
);
|
||||
};
|
||||
renderProjectsFor = (certName, isCert) => {
|
||||
const { username, isHonest, createFlashMessage, verifyCert } = this.props;
|
||||
const {
|
||||
username,
|
||||
isHonest,
|
||||
createFlashMessage,
|
||||
t,
|
||||
verifyCert
|
||||
} = this.props;
|
||||
const { superBlock } = first(projectMap[certName]);
|
||||
const certLocation = `/certification/${username}/${superBlock}`;
|
||||
const createClickHandler = superBlock => e => {
|
||||
@@ -310,7 +322,7 @@ export class CertificationSettings extends Component {
|
||||
href={certLocation}
|
||||
onClick={createClickHandler(superBlock)}
|
||||
>
|
||||
{isCert ? 'Show Certification' : 'Claim Certification'}
|
||||
{isCert ? t('buttons.show-cert') : t('buttons.claim-cert')}
|
||||
</Button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -391,7 +403,7 @@ export class CertificationSettings extends Component {
|
||||
}
|
||||
|
||||
renderLegacyCertifications = certName => {
|
||||
const { username, createFlashMessage, completedChallenges } = this.props;
|
||||
const { username, createFlashMessage, completedChallenges, t } = this.props;
|
||||
const { superBlock } = first(legacyProjectMap[certName]);
|
||||
const certLocation = `/certification/${username}/${superBlock}`;
|
||||
const challengeTitles = legacyProjectMap[certName].map(item => item.title);
|
||||
@@ -442,7 +454,9 @@ export class CertificationSettings extends Component {
|
||||
<Spacer />
|
||||
<h3 className='text-center'>{certName}</h3>
|
||||
<Form
|
||||
buttonText={fullForm ? 'Claim Certification' : 'Save Progress'}
|
||||
buttonText={
|
||||
fullForm ? t('buttons.claim-cert') : t('buttons.save-progress')
|
||||
}
|
||||
enableSubmit={fullForm}
|
||||
formFields={formFields}
|
||||
hideButton={isCertClaimed}
|
||||
@@ -465,7 +479,7 @@ export class CertificationSettings extends Component {
|
||||
style={buttonStyle}
|
||||
target='_blank'
|
||||
>
|
||||
Show Certification
|
||||
{t('buttons.show-cert')}
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
@@ -485,7 +499,8 @@ export class CertificationSettings extends Component {
|
||||
isFrontEndLibsCert,
|
||||
isInfosecQaCert,
|
||||
isJsAlgoDataStructCert,
|
||||
isRespWebDesignCert
|
||||
isRespWebDesignCert,
|
||||
t
|
||||
} = this.props;
|
||||
|
||||
const fullStackClaimable =
|
||||
@@ -522,8 +537,9 @@ export class CertificationSettings extends Component {
|
||||
<h3 className='text-center'>Legacy Full Stack Certification</h3>
|
||||
<div>
|
||||
<p>
|
||||
Once you've earned the following freeCodeCamp certifications, you'll
|
||||
be able to claim the Legacy Full Stack Developer Certification:
|
||||
{t('settings.claim-legacy', {
|
||||
cert: 'Legacy Full Stack Certification'
|
||||
})}
|
||||
</p>
|
||||
<ul>
|
||||
<li>Responsive Web Design</li>
|
||||
@@ -547,7 +563,9 @@ export class CertificationSettings extends Component {
|
||||
style={buttonStyle}
|
||||
target='_blank'
|
||||
>
|
||||
{isFullStackCert ? 'Show Certification' : 'Claim Certification'}
|
||||
{isFullStackCert
|
||||
? t('buttons.show-cert')
|
||||
: t('buttons.claim-cert')}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
@@ -559,7 +577,7 @@ export class CertificationSettings extends Component {
|
||||
style={buttonStyle}
|
||||
target='_blank'
|
||||
>
|
||||
Claim Certification
|
||||
{t('buttons.claim-cert')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
@@ -572,11 +590,13 @@ export class CertificationSettings extends Component {
|
||||
const {
|
||||
solutionViewer: { files, solution, isOpen, projectTitle }
|
||||
} = this.state;
|
||||
|
||||
const { t } = this.props;
|
||||
return (
|
||||
<section id='certification-settings'>
|
||||
<SectionHeader>Certifications</SectionHeader>
|
||||
<SectionHeader>{t('settings.headings.certs')}</SectionHeader>
|
||||
{certifications.map(this.renderCertifications)}
|
||||
<SectionHeader>Legacy Certifications</SectionHeader>
|
||||
<SectionHeader>{t('settings.headings.legacy-certs')}</SectionHeader>
|
||||
{this.renderLegacyFullStack()}
|
||||
{legacyCertifications.map(this.renderLegacyCertifications)}
|
||||
{isOpen ? (
|
||||
@@ -588,14 +608,18 @@ export class CertificationSettings extends Component {
|
||||
>
|
||||
<Modal.Header className='this-one?' closeButton={true}>
|
||||
<Modal.Title id='solution-viewer-modal-title'>
|
||||
Solution for {projectTitle}
|
||||
{t('settings.labels.solution-for', {
|
||||
projectTitle: projectTitle
|
||||
})}
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<SolutionViewer files={files} solution={solution} />
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button onClick={this.handleSolutionModalHide}>Close</Button>
|
||||
<Button onClick={this.handleSolutionModalHide}>
|
||||
{t('buttons.close')}
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
) : null}
|
||||
@@ -610,4 +634,4 @@ CertificationSettings.propTypes = propTypes;
|
||||
export default connect(
|
||||
null,
|
||||
mapDispatchToProps
|
||||
)(CertificationSettings);
|
||||
)(withTranslation()(CertificationSettings));
|
||||
|
Reference in New Issue
Block a user