• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / 3b5e7bce9c5da12af4359302c0da5c793b07091e

04 Feb 2025 08:41AM UTC coverage: 54.606% (+0.01%) from 54.595%
3b5e7bce9c5da12af4359302c0da5c793b07091e

push

github

YoastBot
Bump version to 24.4 on free

7710 of 13750 branches covered (56.07%)

Branch coverage included in aggregate %.

30086 of 55466 relevant lines covered (54.24%)

41481.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/js/src/components/contentAnalysis/InclusiveLanguageAnalysis.js
1
/* global wpseoAdminL10n */
2
/* External components */
3
import { withSelect } from "@wordpress/data";
4
import { Fragment, createInterpolateElement } from "@wordpress/element";
5
import { __, sprintf } from "@wordpress/i18n";
6
import { isNil } from "lodash";
7
import PropTypes from "prop-types";
8
import styled from "styled-components";
9

10
/* Internal components */
11
import ScoreIconPortal from "../portals/ScoreIconPortal";
12
import Results from "../../containers/Results";
13
import Collapsible from "../SidebarCollapsible";
14
import getIndicatorForScore from "../../analysis/getIndicatorForScore";
15
import { getIconForScore } from "./mapResults";
16
import { LocationConsumer } from "@yoast/externals/contexts";
17
import HelpLink from "../HelpLink";
18
import Portal from "../portals/Portal";
19
import { Alert, SvgIcon } from "@yoast/components";
20
import isMultilingualPluginActive from "../../analysis/isMultilingualPluginActive";
21

22
const AnalysisHeader = styled.span`
×
23
        font-size: 1em;
24
        font-weight: bold;
25
        margin: 0 0 8px;
26
        display: block;
27
`;
28

29
const InclusiveLanguageResultsTabContainer = styled.div`
×
30
        padding: 16px;
31
`;
32

33
const StyledHelpLink = styled( HelpLink )`
×
34
        margin: -8px 0 -4px 4px;
35
`;
36

37
const GoodJobAnalysisResult = styled.p`
×
38
        min-height: 24px;
39
        margin: 12px 0 0 0;
40
        padding: 0;
41
        display: flex;
42
        align-items: flex-start;
43
`;
44
const ScoreIcon = styled( SvgIcon )`
×
45
        margin: 3px 11px 0 0; // icon 13 + 11 right margin = 24 for the 8px grid.
46
`;
47

48
/**
49
 * The inclusive language analysis component.
50
 *
51
 * @param {Object} props                                                                         The properties.
52
 *
53
 * @param {MappedResult[]} props.results                                         The assessment results.
54
 * @param {number} props.overallScore                                                 The overall analysis score.
55
 * @param {"enabled"|"disabled"} props.marksButtonStatus         The status of the mark buttons.
56
 *
57
 * @returns {JSX.Element} The inclusive language analysis component.
58
 */
