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

Yoast / wordpress-seo / bd4fb5b465aecaf6795c5e18878a3b74fd4847b4

08 May 2025 07:46AM UTC coverage: 52.795% (+0.3%) from 52.524%
bd4fb5b465aecaf6795c5e18878a3b74fd4847b4

push

github

FAMarfuaty
Merge branch 'trunk' of github.com:Yoast/wordpress-seo into feature/ai-optimize-classic

8129 of 14281 branches covered (56.92%)

Branch coverage included in aggregate %.

27 of 71 new or added lines in 24 files covered. (38.03%)

51 existing lines in 1 file now uncovered.

29567 of 57120 relevant lines covered (51.76%)

41799.5 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 } 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
import { safeCreateInterpolateElement } from "../../helpers/i18n";
22

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

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

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

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

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

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

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

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

115

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

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

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

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

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

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

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

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

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

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

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

253
        return {
×
254
                ...getInclusiveLanguageResults(),
255
                marksButtonStatus: getMarkButtonStatus(),
256
        };
257
} )( 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