59
const InclusiveLanguageAnalysis = ( props ) => {
×
60
        const analysisInfoLink = wpseoAdminL10n[ "shortlinks.inclusive_language_analysis_info" ];
×
61

62
        /**
63
         * Renders the results of the analysis.
64
         *
65
         * @returns {JSX.Element} The results of the analysis.
66
         */
67
        function renderResults() {
68
                const highlightingUpsellLink = "shortlinks.upsell.sidebar.highlighting_inclusive_analysis";
×
69

70
                return (
×
71
                        <Fragment>
72
                                <AnalysisHeader>
73
                                        { __( "Analysis results", "wordpress-seo" ) }
74
                                        <StyledHelpLink
75
                                                href={ analysisInfoLink }
76
                                                className="dashicons"
77
                                        >
78
                                                <span className="screen-reader-text">
79
                                                        {
80
                                                                /* translators: Hidden accessibility text. */
81
                                                                __( "Learn more about the inclusive language analysis", "wordpress-seo" )
82
                                                        }
83
                                                </span>
84
                                        </StyledHelpLink>
85
                                </AnalysisHeader>
86
                                <Results
87
                                        results={ props.results }
88
                                        marksButtonClassName="yoast-tooltip yoast-tooltip-w"
89
                                        marksButtonStatus={ props.marksButtonStatus }
90
                                        resultCategoryLabels={ {
91
                                                problems: __( "Non-inclusive", "wordpress-seo" ),
92
                                                improvements: __( "Potentially non-inclusive", "wordpress-seo" ),
93
                                        } }
94
                                        highlightingUpsellLink={ highlightingUpsellLink }
95
                                        shouldUpsellHighlighting={ props.shouldUpsellHighlighting }
96
                                />
97
                        </Fragment>
98
                );
99
        }
100

101
        const goodJobFeedback = createInterpolateElement(
×
102
                sprintf(
103
                        /* Translators: %1$s expands to a link on yoast.com, %2$s expands to the anchor end tag. */
104
                        __( "%1$sInclusive language%2$s: We haven't detected any potentially non-inclusive phrases. Great work!", "wordpress-seo" ),
105
                        "<a>",
106
                        "</a>"
107
                ),
108
                {
109
                        // eslint-disable-next-line jsx-a11y/anchor-has-content
110
                        a: <a href={ analysisInfoLink } target="_blank" rel="noreferrer" />,
111
                }
112
        );
113

114

115
        /**
116
         * Renders a notice that a multilingual plugin has been
117
         * detected and the analysis is run in English.
118
         *
119
         * @returns {JSX.Element} The multilingual plugin detected notice.
120
         */
121
        function renderMultilingualPluginDetectedNotice() {
122
                const notice = __(
×
123
                        "We noticed that you are using a multilingual plugin. Please be aware that this analysis feedback is intended only for texts written in English.",
124
                        "wordpress-seo"
125
                );
126
                return <Alert type={ "info" }>
×
127
                        { notice }
128
                </Alert>;
129
        }
130

131
        /**
132
         * Renders a feedback string for when no non-inclusive phrases are detected.
133
         *
134
         * @returns {JSX.Element} The feedback string.
135
         */
136
        function renderGoodJob() {
137
                return (
×
138
                        <Fragment>
139
                                <AnalysisHeader>
140
                                        { __( "Analysis results", "wordpress-seo" ) }
141
                                        <StyledHelpLink
142
                                                href={ analysisInfoLink }
143
                                                className="dashicons"
144
                                        >
145
                                                <span className="screen-reader-text">
146
                                                        {
147
                                                                /* translators: Hidden accessibility text. */
148
                                                                __( "Learn more about the inclusive language analysis", "wordpress-seo" )
149
                                                        }
150
                                                </span>
151
                                        </StyledHelpLink>
152
                                </AnalysisHeader>
153
                                <GoodJobAnalysisResult>
154
                                        <ScoreIcon
155
                                                icon={ "circle" }
156
                                                color={ "#7ad03a" }
157
                                                size="13px"
158
                                        />
159
                                        <span>{ goodJobFeedback }</span>
160
                                </GoodJobAnalysisResult>
161
                        </Fragment>
162
                );
163
        }
164

165
        /**
166
         * Renders the inclusive language analysis for the sidebar.
167
         *
168
         * @param {Array} results                                         The inclusive language assessment results.
169
         * @param {number} inclusiveLanguageScore         The inclusive language score.
170
         *
171
         * @returns {JSX.Element} The inclusive language for the sidebar.
172
         */
173
        function renderSidebar( results, inclusiveLanguageScore ) {
174
                return (
×
175
                        <Collapsible
176
                                title={ __( "Inclusive language", "wordpress-seo" ) }
177
                                titleScreenReaderText={ inclusiveLanguageScore.screenReaderInclusiveLanguageText }
178
                                prefixIcon={ getIconForScore( inclusiveLanguageScore.className ) }
179
                                prefixIconCollapsed={ getIconForScore( inclusiveLanguageScore.className ) }
180
                                id={ "yoast-inclusive-language-analysis-collapsible-sidebar" }
181
                        >
182
                                { isMultilingualPluginActive() ? renderMultilingualPluginDetectedNotice() : null }
×
183
                                { results.length >= 1 ? renderResults() : renderGoodJob() }
×
184
                        </Collapsible>
185
                );
186
        }
187

188
        /**
189
         * Renders the inclusive language analysis for the metabox.
190
         *
191
         * @param {Array} results                                         The inclusive language assessment results.
192
         * @param {number} inclusiveLanguageScore         The inclusive language score.
193
         *
194
         * @returns {JSX.Element} The inclusive language for the metabox.
195
         */
196
        function renderMetabox( results, inclusiveLanguageScore ) {
197
                return (
×
198
                        <Portal target="wpseo-metabox-inclusive-language-root">
199
                                <InclusiveLanguageResultsTabContainer>
200
                                        <ScoreIconPortal
201
                                                target="wpseo-inclusive-language-score-icon"
202
                                                scoreIndicator={ inclusiveLanguageScore.className }
203
                                        />
204
                                        { isMultilingualPluginActive() ? renderMultilingualPluginDetectedNotice() : null }
×
205
                                        { results.length >= 1 ? renderResults() : renderGoodJob() }
×
206
                                </InclusiveLanguageResultsTabContainer>
207
                        </Portal>
208
                );
209
        }
210

211
        const score = getIndicatorForScore( props.overallScore );
×
212

213
        if ( isNil( props.overallScore ) ) {
×
214
                score.className = "loading";
×
215
        }
216

217
        return (
×
218
                <LocationConsumer>
219
                        { location => {
220
                                if ( location === "sidebar" ) {
×
221
                                        return renderSidebar( props.results, score );
×
222
                                }
223

224
                                if ( location === "metabox" ) {
×
225
                                        return renderMetabox( props.results, score );
×
226
                                }
227
                        } }
228
                </LocationConsumer>
229
        );
230
};
231

232
InclusiveLanguageAnalysis.propTypes = {
×
233
        results: PropTypes.array,
234
        // `marksButtonStatus` is used, but not recognized by ESLint.
235
        marksButtonStatus: PropTypes.oneOf( [ "enabled", "disabled", "hidden" ] ).isRequired,
236
        overallScore: PropTypes.number,
237
        shouldUpsellHighlighting: PropTypes.bool,
238
};
239

240
InclusiveLanguageAnalysis.defaultProps = {
×
241
        results: [],
242
        overallScore: null,
243
        shouldUpsellHighlighting: false,
244
};
245

246
export default withSelect( select => {
247
        const {
248
                getInclusiveLanguageResults,
249
                getMarkButtonStatus,
250
        } = select( "yoast-seo/editor" );
×
251

252
        return {
×
253
                ...getInclusiveLanguageResults(),
254
                marksButtonStatus: getMarkButtonStatus(),
255
        };
256
} )( InclusiveLanguageAnalysis );
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc