const IGNORED_ERROR_MESSAGES: string[] = [
// react-virtualized & react-draggable use `findDOMNode` which is deprecated
'findDOMNode is deprecated and will be removed in the next major release',
+
+ // react-intl warning
+ '[@formatjs/intl] "defaultRichTextElements" was specified but "message" was not pre-compiled.',
];
failOnConsole({
"@primer/octicons-react": "19.11.0",
"@react-spring/rafz": "9.7.4",
"@react-spring/web": "9.7.4",
- "@sonarsource/echoes-react": "0.9.0",
+ "@sonarsource/echoes-react": "0.10.1",
"@tanstack/react-query": "5.56.2",
"@types/validator": "13.12.2",
"axios": "1.7.7",
+++ /dev/null
-<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 88"><defs><style>.cls-1{fill:#cb2029;}.cls-2{fill:#549dd0;}.cls-3{fill:#a0a5a8;}</style></defs><g id="Group_7691" data-name="Group 7691"><path id="Path_10468" data-name="Path 10468" class="cls-1" d="M15,87.26a14,14,0,1,1,14-14,14,14,0,0,1-14,14m0-25.42A11.44,11.44,0,1,0,26.43,73.28,11.46,11.46,0,0,0,15,61.84"/></g><path id="Path_10469" data-name="Path 10469" class="cls-1" d="M24.78,72.54c-.37-.73-.83-1.65-1.73-1.65s-1.35.91-1.72,1.65-.54,1-1,1-.62-.35-1-1-.82-1.65-1.72-1.65-1.35.91-1.73,1.65-.53,1-1,1-.62-.35-1-1-.82-1.65-1.72-1.65-1.36.91-1.73,1.65-.53,1-1,1-.63-.35-1-1-.82-1.65-1.72-1.65-1.36.87-1.72,1.6c0,0-.28.62-.4.91s-.6,1.41-.17,1.95c.25.3.6-.13.8-.45s.5-.94.5-.94c.37-.65.56-1,1-1s.62.36,1,1,.82,1.64,1.73,1.64S11,74.73,11.32,74s.54-1,1-1,.62.36,1,1,.83,1.64,1.73,1.64,1.35-.91,1.72-1.64.54-1,1-1,.62.36,1,1,.82,1.64,1.72,1.64,1.35-.91,1.73-1.64.53-1,1-1,.62.36,1,1l.38.7c.1.17.48.8.81.78s.4-1,.07-1.77C25.06,73.17,24.78,72.54,24.78,72.54Z"/><g id="SonarQube_Icon" data-name="SonarQube Icon"><path id="Path_10444" data-name="Path 10444" class="cls-2" d="M26.24,29.05H24.61A24.1,24.1,0,0,0,.37,5.15V3.52A25.73,25.73,0,0,1,26.24,29.05Z"/><path id="Path_10445" data-name="Path 10445" class="cls-2" d="M27.37,20.26a24.64,24.64,0,0,0-17-17.58l.38-1.31A26,26,0,0,1,28.7,20Z"/><path id="Path_10446" data-name="Path 10446" class="cls-2" d="M28.63,12.5A25,25,0,0,0,18.92,1.67l.57-.93A26.19,26.19,0,0,1,29.63,12.05Z"/></g><path class="cls-3" d="M16.25,42.09h4v2.33h-4V49H13.77V44.42h-4V42.09h4V37.85h2.48Z"/></svg>
\ No newline at end of file
import { getPendingPlugins } from '../../api/plugins';
import { getSystemStatus, waitSystemUPStatus } from '../../api/system';
import handleRequiredAuthorization from '../../app/utils/handleRequiredAuthorization';
-import { translate, translateWithParameters } from '../../helpers/l10n';
+import { translate } from '../../helpers/l10n';
+import { getIntl } from '../../helpers/l10nBundle';
import { AdminPagesContext } from '../../types/admin';
import { AppState } from '../../types/appstate';
import { PendingPluginResult } from '../../types/plugins';
}
export class AdminContainer extends React.PureComponent<AdminContainerProps, State> {
+ intl = getIntl();
mounted = false;
portalAnchor: Element | null = null;
state: State = {
<>
<Helmet
defer={false}
- titleTemplate={translateWithParameters(
- 'page_title.template.with_category',
- translate('layout.settings'),
+ titleTemplate={this.intl.formatMessage(
+ { id: 'page_title.template.with_category' },
+ { page: translate('layout.settings') },
)}
/>
{this.portalAnchor &&
import * as React from 'react';
import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async';
+import { useIntl } from 'react-intl';
import { Outlet } from 'react-router-dom';
import { CenteredLayout, Spinner } from '~design-system';
import { useLocation, useRouter } from '~sonar-aligned/components/hoc/withRouter';
import { getTasksForComponent } from '../../api/ce';
import { getComponentData } from '../../api/components';
import { getComponentNavigation } from '../../api/navigation';
-import { translateWithParameters } from '../../helpers/l10n';
import { HttpStatus } from '../../helpers/request';
import { getPortfolioUrl, getProjectUrl, getPullRequestUrl } from '../../helpers/urls';
import { useCurrentBranchQuery } from '../../queries/branch';
} = useLocation();
const router = useRouter();
+ const intl = useIntl();
+
const [component, setComponent] = React.useState<Component>();
const [currentTask, setCurrentTask] = React.useState<Task>();
const [tasksInProgress, setTasksInProgress] = React.useState<Task[]>();
<div>
<Helmet
defer={false}
- titleTemplate={translateWithParameters(
- 'page_title.template.with_instance',
- component?.name ?? '',
+ titleTemplate={intl.formatMessage(
+ { id: 'page_title.template.with_instance' },
+ { project: component?.name ?? '' },
)}
/>
{component &&
Title,
} from '~design-system';
import { Image } from '~sonar-aligned/components/common/Image';
+import { SonarQubeConnectionIllustration } from '../../components/branding/SonarQubeConnectionIllustration';
import { whenLoggedIn } from '../../components/hoc/whenLoggedIn';
import { translate, translateWithParameters } from '../../helpers/l10n';
import { generateSonarLintUserToken, portIsValid, sendUserToken } from '../../helpers/sonarlint';
{status === Status.request && (
<>
<Title>{translate('sonarlint-connection.request.title')}</Title>
- <Image
- alt="sonarlint-connection-request"
- className="sw-my-4"
- src="/images/SonarLint-connection-request.png"
- />
+ <SonarQubeConnectionIllustration className="sw-my-4" connected={false} />
<p className="sw-my-4">
- {translateWithParameters('sonarlint-connection.request.description', ideName)}
+ <FormattedMessage id="sonarlint-connection.request.description" values={{ ideName }} />
</p>
<p className="sw-mb-10">{translate('sonarlint-connection.request.description2')}</p>
{status === Status.tokenError && (
<>
- <Image alt="sonarlint-token-error" className="sw-my-4 sw-pt-2" src="/images/cross.svg" />
+ <Image aria-hidden className="sw-my-4 sw-pt-2" src="/images/cross.svg" />
<Title>{translate('sonarlint-connection.token-error.title')}</Title>
<p className="sw-my-4">{translate('sonarlint-connection.token-error.description')}</p>
<p className="sw-mb-4">
{status === Status.tokenCreated && newToken && (
<>
- <Image
- alt="sonarlint-connection-error"
- className="sw-my-4 sw-pt-2"
- src="/images/check.svg"
- />
+ <Image aria-hidden className="sw-my-4 sw-pt-2" src="/images/check.svg" />
<Title>{translate('sonarlint-connection.connection-error.title')}</Title>
<p className="sw-my-6">
{translate('sonarlint-connection.connection-error.description')}
{status === Status.tokenSent && newToken && (
<>
<Title>{translate('sonarlint-connection.success.title')}</Title>
- <Image
- alt="sonarlint-connection-success"
- className="sw-mb-4"
- src="/images/SonarLint-connection-ok.png"
- />
+ <SonarQubeConnectionIllustration className="sw-mb-4" connected />
<p className="sw-my-4">
{translateWithParameters('sonarlint-connection.success.description', newToken.name)}
</p>
import { AdminContainer, AdminContainerProps } from '../AdminContainer';
import AdminContext from '../AdminContext';
+jest.mock('../../../helpers/l10nBundle', () => {
+ const bundle = jest.requireActual('../../../helpers/l10nBundle');
+ return {
+ ...bundle,
+ getIntl: () => ({ formatMessage: jest.fn() }),
+ };
+});
+
jest.mock('../../../api/navigation', () => ({
getSettingsNavigation: jest
.fn()
});
it('should render the logged-in information', async () => {
- renderGlobalFooter();
+ renderGlobalFooter({}, { edition: EditionKey.community });
expect(ui.databaseWarningMessage.query()).not.toBeInTheDocument();
expect(ui.footerListItems.getAll()).toHaveLength(7);
expect(byText('Community Edition').get()).toBeInTheDocument();
- expect(ui.versionLabel('4.2').get()).toBeInTheDocument();
- expect(await ui.ltaDocumentationLinkActive.find()).toBeInTheDocument();
+ expect(await ui.versionLabel('4.2').find()).toBeInTheDocument();
+ expect(ui.ltaDocumentationLinkActive.query()).not.toBeInTheDocument();
expect(ui.apiLink.get()).toBeInTheDocument();
});
});
it('should not render the logged-in information', () => {
- renderGlobalFooter({ hideLoggedInInfo: true });
+ renderGlobalFooter({ hideLoggedInInfo: true }, { edition: EditionKey.community });
expect(ui.databaseWarningMessage.query()).not.toBeInTheDocument();
return renderComponent(<GlobalFooter {...props} />, '/', {
appState: mockAppState({
productionDatabase: true,
- edition: EditionKey.community,
+ edition: EditionKey.developer,
version: '4.2',
...appStateOverride,
}),
<span>
<FormattedMessage
id="indexation.admin_link"
- defaultMessage={translate('indexation.admin_link')}
values={{
link: renderBackgroundTasksPageLink(false, translate('background_tasks.page')),
}}
import withIndexationContext, {
WithIndexationContextProps,
} from '../../../components/hoc/withIndexationContext';
-import { translate } from '../../../helpers/l10n';
export class PageUnavailableDueToIndexation extends React.PureComponent<WithIndexationContextProps> {
componentDidUpdate() {
<CenteredLayout className="sw-flex sw-justify-around">
<FlagMessage className="sw-mt-32" variant="info">
<span className="sw-w-[290px]">
- {translate('indexation.page_unavailable.description')}
+ <FormattedMessage id="indexation.page_unavailable.description" />
<span className="sw-ml-1">
<FormattedMessage
- defaultMessage={translate(
- 'indexation.page_unavailable.description.additional_information',
- )}
id="indexation.page_unavailable.description.additional_information"
values={{
link: (
<Link to="https://docs.sonarsource.com/sonarqube/latest/instance-administration/reindexing/">
- {translate('learn_more')}
+ <FormattedMessage id="learn_more" />
</Link>
),
}}
*/
import { Link } from '@sonarsource/echoes-react';
+import { useIntl } from 'react-intl';
import { HelperHintIcon } from '~design-system';
import DocHelpTooltip from '~sonar-aligned/components/controls/DocHelpTooltip';
import HelpTooltip from '~sonar-aligned/components/controls/HelpTooltip';
import { DocLink } from '../../../../../helpers/doc-links';
-import { translate, translateWithParameters } from '../../../../../helpers/l10n';
+import { translate } from '../../../../../helpers/l10n';
import { getApplicationAdminUrl } from '../../../../../helpers/urls';
import { useProjectBindingQuery } from '../../../../../queries/devops-integration';
import { AlmKeys } from '../../../../../types/alm-settings';
const { data: projectBinding } = useProjectBindingQuery(component.key);
const isGitLab = projectBinding != null && projectBinding.alm === AlmKeys.GitLab;
+ const intl = useIntl();
+
if (isApplication) {
if (!hasManyBranches && canAdminComponent) {
return (
<DocHelpTooltip
content={
projectBinding != null
- ? translateWithParameters(
- `branch_like_navigation.no_branch_support.content_x.${isGitLab ? 'mr' : 'pr'}`,
- translate('alm', projectBinding.alm),
+ ? intl.formatMessage(
+ {
+ id: `branch_like_navigation.no_branch_support.content_x.${isGitLab ? 'mr' : 'pr'}`,
+ },
+ { alm: translate('alm', projectBinding.alm) },
)
: translate('branch_like_navigation.no_branch_support.content')
}
*/
import { DropdownMenu, DropdownMenuAlign } from '@sonarsource/echoes-react';
+import { FormattedMessage } from 'react-intl';
import { MainMenuItem } from '~design-system';
-import { translate } from '../../../../helpers/l10n';
import { AppState } from '../../../../types/appstate';
import { Extension } from '../../../../types/types';
import withAppStateContext from '../../app-state/withAppStateContext';
>
<MainMenuItem>
<a aria-haspopup="menu" href="#" id="global-navigation-more" role="button">
- {translate('more')}
+ <FormattedMessage id="more" />
</a>
</MainMenuItem>
</DropdownMenu.Root>
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { LogoSize } from '@sonarsource/echoes-react';
import * as React from 'react';
-import { MainAppBar, SonarQubeLogo } from '~design-system';
+import { MainAppBar } from '~design-system';
import { Image } from '~sonar-aligned/components/common/Image';
+import { SonarQubeProductLogo } from '../../../../components/branding/SonarQubeProductLogo';
import { translate } from '../../../../helpers/l10n';
import { GlobalSettingKeys } from '../../../../types/settings';
import { AppStateContext } from '../../app-state/AppStateContext';
{customLogoUrl ? (
<Image alt={title} src={customLogoUrl} width={customLogoWidth} />
) : (
- <SonarQubeLogo />
+ <SonarQubeProductLogo hasText size={LogoSize.Large} />
)}
</div>
);
*/
import styled from '@emotion/styled';
-import { Button } from '@sonarsource/echoes-react';
+import { Button, Theme, ThemeProvider } from '@sonarsource/echoes-react';
import * as React from 'react';
import { ButtonPrimary, themeBorder, themeColor } from '~design-system';
-import { Image } from '~sonar-aligned/components/common/Image';
import { dismissNotice } from '../../../api/users';
+import { SonarQubeIDEPromotionIllustration } from '../../../components/branding/SonarQubeIDEPromotionIllustration';
import { translate } from '../../../helpers/l10n';
import { NoticeType, isLoggedIn } from '../../../types/users';
import { CurrentUserContextInterface } from '../current-user/CurrentUserContext';
return (
<PromotionNotificationWrapper className="it__promotion_notification sw-z-global-popup sw-rounded-1 sw-flex sw-items-center sw-px-4">
- <div className="sw-mr-2">
- <Image alt="SonarQube + SonarLint" height={80} src="/images/sq-sl.svg" />
- </div>
+ <ThemeProvider theme={Theme.dark}>
+ <div className="sw-mr-2">
+ <SonarQubeIDEPromotionIllustration />
+ </div>
+ </ThemeProvider>
<PromotionNotificationContent className="sw-flex-1 sw-px-2 sw-py-4">
<span className="sw-typo-semibold">{translate('promotion.sonarlint.title')}</span>
<p className="sw-mt-2">{translate('promotion.sonarlint.content')}</p>
},
);
- const [l10nBundle, currentUser, appState, availableFeatures] = await Promise.all([
- loadL10nBundle(),
+ const appState = isMainApp()
+ ? await getGlobalNavigation().catch((error) => {
+ // eslint-disable-next-line no-console
+ console.error(error);
+ return undefined;
+ })
+ : undefined;
+
+ const [l10nBundle, currentUser, availableFeatures] = await Promise.all([
+ loadL10nBundle(appState),
isMainApp() ? getCurrentUser() : undefined,
- isMainApp() ? getGlobalNavigation() : undefined,
isMainApp() ? getAvailableFeatures() : undefined,
]).catch((error) => {
// eslint-disable-next-line no-console
import * as React from 'react';
import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async';
+import { useIntl } from 'react-intl';
import { Outlet } from 'react-router-dom';
import { LargeCenteredLayout, PageContentFontWrapper, TopBar } from '~design-system';
import A11ySkipTarget from '~sonar-aligned/components/a11y/A11ySkipTarget';
import { useCurrentLoginUser } from '../../app/components/current-user/CurrentUserContext';
-import { translate, translateWithParameters } from '../../helpers/l10n';
+import { translate } from '../../helpers/l10n';
import Nav from './components/Nav';
import UserCard from './components/UserCard';
const currentUser = useCurrentLoginUser();
const [portalAnchor, setPortalAnchor] = React.useState<Element | null>(null);
+ const intl = useIntl();
+
// Set portal anchor on mount
React.useEffect(() => {
setPortalAnchor(document.getElementById('component-nav-portal'));
<Helmet
defaultTitle={title}
defer={false}
- titleTemplate={translateWithParameters(
- 'page_title.template.with_category',
- translate('my_account.page'),
+ titleTemplate={intl.formatMessage(
+ { id: 'page_title.template.with_category' },
+ { page: translate('my_account.page') },
)}
/>
};
});
+jest.mock('../../../../helpers/l10nBundle', () => {
+ const bundle = jest.requireActual('../../../../helpers/l10nBundle');
+ return {
+ ...bundle,
+ getIntl: () => ({ formatMessage: jest.fn(({ id }) => `${id}`) }),
+ };
+});
+
const ui = {
pageTitle: byRole('heading', { name: 'audit_logs.page' }),
downloadButton: byRole('link', { name: 'download_verb' }),
const rulesHandler = new CodingRulesServiceMock();
const settingsHandler = new SettingsServiceMock();
+
+jest.mock('../../../helpers/l10nBundle', () => {
+ const bundle = jest.requireActual('../../../helpers/l10nBundle');
+ return {
+ ...bundle,
+ getIntl: () => ({ formatMessage: jest.fn() }),
+ };
+});
+
afterEach(() => {
settingsHandler.reset();
rulesHandler.reset();
expect(ui.ruleCleanCodeAttribute(CleanCodeAttribute.Clear).get()).toBeInTheDocument();
// 1 In Rule details + 1 in facet
expect(ui.ruleSoftwareQuality(SoftwareQuality.Maintainability).getAll()).toHaveLength(2);
- expect(document.title).toEqual('page_title.template.with_category.coding_rules.page');
+ expect(document.title).toEqual('coding_rule.page.Java.Awsome java rule');
expect(screen.getByText('Why')).toBeInTheDocument();
expect(screen.getByText('Because')).toBeInTheDocument();
const rulesHandler = new CodingRulesServiceMock();
const settingsHandler = new SettingsServiceMock();
+jest.mock('../../../helpers/l10nBundle', () => {
+ const bundle = jest.requireActual('../../../helpers/l10nBundle');
+ return {
+ ...bundle,
+ getIntl: () => ({ formatMessage: jest.fn() }),
+ };
+});
+
afterEach(() => {
rulesHandler.reset();
settingsHandler.reset();
const rulesHandler = new CodingRulesServiceMock();
const settingsHandler = new SettingsServiceMock();
+jest.mock('../../../helpers/l10nBundle', () => {
+ const bundle = jest.requireActual('../../../helpers/l10nBundle');
+ return {
+ ...bundle,
+ getIntl: () => ({ formatMessage: jest.fn() }),
+ };
+});
+
afterEach(() => {
rulesHandler.reset();
settingsHandler.reset();
import { isInput, isShortcut } from '../../../helpers/keyboardEventHelpers';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { getIntl } from '../../../helpers/l10nBundle';
import { SecurityStandard } from '../../../types/security';
import { SettingsKey } from '../../../types/settings';
import { Dict, Paging, Rule, RuleActivation } from '../../../types/types';
const RULE_LIST_HEADER_HEIGHT = 68;
export class CodingRulesApp extends React.PureComponent<Props, State> {
+ intl = getIntl();
mounted = false;
constructor(props: Props) {
<Helmet
defer={false}
title={translateWithParameters('coding_rule.page', openRule.langName, openRule.name)}
- titleTemplate={translateWithParameters(
- 'page_title.template.with_category',
- translate('coding_rules.page'),
+ titleTemplate={this.intl.formatMessage(
+ { id: 'page_title.template.with_category' },
+ { page: translate('coding_rules.page') },
)}
/>
) : (
}),
};
-const original = window.location;
-
beforeAll(() => {
- Object.defineProperty(window, 'location', {
- configurable: true,
- value: { replace: jest.fn() },
- });
almIntegrationHandler = new AlmIntegrationsServiceMock();
dopTranslationHandler = new DopTranslationServiceMock();
newCodePeriodHandler = new NewCodeDefinitionServiceMock();
dopTranslationHandler.reset();
newCodePeriodHandler.reset();
});
-afterAll(() => {
- Object.defineProperty(window, 'location', { configurable: true, value: original });
-});
it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => {
const user = userEvent.setup();
}),
instanceSelector: byLabelText(/alm.configuration.selector.label/),
};
-const original = window.location;
beforeAll(() => {
- Object.defineProperty(window, 'location', {
- configurable: true,
- value: { replace: jest.fn() },
- });
almIntegrationHandler = new AlmIntegrationsServiceMock();
dopTranslationHandler = new DopTranslationServiceMock();
newCodePeriodHandler = new NewCodeDefinitionServiceMock();
newCodePeriodHandler.reset();
});
-afterAll(() => {
- Object.defineProperty(window, 'location', { configurable: true, value: original });
-});
-
it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => {
const user = userEvent.setup();
renderCreateProject();
globalSettingRadio: byRole('radio', { name: 'new_code_definition.global_setting' }),
};
-const original = window.location;
-
beforeAll(() => {
- Object.defineProperty(window, 'location', {
- configurable: true,
- value: { replace: jest.fn() },
- });
almIntegrationHandler = new AlmIntegrationsServiceMock();
dopTranslationHandler = new DopTranslationServiceMock();
newCodePeriodHandler = new NewCodeDefinitionServiceMock();
newCodePeriodHandler.reset();
});
-afterAll(() => {
- Object.defineProperty(window, 'location', { configurable: true, value: original });
-});
-
it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => {
const user = userEvent.setup();
renderCreateProject();
};
beforeAll(() => {
- Object.defineProperty(window, 'location', {
- configurable: true,
- value: { replace: jest.fn() },
- });
almIntegrationHandler = new AlmIntegrationsServiceMock();
almSettingsHandler = new AlmSettingsServiceMock();
componentsHandler = new ComponentsServiceMock();
// Are rule headers present?
expect(screen.getByRole('heading', { level: 1, name: 'Fix that' })).toBeInTheDocument();
- expect(screen.getByRole('link', { name: 'advancedRuleId' })).toBeInTheDocument();
+ expect(screen.getByRole('link', { name: /^advancedRuleId/ })).toBeInTheDocument();
// Select the "why is this an issue" tab and check its content
await user.click(
// Are rule headers present?
expect(screen.getByRole('heading', { level: 1, name: 'Fix this' })).toBeInTheDocument();
- expect(screen.getByRole('link', { name: 'simpleRuleId' })).toBeInTheDocument();
+ expect(screen.getByRole('link', { name: /^simpleRuleId/ })).toBeInTheDocument();
// Select the "why is this an issue tab" and check its content
await user.click(
// Are rule headers present?
expect(screen.getByRole('heading', { level: 1, name: 'Issue on file' })).toBeInTheDocument();
- expect(screen.getByRole('link', { name: 'simpleRuleId' })).toBeInTheDocument();
+ expect(screen.getByRole('link', { name: /^simpleRuleId/ })).toBeInTheDocument();
// The "Where is the issue" tab should be selected by default. Check its content
expect(screen.getAllByRole('button', { name: 'Issue on file' })).toHaveLength(2); // there will be 2 buttons one in concise issue and other in code viewer
import styled from '@emotion/styled';
import { Spinner } from '@sonarsource/echoes-react';
import { Helmet } from 'react-helmet-async';
+import { useIntl } from 'react-intl';
import {
FlagMessage,
LargeCenteredLayout,
import { IssueSuggestionCodeTab } from '../../../components/rules/IssueSuggestionCodeTab';
import IssueTabViewer from '../../../components/rules/IssueTabViewer';
import { fillBranchLike } from '../../../helpers/branch-like';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { translate } from '../../../helpers/l10n';
import { useRuleDetailsQuery } from '../../../queries/rules';
import A11ySkipTarget from '../../../sonar-aligned/components/a11y/A11ySkipTarget';
import { isPortfolioLike } from '../../../sonar-aligned/helpers/component';
const { data: ruleData, isLoading: isLoadingRule } = useRuleDetailsQuery({ key: openIssue.rule });
const openRuleDetails = ruleData?.rule;
+ const intl = useIntl();
+
const warning = !canBrowseAllChildProjects && isPortfolioLike(qualifier) && (
<FlagMessage
className="it__portfolio_warning sw-flex"
<Helmet
defer={false}
title={openIssue.message}
- titleTemplate={translateWithParameters(
- 'page_title.template.with_category',
- translate('issues.page'),
+ titleTemplate={intl.formatMessage(
+ { id: 'page_title.template.with_category' },
+ { page: translate('issues.page') },
)}
/>
<h1 className="sw-sr-only">{translate('issues.page')}</h1>
{isExternal ? (
<span>({key})</span>
) : (
- <Link to={getRuleUrl(key)} target="_blank">
+ <Link to={getRuleUrl(key)} shouldOpenInNewTab>
{key}
</Link>
)}
import { FormattedMessage } from 'react-intl';
import { formatMeasure } from '~sonar-aligned/helpers/measures';
-import { translate } from '../../../helpers/l10n';
export default function TotalEffort({ effort }: { effort: number }) {
return (
<div className="sw-inline-block">
<FormattedMessage
- defaultMessage={translate('issue.x_effort')}
id="issue.x_effort"
values={{ 0: <strong>{formatMeasure(effort, 'WORK_DUR')}</strong> }}
/>
IconMoreVertical,
Tooltip,
} from '@sonarsource/echoes-react';
+import { useIntl } from 'react-intl';
import {
ActionCell,
Badge,
export default function BranchListRow(props: BranchListRowProps) {
const { branch, existingBranches, inheritedSetting } = props;
+ const intl = useIntl();
+
let settingWarning: string | undefined;
if (branchInheritsItselfAsReference(branch, inheritedSetting)) {
settingWarning = translateWithParameters(
branch.name,
);
} else if (referenceBranchDoesNotExist(branch, existingBranches)) {
- settingWarning = translateWithParameters(
- 'baseline.reference_branch.does_not_exist',
- branch.newCodePeriod?.value ?? '',
+ settingWarning = intl.formatMessage(
+ {
+ id: 'baseline.reference_branch.does_not_exist',
+ },
+ { branch: branch.newCodePeriod?.value ?? '' },
);
}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { FormattedMessage } from 'react-intl';
import { MenuPlacement, OptionProps, components } from 'react-select';
import { Badge, FlagErrorIcon, FormField, InputSelect, SelectionCard } from '~design-system';
import Tooltip from '../../../components/controls/Tooltip';
import { NewCodeDefinitionLevels } from '../../../components/new-code-definition/utils';
import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { translate } from '../../../helpers/l10n';
import { NewCodeDefinitionType } from '../../../types/new-code-definition';
export interface BaselineSettingReferenceBranchProps {
<components.Option {...props}>
{option.isInvalid ? (
<Tooltip
- content={translateWithParameters(
- 'baseline.reference_branch.does_not_exist',
- option.value,
- )}
+ content={
+ <FormattedMessage
+ id="baseline.reference_branch.does_not_exist"
+ values={{ branch: option.value }}
+ />
+ }
>
<span>
{option.value} <FlagErrorIcon className="sw-ml-2" />
branchNCDsBanner: byText(/new_code_definition.auto_update.branch.message/),
dismissButton: byLabelText('dismiss'),
baselineSpecificAnalysisDate: byText(/January 10, 2018/),
+ missingReferenceBranchWarning: byText('baseline.reference_branch.does_not_exist'),
};
async function appIsLoaded() {
<span className="sw-typo-semibold" title={formattedAnalysisDate}>
<FormattedMessage
id="projects.last_analysis_on_x"
- defaultMessage={translate('projects.last_analysis_on_x')}
values={{
date: <DateFromNow className="sw-typo-default" date={analysisDate} />,
}}
import styled from '@emotion/styled';
import { useCallback, useEffect } from 'react';
import { Helmet } from 'react-helmet-async';
+import { useIntl } from 'react-intl';
import { useNavigate, useParams } from 'react-router-dom';
import {
Card,
import Suggestions from '../../../components/embed-docs-modal/Suggestions';
import '../../../components/search-navigator.css';
import { DocLink } from '../../../helpers/doc-links';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { translate } from '../../../helpers/l10n';
import { getQualityGateUrl } from '../../../helpers/urls';
import { useQualityGatesQuery } from '../../../queries/quality-gates';
import { QualityGate } from '../../../types/types';
export default function App() {
const { data, isLoading } = useQualityGatesQuery();
+ const intl = useIntl();
const { name } = useParams();
const navigate = useNavigate();
const {
<PageContentFontWrapper className="sw-typo-default">
<Helmet
defer={false}
- titleTemplate={translateWithParameters(
- 'page_title.template.with_category',
- translate('quality_gates.page'),
+ titleTemplate={intl.formatMessage(
+ { id: 'page_title.template.with_category' },
+ { page: translate('quality_gates.page') },
)}
/>
<div className="sw-grid sw-gap-x-12 sw-gap-y-6 sw-grid-cols-12 sw-w-full">
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
+import { useIntl } from 'react-intl';
import { Outlet, useSearchParams } from 'react-router-dom';
import { useLocation } from '~sonar-aligned/components/hoc/withRouter';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { translate } from '../../../helpers/l10n';
import ProfileHeader from '../details/ProfileHeader';
import { useQualityProfilesContext } from '../qualityProfilesContext';
import ProfileNotFound from './ProfileNotFound';
const context = useQualityProfilesContext();
const { profiles } = context;
+ const intl = useIntl();
+
// try to find a quality profile with the given key
// if managed to find one, redirect to a new version
// otherwise show not found page
<Helmet
defer={false}
title={profile.name}
- titleTemplate={translateWithParameters(
- 'page_title.template.with_category',
- translate('quality_profiles.page'),
+ titleTemplate={intl.formatMessage(
+ { id: 'page_title.template.with_category' },
+ { page: translate('quality_profiles.page') },
)}
/>
<ProfileHeader
*/
import styled from '@emotion/styled';
-import { Spinner } from '@sonarsource/echoes-react';
+import { LogoSize, LogoSonar, Spinner } from '@sonarsource/echoes-react';
import { Helmet } from 'react-helmet-async';
+import { FormattedMessage } from 'react-intl';
import {
Card,
FlagMessage,
themeBorder,
themeColor,
} from '~design-system';
-import { Image } from '~sonar-aligned/components/common/Image';
import { Location } from '~sonar-aligned/types/router';
+import { SonarQubeProductLogo } from '../../../components/branding/SonarQubeProductLogo';
import { translate } from '../../../helpers/l10n';
import { getReturnUrl } from '../../../helpers/urls';
import { IdentityProvider } from '../../../types/types';
const displayError = Boolean(location.query.authorizationError);
return (
- <div className="sw-flex sw-flex-col sw-items-center" id="login_form">
+ <div className="sw-flex sw-flex-col sw-items-center sw-pt-32" id="login_form">
<Helmet defer={false} title={translate('login.page')} />
- <Image alt="" className="sw-mt-32" src="/images/sonar-logo-horizontal.png" />
+ <LogoSonar hasText size={LogoSize.Large} />
<Card className="sw-my-14 sw-p-0 sw-w-abs-350">
<PageContentFontWrapper className="sw-typo-lg sw-flex sw-flex-col sw-items-center sw-py-8 sw-px-4">
- <Image alt="" className="sw-mb-6" src="/images/embed-doc/sq-icon.svg" width={28} />
- <Title className="sw-mb-6">{translate('login.login_to_sonarqube')}</Title>
+ <SonarQubeProductLogo size={LogoSize.Small} />
+ <Title className="sw-my-6 sw-text-center">
+ <FormattedMessage id="login.login_to_sonarqube" />
+ </Title>
<Spinner isLoading={loading}>
<>
{displayError && (
hasMessage: jest.fn(),
}));
+jest.mock('../../../helpers/l10nBundle', () => {
+ const bundle = jest.requireActual('../../../helpers/l10nBundle');
+ return {
+ ...bundle,
+ getIntl: () => ({ formatMessage: jest.fn(({ id }) => `${id}`) }),
+ };
+});
+
const fields = [
{ key: 'foo', type: 'STRING' } as SettingFieldDefinition,
{ key: 'bar', type: 'SINGLE_SELECT_LIST' } as SettingFieldDefinition,
import { first } from 'lodash';
import { byRole, byText } from '~sonar-aligned/helpers/testSelector';
import SystemServiceMock from '../../../../api/mocks/SystemServiceMock';
+import { mockAppState } from '../../../../helpers/testMocks';
import { renderAppRoutes } from '../../../../helpers/testReactTestingUtils';
import { AppState } from '../../../../types/appstate';
+import { EditionKey } from '../../../../types/editions';
import routes from '../../routes';
import { LogsLevels } from '../../utils';
});
function renderSystemApp(appState?: AppState) {
- return renderAppRoutes('system', routes, { appState });
+ return renderAppRoutes('system', routes, {
+ appState: mockAppState({ edition: EditionKey.developer, ...appState }),
+ });
}
function getPageObjects() {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { useAppState } from '../../app/components/app-state/withAppStateContext';
+import { EditionKey } from '../../types/editions';
+
+interface Props {
+ className?: string;
+ connected: boolean;
+}
+
+/**
+ * This component switches between the Community and Server product versions' logo,
+ * and between the connected and requested versions of the illustration
+ */
+export function SonarQubeConnectionIllustration(props: Props) {
+ const { edition } = useAppState();
+
+ return edition === EditionKey.community ? (
+ <CommunityIllustration {...props} />
+ ) : (
+ <ServerIllustration {...props} />
+ );
+}
+
+function CommunityIllustration({ connected, ...imageProps }: Props) {
+ return connected ? (
+ <svg
+ aria-hidden
+ width="179"
+ height="98"
+ viewBox="0 0 179 98"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ {...imageProps}
+ >
+ <path
+ fillRule="evenodd"
+ clipRule="evenodd"
+ d="M72.005 26h-50.01c-8.836 0-16 7.163-16 16v40c0 8.837 7.164 16 16 16h135c8.837 0 16-7.163 16-16V42c0-8.837-7.163-16-16-16h-57.4l-2 2h59.4c7.732 0 14 6.268 14 14v40c0 7.732-6.268 14-14 14h-135c-7.732 0-14-6.268-14-14V42c0-7.732 6.268-14 14-14h52.01l-2-2Z"
+ fill="var(--echoes-color-icon-success)"
+ />
+ <path
+ d="M66.545 64.34c0 1.08-1.23 1.71-2.1 1.08-.96-.72-1.56-1.86-2.04-2.76-.66-1.26-1.14-2.01-1.74-2.01-.6 0-1.05.75-1.74 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.74-2.01-.63 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.71-2.01-.6 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.48-.87-.84-1.53-1.2-1.83-.3-.24-.51-.57-.51-.96v-.21c0-1.08 1.23-1.71 2.1-1.08.96.72 1.56 1.86 2.04 2.76.66 1.26 1.11 2.01 1.71 2.01.6 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.74-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.48.87.84 1.53 1.23 1.83.3.24.51.57.51.96v.21h-.03ZM46.355 83.18c-4.95 0-9.66-1.71-13.47-4.83-.6-.51-.66-1.44-.12-2.01.51-.54 1.32-.57 1.86-.12 3.42 2.85 7.71 4.32 12.21 4.2 4.5-.12 8.7-1.83 11.97-4.83.54-.48 1.35-.48 1.86 0 .57.54.57 1.47 0 2.01-3.75 3.48-8.61 5.43-13.77 5.58h-.57.03ZM32.045 48.41c-.57-.54-.57-1.47 0-2.01 3.87-3.57 8.79-5.43 13.77-5.55 4.98-.12 9.96 1.47 14.04 4.83.6.51.66 1.44.12 2.01-.51.51-1.32.57-1.86.12-3.51-2.88-7.8-4.29-12.09-4.2-4.29.09-8.67 1.71-12.09 4.83-.54.48-1.35.48-1.86 0l-.03-.03Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M90.316 63.612h5.232v1.632h-5.232V70.5h-1.632v-5.256h-5.232v-1.632h5.232v-5.256h1.632v5.256Z"
+ fill="var(--echoes-color-text-subdued)"
+ />
+ <path
+ d="M155.444 63.552A1.55 1.55 0 0 1 153.892 62c0-11.524-9.373-20.897-20.897-20.897a1.55 1.55 0 0 1-1.551-1.551A1.55 1.55 0 0 1 132.995 38c13.231 0 24 10.769 24 24a1.55 1.55 0 0 1-1.551 1.552ZM132.995 86c-13.231 0-24-10.769-24-24a1.55 1.55 0 0 1 1.552-1.552A1.55 1.55 0 0 1 112.099 62c0 11.524 9.372 20.897 20.896 20.897a1.55 1.55 0 0 1 1.552 1.551A1.55 1.55 0 0 1 132.995 86Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M147.582 63.552A1.55 1.55 0 0 1 146.03 62c0-7.19-5.845-13.035-13.035-13.035a1.55 1.55 0 0 1-1.551-1.551 1.55 1.55 0 0 1 1.551-1.552c8.897 0 16.138 7.241 16.138 16.138a1.55 1.55 0 0 1-1.551 1.552ZM132.995 78.138c-8.896 0-16.138-7.242-16.138-16.138a1.55 1.55 0 0 1 1.552-1.552A1.55 1.55 0 0 1 119.961 62c0 7.19 5.845 13.034 13.034 13.034a1.55 1.55 0 0 1 1.552 1.552 1.55 1.55 0 0 1-1.552 1.552ZM133.016 70.286a8.254 8.254 0 0 1-5.855-2.42c-3.228-3.228-3.228-8.483 0-11.721a8.232 8.232 0 0 1 5.855-2.431 8.19 8.19 0 0 1 5.855 2.43c.61.611.61 1.594 0 2.194-.61.61-1.593.61-2.193 0a5.133 5.133 0 0 0-3.662-1.52c-1.386 0-2.69.537-3.662 1.52a5.189 5.189 0 0 0 0 7.324 5.188 5.188 0 0 0 7.324 0c.61-.61 1.593-.61 2.193 0 .6.61.61 1.593 0 2.193a8.254 8.254 0 0 1-5.855 2.42v.011Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M110.658 4.837a2.861 2.861 0 0 1 0 4.044L87.804 31.736a2.861 2.861 0 0 1-4.044 0L72.332 20.308a2.861 2.861 0 0 1 0-4.044 2.861 2.861 0 0 1 4.044 0l9.41 9.401 20.837-20.828a2.86 2.86 0 0 1 4.044 0h-.009Z"
+ fill="var(--echoes-color-icon-success)"
+ />
+ </svg>
+ ) : (
+ <svg
+ aria-hidden
+ width="179"
+ height="98"
+ viewBox="0 0 179 98"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ {...imageProps}
+ >
+ <path
+ d="M35.076 27H80.745L64.703 97H16C7.716 97 1 90.284 1 82V42c0-8.284 6.716-15 15-15h19.076Z"
+ stroke="var(--echoes-color-border-weak)"
+ strokeWidth="2"
+ />
+ <path
+ d="M56.55 64.34c0 1.08-1.23 1.71-2.1 1.08-.96-.72-1.56-1.86-2.04-2.76-.66-1.26-1.14-2.01-1.74-2.01-.6 0-1.05.75-1.74 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.74-2.01-.63 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.71-2.01-.6 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.48-.87-.84-1.53-1.2-1.83-.3-.24-.51-.57-.51-.96v-.21c0-1.08 1.23-1.71 2.1-1.08.96.72 1.56 1.86 2.04 2.76.66 1.26 1.11 2.01 1.71 2.01.6 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.74-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.48.87.84 1.53 1.23 1.83.3.24.51.57.51.96v.21h-.03ZM36.36 83.18c-4.95 0-9.66-1.71-13.47-4.83-.6-.51-.66-1.44-.12-2.01.51-.54 1.32-.57 1.86-.12 3.42 2.85 7.71 4.32 12.21 4.2 4.5-.12 8.7-1.83 11.97-4.83.54-.48 1.35-.48 1.86 0 .57.54.57 1.47 0 2.01-3.75 3.48-8.61 5.43-13.77 5.58h-.57.03ZM22.05 48.41c-.57-.54-.57-1.47 0-2.01 3.87-3.57 8.79-5.43 13.77-5.55 4.98-.12 9.96 1.47 14.04 4.83.6.51.66 1.44.12 2.01-.51.51-1.32.57-1.86.12-3.51-2.88-7.8-4.29-12.09-4.2-4.29.09-8.67 1.71-12.09 4.83-.54.48-1.35.48-1.86 0l-.03-.03Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M90.32 63.612h5.233v1.632H90.32V70.5h-1.632v-5.256h-5.232v-1.632h5.232v-5.256h1.632v5.256Z"
+ fill="var(--echoes-color-text-subdued)"
+ />
+ <path
+ d="M143.924 97H98.255l16.042-70H163c8.284 0 15 6.716 15 15v40c0 8.284-6.716 15-15 15h-19.076Z"
+ stroke="var(--echoes-color-border-weak)"
+ strokeWidth="2"
+ />
+ <path
+ d="M165.448 62.552A1.55 1.55 0 0 1 163.897 61c0-11.524-9.373-20.897-20.897-20.897a1.55 1.55 0 0 1-1.552-1.551A1.55 1.55 0 0 1 143 37c13.231 0 24 10.769 24 24a1.55 1.55 0 0 1-1.552 1.552ZM143 85c-13.231 0-24-10.769-24-24a1.55 1.55 0 0 1 1.552-1.552A1.55 1.55 0 0 1 122.103 61c0 11.524 9.373 20.897 20.897 20.897a1.55 1.55 0 0 1 1.552 1.551A1.55 1.55 0 0 1 143 85Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M157.586 62.552A1.55 1.55 0 0 1 156.034 61c0-7.19-5.844-13.035-13.034-13.035a1.55 1.55 0 0 1-1.552-1.551A1.55 1.55 0 0 1 143 44.862c8.897 0 16.138 7.241 16.138 16.138a1.55 1.55 0 0 1-1.552 1.552ZM143 77.138c-8.897 0-16.138-7.242-16.138-16.138a1.55 1.55 0 0 1 1.552-1.552A1.55 1.55 0 0 1 129.966 61c0 7.19 5.844 13.034 13.034 13.034a1.55 1.55 0 0 1 1.552 1.552A1.55 1.55 0 0 1 143 77.138ZM143.021 69.286a8.252 8.252 0 0 1-5.855-2.42c-3.228-3.228-3.228-8.483 0-11.721a8.232 8.232 0 0 1 5.855-2.431c2.213 0 4.293.858 5.855 2.43.61.611.61 1.594 0 2.194-.61.61-1.593.61-2.193 0a5.133 5.133 0 0 0-3.662-1.52c-1.387 0-2.69.537-3.662 1.52a5.187 5.187 0 0 0 0 7.324 5.188 5.188 0 0 0 7.324 0c.61-.61 1.593-.61 2.193 0 .6.61.61 1.593 0 2.193a8.256 8.256 0 0 1-5.855 2.42v.011Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ </svg>
+ );
+}
+
+function ServerIllustration({ connected, ...imageProps }: Props) {
+ return connected ? (
+ <svg
+ aria-hidden
+ width="179"
+ height="98"
+ viewBox="0 0 179 98"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ {...imageProps}
+ >
+ <path
+ fillRule="evenodd"
+ clipRule="evenodd"
+ d="M72.005 26h-50.01c-8.836 0-16 7.163-16 16v40c0 8.837 7.164 16 16 16h135c8.837 0 16-7.163 16-16V42c0-8.837-7.163-16-16-16h-57.4l-2 2h59.4c7.732 0 14 6.268 14 14v40c0 7.732-6.268 14-14 14h-135c-7.732 0-14-6.268-14-14V42c0-7.732 6.268-14 14-14h52.01l-2-2Z"
+ fill="var(--echoes-color-icon-success)"
+ />
+ <path
+ d="M66.545 64.34c0 1.08-1.23 1.71-2.1 1.08-.96-.72-1.56-1.86-2.04-2.76-.66-1.26-1.14-2.01-1.74-2.01-.6 0-1.05.75-1.74 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.74-2.01-.63 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.71-2.01-.6 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.48-.87-.84-1.53-1.2-1.83-.3-.24-.51-.57-.51-.96v-.21c0-1.08 1.23-1.71 2.1-1.08.96.72 1.56 1.86 2.04 2.76.66 1.26 1.11 2.01 1.71 2.01.6 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.74-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.48.87.84 1.53 1.23 1.83.3.24.51.57.51.96v.21h-.03ZM46.355 83.18c-4.95 0-9.66-1.71-13.47-4.83-.6-.51-.66-1.44-.12-2.01.51-.54 1.32-.57 1.86-.12 3.42 2.85 7.71 4.32 12.21 4.2 4.5-.12 8.7-1.83 11.97-4.83.54-.48 1.35-.48 1.86 0 .57.54.57 1.47 0 2.01-3.75 3.48-8.61 5.43-13.77 5.58h-.57.03ZM32.045 48.41c-.57-.54-.57-1.47 0-2.01 3.87-3.57 8.79-5.43 13.77-5.55 4.98-.12 9.96 1.47 14.04 4.83.6.51.66 1.44.12 2.01-.51.51-1.32.57-1.86.12-3.51-2.88-7.8-4.29-12.09-4.2-4.29.09-8.67 1.71-12.09 4.83-.54.48-1.35.48-1.86 0l-.03-.03Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M90.316 63.612h5.232v1.632h-5.232V70.5h-1.632v-5.256h-5.232v-1.632h5.232v-5.256h1.632v5.256Z"
+ fill="var(--echoes-color-text-subdued)"
+ />
+ <g clipPath="url(#sqciok)" fill="var(--echoes-logos-colors-brand)">
+ <path d="M155.268 63.54a1.54 1.54 0 0 1-1.539-1.54c0-11.433-9.301-20.733-20.734-20.733a1.54 1.54 0 0 1 0-3.079c13.131 0 23.814 10.682 23.814 23.812 0 .85-.69 1.54-1.54 1.54h-.001ZM132.994 85.812c-13.129 0-23.811-10.681-23.811-23.812a1.54 1.54 0 0 1 3.079 0c0 11.433 9.3 20.733 20.732 20.733a1.54 1.54 0 1 1 0 3.079ZM139.677 63.54c-.85 0-1.54-.69-1.54-1.54a5.147 5.147 0 0 0-5.142-5.141 1.54 1.54 0 0 1 0-3.079c4.534 0 8.222 3.688 8.222 8.22 0 .851-.69 1.54-1.539 1.54h-.001ZM132.994 70.222c-4.532 0-8.221-3.688-8.221-8.222a1.54 1.54 0 0 1 3.079 0 5.147 5.147 0 0 0 5.141 5.142 1.54 1.54 0 1 1 0 3.079h.001Z" />
+ <path d="M147.472 63.54a1.54 1.54 0 0 1-1.539-1.54c0-7.133-5.804-12.937-12.939-12.937a1.54 1.54 0 0 1 0-3.078c8.833 0 16.018 7.185 16.018 16.016 0 .85-.69 1.54-1.54 1.54v-.002ZM132.994 78.017c-8.831 0-16.016-7.185-16.016-16.017a1.54 1.54 0 0 1 3.079 0c0 7.134 5.804 12.938 12.936 12.938a1.54 1.54 0 1 1 0 3.08h.001Z" />
+ </g>
+ <path
+ d="M110.658 4.837a2.861 2.861 0 0 1 0 4.044L87.804 31.736a2.861 2.861 0 0 1-4.044 0L72.332 20.308a2.861 2.861 0 0 1 0-4.044 2.861 2.861 0 0 1 4.044 0l9.41 9.401 20.837-20.828a2.86 2.86 0 0 1 4.044 0h-.009Z"
+ fill="var(--echoes-color-icon-success)"
+ />
+ <defs>
+ <clipPath id="sqciok">
+ <path fill="#fff" transform="translate(108.995 38)" d="M0 0h48v48H0z" />
+ </clipPath>
+ </defs>
+ </svg>
+ ) : (
+ <svg
+ aria-hidden
+ width="179"
+ height="98"
+ viewBox="0 0 179 98"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ {...imageProps}
+ >
+ <path
+ d="M35.076 27H80.745L64.703 97H16C7.716 97 1 90.284 1 82V42c0-8.284 6.716-15 15-15h19.076Z"
+ stroke="var(--echoes-color-border-weak)"
+ strokeWidth="2"
+ />
+ <path
+ d="M56.55 64.34c0 1.08-1.23 1.71-2.1 1.08-.96-.72-1.56-1.86-2.04-2.76-.66-1.26-1.14-2.01-1.74-2.01-.6 0-1.05.75-1.74 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.74-2.01-.63 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.71-2.01-.6 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.48-.87-.84-1.53-1.2-1.83-.3-.24-.51-.57-.51-.96v-.21c0-1.08 1.23-1.71 2.1-1.08.96.72 1.56 1.86 2.04 2.76.66 1.26 1.11 2.01 1.71 2.01.6 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.74-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.48.87.84 1.53 1.23 1.83.3.24.51.57.51.96v.21h-.03ZM36.36 83.18c-4.95 0-9.66-1.71-13.47-4.83-.6-.51-.66-1.44-.12-2.01.51-.54 1.32-.57 1.86-.12 3.42 2.85 7.71 4.32 12.21 4.2 4.5-.12 8.7-1.83 11.97-4.83.54-.48 1.35-.48 1.86 0 .57.54.57 1.47 0 2.01-3.75 3.48-8.61 5.43-13.77 5.58h-.57.03ZM22.05 48.41c-.57-.54-.57-1.47 0-2.01 3.87-3.57 8.79-5.43 13.77-5.55 4.98-.12 9.96 1.47 14.04 4.83.6.51.66 1.44.12 2.01-.51.51-1.32.57-1.86.12-3.51-2.88-7.8-4.29-12.09-4.2-4.29.09-8.67 1.71-12.09 4.83-.54.48-1.35.48-1.86 0l-.03-.03Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M90.32 63.612h5.233v1.632H90.32V70.5h-1.632v-5.256h-5.232v-1.632h5.232v-5.256h1.632v5.256Z"
+ fill="var(--echoes-color-text-subdued)"
+ />
+ <path
+ d="M143.924 97H98.255l16.042-70H163c8.284 0 15 6.716 15 15v40c0 8.284-6.716 15-15 15h-19.076Z"
+ stroke="var(--echoes-color-border-weak)"
+ strokeWidth="2"
+ />
+ <g clipPath="url(#sqcireq)" fill="var(--echoes-logos-colors-brand)">
+ <path d="M165.273 63.54a1.54 1.54 0 0 1-1.539-1.54c0-11.433-9.301-20.733-20.734-20.733a1.54 1.54 0 0 1 0-3.079c13.131 0 23.813 10.682 23.813 23.812 0 .85-.69 1.54-1.539 1.54h-.001ZM142.999 85.812c-13.13 0-23.811-10.681-23.811-23.812a1.54 1.54 0 1 1 3.078 0c0 11.433 9.3 20.733 20.733 20.733a1.54 1.54 0 0 1 0 3.079ZM149.682 63.54a1.54 1.54 0 0 1-1.54-1.54A5.147 5.147 0 0 0 143 56.859a1.54 1.54 0 0 1 0-3.079c4.534 0 8.222 3.688 8.222 8.22 0 .851-.69 1.54-1.54 1.54ZM142.999 70.222c-4.533 0-8.221-3.688-8.221-8.222a1.54 1.54 0 0 1 3.079 0 5.147 5.147 0 0 0 5.141 5.142 1.54 1.54 0 0 1 0 3.079h.001Z" />
+ <path d="M157.477 63.54c-.85 0-1.54-.69-1.54-1.54 0-7.133-5.804-12.937-12.938-12.937a1.54 1.54 0 0 1 0-3.078c8.832 0 16.017 7.185 16.017 16.016 0 .85-.69 1.54-1.539 1.54v-.002ZM142.999 78.017c-8.831 0-16.016-7.185-16.016-16.017a1.54 1.54 0 0 1 3.079 0c0 7.134 5.804 12.938 12.936 12.938a1.54 1.54 0 0 1 0 3.08h.001Z" />
+ </g>
+ <defs>
+ <clipPath id="sqcireq">
+ <path fill="#fff" transform="translate(119 38)" d="M0 0h48v48H0z" />
+ </clipPath>
+ </defs>
+ </svg>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { useAppState } from '../../app/components/app-state/withAppStateContext';
+import { EditionKey } from '../../types/editions';
+
+interface Props {
+ className?: string;
+}
+/**
+ * This component switches between the Community and Server product versions' logo
+ */
+export function SonarQubeIDEPromotionIllustration({ className }: Props) {
+ const { edition } = useAppState();
+
+ return edition === EditionKey.community ? (
+ <svg
+ aria-hidden
+ height="120"
+ viewBox="0 0 82 173"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ className={className}
+ >
+ <path
+ d="M46.924 71H1.255L17.297 1H66c8.284 0 15 6.716 15 15v40c0 8.284-6.716 15-15 15H46.924Z"
+ stroke="var(--echoes-color-border-weak)"
+ strokeWidth="2"
+ />
+ <path
+ d="M68.448 36.552A1.55 1.55 0 0 1 66.897 35c0-11.524-9.373-20.897-20.897-20.897a1.55 1.55 0 0 1-1.552-1.551A1.55 1.55 0 0 1 46 11c13.231 0 24 10.769 24 24a1.55 1.55 0 0 1-1.552 1.552ZM46 59c-13.231 0-24-10.769-24-24a1.55 1.55 0 0 1 1.552-1.552A1.55 1.55 0 0 1 25.103 35c0 11.524 9.373 20.897 20.897 20.897a1.55 1.55 0 0 1 1.552 1.551A1.55 1.55 0 0 1 46 59Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M60.586 36.552A1.55 1.55 0 0 1 59.035 35c0-7.19-5.845-13.035-13.035-13.035a1.55 1.55 0 0 1-1.552-1.551A1.55 1.55 0 0 1 46 18.862c8.897 0 16.138 7.241 16.138 16.138a1.55 1.55 0 0 1-1.552 1.552ZM46 51.138c-8.897 0-16.138-7.241-16.138-16.138a1.55 1.55 0 0 1 1.552-1.552A1.55 1.55 0 0 1 32.965 35c0 7.19 5.845 13.035 13.035 13.035a1.55 1.55 0 0 1 1.552 1.551A1.55 1.55 0 0 1 46 51.138ZM46.02 43.286a8.255 8.255 0 0 1-5.855-2.42c-3.227-3.228-3.227-8.483 0-11.721a8.233 8.233 0 0 1 5.856-2.431 8.19 8.19 0 0 1 5.855 2.43c.61.611.61 1.594 0 2.194-.61.61-1.593.61-2.193 0a5.133 5.133 0 0 0-3.662-1.52c-1.386 0-2.69.537-3.662 1.52a5.189 5.189 0 0 0 0 7.324 5.189 5.189 0 0 0 7.324 0c.61-.61 1.593-.61 2.193 0 .6.61.61 1.593 0 2.193a8.255 8.255 0 0 1-5.855 2.42v.011Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M41.82 88.112h5.233v1.632H41.82V95h-1.632v-5.256h-5.232v-1.632h5.232v-5.256h1.632v5.256Z"
+ fill="var(--echoes-color-text-subdued)"
+ />
+ <path
+ d="M35.076 102H80.745l-16.042 70H16c-8.284 0-15-6.716-15-15v-40c0-8.284 6.716-15 15-15h19.076Z"
+ stroke="var(--echoes-color-border-weak)"
+ strokeWidth="2"
+ />
+ <path
+ d="M56.55 139.34c0 1.08-1.23 1.71-2.1 1.08-.96-.72-1.56-1.86-2.04-2.76-.66-1.26-1.14-2.01-1.74-2.01-.6 0-1.05.75-1.74 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.74-2.01-.63 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.71-2.01-.6 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.48-.87-.84-1.53-1.2-1.83-.3-.24-.51-.57-.51-.96v-.21c0-1.08 1.23-1.71 2.1-1.08.96.72 1.56 1.86 2.04 2.76.66 1.26 1.11 2.01 1.71 2.01.6 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.74-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.48.87.84 1.53 1.23 1.83.3.24.51.57.51.96v.21h-.03ZM36.36 158.18c-4.95 0-9.66-1.71-13.47-4.83-.6-.51-.66-1.44-.12-2.01.51-.54 1.32-.57 1.86-.12 3.42 2.85 7.71 4.32 12.21 4.2 4.5-.12 8.7-1.83 11.97-4.83.54-.48 1.35-.48 1.86 0 .57.54.57 1.47 0 2.01-3.75 3.48-8.61 5.43-13.77 5.58h-.57.03ZM22.05 123.41c-.57-.54-.57-1.47 0-2.01 3.87-3.57 8.79-5.43 13.77-5.55 4.98-.12 9.96 1.47 14.04 4.83.6.51.66 1.44.12 2.01-.51.51-1.32.57-1.86.12-3.51-2.88-7.8-4.29-12.09-4.2-4.29.09-8.67 1.71-12.09 4.83-.54.48-1.35.48-1.86 0l-.03-.03Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ </svg>
+ ) : (
+ <svg
+ aria-hidden
+ height="120"
+ viewBox="0 0 82 173"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ className={className}
+ >
+ <path
+ d="M46.924 71H1.255L17.297 1H66c8.284 0 15 6.716 15 15v40c0 8.284-6.716 15-15 15H46.924Z"
+ stroke="var(--echoes-color-border-weak)"
+ strokeWidth="2"
+ />
+ <g clipPath="url(#sqidepi)" fill="var(--echoes-logos-colors-brand)">
+ <path d="M68.273 37.54c-.85 0-1.54-.69-1.54-1.54 0-11.433-9.3-20.733-20.733-20.733a1.54 1.54 0 0 1 0-3.079c13.13 0 23.813 10.682 23.813 23.812 0 .85-.69 1.54-1.539 1.54ZM46 59.812C32.87 59.812 22.186 49.13 22.186 36a1.54 1.54 0 0 1 3.08 0c0 11.433 9.3 20.733 20.732 20.733a1.54 1.54 0 0 1 0 3.079ZM52.682 37.54c-.85 0-1.54-.69-1.54-1.54A5.147 5.147 0 0 0 46 30.859a1.54 1.54 0 0 1 0-3.079c4.534 0 8.222 3.688 8.222 8.22 0 .851-.69 1.54-1.54 1.54ZM46 44.222c-4.534 0-8.222-3.688-8.222-8.222a1.54 1.54 0 0 1 3.079 0 5.147 5.147 0 0 0 5.141 5.142 1.54 1.54 0 0 1 0 3.079H46Z" />
+ <path d="M60.477 37.54c-.85 0-1.54-.69-1.54-1.54 0-7.133-5.804-12.937-12.938-12.937a1.54 1.54 0 0 1 0-3.078c8.832 0 16.017 7.185 16.017 16.016 0 .85-.69 1.54-1.54 1.54v-.002ZM46 52.017c-8.832 0-16.017-7.185-16.017-16.017a1.54 1.54 0 0 1 3.079 0c0 7.134 5.804 12.938 12.936 12.938a1.54 1.54 0 0 1 0 3.08H46Z" />
+ </g>
+ <path
+ d="M41.82 88.112h5.233v1.632H41.82V95h-1.632v-5.256h-5.232v-1.632h5.232v-5.256h1.632v5.256Z"
+ fill="var(--echoes-color-text-subdued)"
+ />
+ <path
+ d="M35.076 102H80.745l-16.042 70H16c-8.284 0-15-6.716-15-15v-40c0-8.284 6.716-15 15-15h19.076Z"
+ stroke="var(--echoes-color-border-weak)"
+ strokeWidth="2"
+ />
+ <path
+ d="M56.55 139.34c0 1.08-1.23 1.71-2.1 1.08-.96-.72-1.56-1.86-2.04-2.76-.66-1.26-1.14-2.01-1.74-2.01-.6 0-1.05.75-1.74 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.74-2.01-.63 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.71-2.01-.6 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.48-.87-.84-1.53-1.2-1.83-.3-.24-.51-.57-.51-.96v-.21c0-1.08 1.23-1.71 2.1-1.08.96.72 1.56 1.86 2.04 2.76.66 1.26 1.11 2.01 1.71 2.01.6 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.74-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.48.87.84 1.53 1.23 1.83.3.24.51.57.51.96v.21h-.03ZM36.36 158.18c-4.95 0-9.66-1.71-13.47-4.83-.6-.51-.66-1.44-.12-2.01.51-.54 1.32-.57 1.86-.12 3.42 2.85 7.71 4.32 12.21 4.2 4.5-.12 8.7-1.83 11.97-4.83.54-.48 1.35-.48 1.86 0 .57.54.57 1.47 0 2.01-3.75 3.48-8.61 5.43-13.77 5.58h-.57.03ZM22.05 123.41c-.57-.54-.57-1.47 0-2.01 3.87-3.57 8.79-5.43 13.77-5.55 4.98-.12 9.96 1.47 14.04 4.83.6.51.66 1.44.12 2.01-.51.51-1.32.57-1.86.12-3.51-2.88-7.8-4.29-12.09-4.2-4.29.09-8.67 1.71-12.09 4.83-.54.48-1.35.48-1.86 0l-.03-.03Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <defs>
+ <clipPath id="sqidepi">
+ <path fill="#fff" transform="translate(22 12)" d="M0 0h48v48H0z" />
+ </clipPath>
+ </defs>
+ </svg>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { LogoSonarQubeCommunity, LogoSonarQubeServer } from '@sonarsource/echoes-react';
+import * as React from 'react';
+import { useAppState } from '../../app/components/app-state/withAppStateContext';
+import { EditionKey } from '../../types/editions';
+
+type Props = React.ComponentProps<typeof LogoSonarQubeServer>;
+
+/**
+ * This component switches between the Community and Server product versions' logo
+ */
+export function SonarQubeProductLogo(props: Props) {
+ const { edition } = useAppState();
+
+ const OfficialLogo =
+ edition === EditionKey.community ? LogoSonarQubeCommunity : LogoSonarQubeServer;
+
+ return <OfficialLogo {...props} />;
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { mockAppState } from '../../../helpers/testMocks';
+import { renderComponent } from '../../../helpers/testReactTestingUtils';
+import { EditionKey } from '../../../types/editions';
+import { SonarQubeConnectionIllustration } from '../SonarQubeConnectionIllustration';
+
+it.each([
+ [EditionKey.community, true],
+ [EditionKey.community, false],
+ [EditionKey.enterprise, true],
+ [EditionKey.enterprise, false],
+])('should render %s edition (variant connected %s) correctly', (edition, connected) => {
+ const { container } = renderComponent(
+ <SonarQubeConnectionIllustration connected={connected} />,
+ '',
+ { appState: mockAppState({ edition }) },
+ );
+
+ expect(container).toMatchSnapshot();
+});
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render community edition (variant connected false) correctly 1`] = `
+<div>
+ <svg
+ aria-hidden="true"
+ fill="none"
+ height="98"
+ viewBox="0 0 179 98"
+ width="179"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M35.076 27H80.745L64.703 97H16C7.716 97 1 90.284 1 82V42c0-8.284 6.716-15 15-15h19.076Z"
+ stroke="var(--echoes-color-border-weak)"
+ stroke-width="2"
+ />
+ <path
+ d="M56.55 64.34c0 1.08-1.23 1.71-2.1 1.08-.96-.72-1.56-1.86-2.04-2.76-.66-1.26-1.14-2.01-1.74-2.01-.6 0-1.05.75-1.74 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.74-2.01-.63 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.71-2.01-.6 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.48-.87-.84-1.53-1.2-1.83-.3-.24-.51-.57-.51-.96v-.21c0-1.08 1.23-1.71 2.1-1.08.96.72 1.56 1.86 2.04 2.76.66 1.26 1.11 2.01 1.71 2.01.6 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.74-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.48.87.84 1.53 1.23 1.83.3.24.51.57.51.96v.21h-.03ZM36.36 83.18c-4.95 0-9.66-1.71-13.47-4.83-.6-.51-.66-1.44-.12-2.01.51-.54 1.32-.57 1.86-.12 3.42 2.85 7.71 4.32 12.21 4.2 4.5-.12 8.7-1.83 11.97-4.83.54-.48 1.35-.48 1.86 0 .57.54.57 1.47 0 2.01-3.75 3.48-8.61 5.43-13.77 5.58h-.57.03ZM22.05 48.41c-.57-.54-.57-1.47 0-2.01 3.87-3.57 8.79-5.43 13.77-5.55 4.98-.12 9.96 1.47 14.04 4.83.6.51.66 1.44.12 2.01-.51.51-1.32.57-1.86.12-3.51-2.88-7.8-4.29-12.09-4.2-4.29.09-8.67 1.71-12.09 4.83-.54.48-1.35.48-1.86 0l-.03-.03Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M90.32 63.612h5.233v1.632H90.32V70.5h-1.632v-5.256h-5.232v-1.632h5.232v-5.256h1.632v5.256Z"
+ fill="var(--echoes-color-text-subdued)"
+ />
+ <path
+ d="M143.924 97H98.255l16.042-70H163c8.284 0 15 6.716 15 15v40c0 8.284-6.716 15-15 15h-19.076Z"
+ stroke="var(--echoes-color-border-weak)"
+ stroke-width="2"
+ />
+ <path
+ d="M165.448 62.552A1.55 1.55 0 0 1 163.897 61c0-11.524-9.373-20.897-20.897-20.897a1.55 1.55 0 0 1-1.552-1.551A1.55 1.55 0 0 1 143 37c13.231 0 24 10.769 24 24a1.55 1.55 0 0 1-1.552 1.552ZM143 85c-13.231 0-24-10.769-24-24a1.55 1.55 0 0 1 1.552-1.552A1.55 1.55 0 0 1 122.103 61c0 11.524 9.373 20.897 20.897 20.897a1.55 1.55 0 0 1 1.552 1.551A1.55 1.55 0 0 1 143 85Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M157.586 62.552A1.55 1.55 0 0 1 156.034 61c0-7.19-5.844-13.035-13.034-13.035a1.55 1.55 0 0 1-1.552-1.551A1.55 1.55 0 0 1 143 44.862c8.897 0 16.138 7.241 16.138 16.138a1.55 1.55 0 0 1-1.552 1.552ZM143 77.138c-8.897 0-16.138-7.242-16.138-16.138a1.55 1.55 0 0 1 1.552-1.552A1.55 1.55 0 0 1 129.966 61c0 7.19 5.844 13.034 13.034 13.034a1.55 1.55 0 0 1 1.552 1.552A1.55 1.55 0 0 1 143 77.138ZM143.021 69.286a8.252 8.252 0 0 1-5.855-2.42c-3.228-3.228-3.228-8.483 0-11.721a8.232 8.232 0 0 1 5.855-2.431c2.213 0 4.293.858 5.855 2.43.61.611.61 1.594 0 2.194-.61.61-1.593.61-2.193 0a5.133 5.133 0 0 0-3.662-1.52c-1.387 0-2.69.537-3.662 1.52a5.187 5.187 0 0 0 0 7.324 5.188 5.188 0 0 0 7.324 0c.61-.61 1.593-.61 2.193 0 .6.61.61 1.593 0 2.193a8.256 8.256 0 0 1-5.855 2.42v.011Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ </svg>
+</div>
+`;
+
+exports[`should render community edition (variant connected true) correctly 1`] = `
+<div>
+ <svg
+ aria-hidden="true"
+ fill="none"
+ height="98"
+ viewBox="0 0 179 98"
+ width="179"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ clip-rule="evenodd"
+ d="M72.005 26h-50.01c-8.836 0-16 7.163-16 16v40c0 8.837 7.164 16 16 16h135c8.837 0 16-7.163 16-16V42c0-8.837-7.163-16-16-16h-57.4l-2 2h59.4c7.732 0 14 6.268 14 14v40c0 7.732-6.268 14-14 14h-135c-7.732 0-14-6.268-14-14V42c0-7.732 6.268-14 14-14h52.01l-2-2Z"
+ fill="var(--echoes-color-icon-success)"
+ fill-rule="evenodd"
+ />
+ <path
+ d="M66.545 64.34c0 1.08-1.23 1.71-2.1 1.08-.96-.72-1.56-1.86-2.04-2.76-.66-1.26-1.14-2.01-1.74-2.01-.6 0-1.05.75-1.74 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.74-2.01-.63 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.71-2.01-.6 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.48-.87-.84-1.53-1.2-1.83-.3-.24-.51-.57-.51-.96v-.21c0-1.08 1.23-1.71 2.1-1.08.96.72 1.56 1.86 2.04 2.76.66 1.26 1.11 2.01 1.71 2.01.6 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.74-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.48.87.84 1.53 1.23 1.83.3.24.51.57.51.96v.21h-.03ZM46.355 83.18c-4.95 0-9.66-1.71-13.47-4.83-.6-.51-.66-1.44-.12-2.01.51-.54 1.32-.57 1.86-.12 3.42 2.85 7.71 4.32 12.21 4.2 4.5-.12 8.7-1.83 11.97-4.83.54-.48 1.35-.48 1.86 0 .57.54.57 1.47 0 2.01-3.75 3.48-8.61 5.43-13.77 5.58h-.57.03ZM32.045 48.41c-.57-.54-.57-1.47 0-2.01 3.87-3.57 8.79-5.43 13.77-5.55 4.98-.12 9.96 1.47 14.04 4.83.6.51.66 1.44.12 2.01-.51.51-1.32.57-1.86.12-3.51-2.88-7.8-4.29-12.09-4.2-4.29.09-8.67 1.71-12.09 4.83-.54.48-1.35.48-1.86 0l-.03-.03Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M90.316 63.612h5.232v1.632h-5.232V70.5h-1.632v-5.256h-5.232v-1.632h5.232v-5.256h1.632v5.256Z"
+ fill="var(--echoes-color-text-subdued)"
+ />
+ <path
+ d="M155.444 63.552A1.55 1.55 0 0 1 153.892 62c0-11.524-9.373-20.897-20.897-20.897a1.55 1.55 0 0 1-1.551-1.551A1.55 1.55 0 0 1 132.995 38c13.231 0 24 10.769 24 24a1.55 1.55 0 0 1-1.551 1.552ZM132.995 86c-13.231 0-24-10.769-24-24a1.55 1.55 0 0 1 1.552-1.552A1.55 1.55 0 0 1 112.099 62c0 11.524 9.372 20.897 20.896 20.897a1.55 1.55 0 0 1 1.552 1.551A1.55 1.55 0 0 1 132.995 86Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M147.582 63.552A1.55 1.55 0 0 1 146.03 62c0-7.19-5.845-13.035-13.035-13.035a1.55 1.55 0 0 1-1.551-1.551 1.55 1.55 0 0 1 1.551-1.552c8.897 0 16.138 7.241 16.138 16.138a1.55 1.55 0 0 1-1.551 1.552ZM132.995 78.138c-8.896 0-16.138-7.242-16.138-16.138a1.55 1.55 0 0 1 1.552-1.552A1.55 1.55 0 0 1 119.961 62c0 7.19 5.845 13.034 13.034 13.034a1.55 1.55 0 0 1 1.552 1.552 1.55 1.55 0 0 1-1.552 1.552ZM133.016 70.286a8.254 8.254 0 0 1-5.855-2.42c-3.228-3.228-3.228-8.483 0-11.721a8.232 8.232 0 0 1 5.855-2.431 8.19 8.19 0 0 1 5.855 2.43c.61.611.61 1.594 0 2.194-.61.61-1.593.61-2.193 0a5.133 5.133 0 0 0-3.662-1.52c-1.386 0-2.69.537-3.662 1.52a5.189 5.189 0 0 0 0 7.324 5.188 5.188 0 0 0 7.324 0c.61-.61 1.593-.61 2.193 0 .6.61.61 1.593 0 2.193a8.254 8.254 0 0 1-5.855 2.42v.011Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M110.658 4.837a2.861 2.861 0 0 1 0 4.044L87.804 31.736a2.861 2.861 0 0 1-4.044 0L72.332 20.308a2.861 2.861 0 0 1 0-4.044 2.861 2.861 0 0 1 4.044 0l9.41 9.401 20.837-20.828a2.86 2.86 0 0 1 4.044 0h-.009Z"
+ fill="var(--echoes-color-icon-success)"
+ />
+ </svg>
+</div>
+`;
+
+exports[`should render enterprise edition (variant connected false) correctly 1`] = `
+<div>
+ <svg
+ aria-hidden="true"
+ fill="none"
+ height="98"
+ viewBox="0 0 179 98"
+ width="179"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M35.076 27H80.745L64.703 97H16C7.716 97 1 90.284 1 82V42c0-8.284 6.716-15 15-15h19.076Z"
+ stroke="var(--echoes-color-border-weak)"
+ stroke-width="2"
+ />
+ <path
+ d="M56.55 64.34c0 1.08-1.23 1.71-2.1 1.08-.96-.72-1.56-1.86-2.04-2.76-.66-1.26-1.14-2.01-1.74-2.01-.6 0-1.05.75-1.74 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.74-2.01-.63 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.71-2.01-.6 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.48-.87-.84-1.53-1.2-1.83-.3-.24-.51-.57-.51-.96v-.21c0-1.08 1.23-1.71 2.1-1.08.96.72 1.56 1.86 2.04 2.76.66 1.26 1.11 2.01 1.71 2.01.6 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.74-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.48.87.84 1.53 1.23 1.83.3.24.51.57.51.96v.21h-.03ZM36.36 83.18c-4.95 0-9.66-1.71-13.47-4.83-.6-.51-.66-1.44-.12-2.01.51-.54 1.32-.57 1.86-.12 3.42 2.85 7.71 4.32 12.21 4.2 4.5-.12 8.7-1.83 11.97-4.83.54-.48 1.35-.48 1.86 0 .57.54.57 1.47 0 2.01-3.75 3.48-8.61 5.43-13.77 5.58h-.57.03ZM22.05 48.41c-.57-.54-.57-1.47 0-2.01 3.87-3.57 8.79-5.43 13.77-5.55 4.98-.12 9.96 1.47 14.04 4.83.6.51.66 1.44.12 2.01-.51.51-1.32.57-1.86.12-3.51-2.88-7.8-4.29-12.09-4.2-4.29.09-8.67 1.71-12.09 4.83-.54.48-1.35.48-1.86 0l-.03-.03Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M90.32 63.612h5.233v1.632H90.32V70.5h-1.632v-5.256h-5.232v-1.632h5.232v-5.256h1.632v5.256Z"
+ fill="var(--echoes-color-text-subdued)"
+ />
+ <path
+ d="M143.924 97H98.255l16.042-70H163c8.284 0 15 6.716 15 15v40c0 8.284-6.716 15-15 15h-19.076Z"
+ stroke="var(--echoes-color-border-weak)"
+ stroke-width="2"
+ />
+ <g
+ clip-path="url(#sqcireq)"
+ fill="var(--echoes-logos-colors-brand)"
+ >
+ <path
+ d="M165.273 63.54a1.54 1.54 0 0 1-1.539-1.54c0-11.433-9.301-20.733-20.734-20.733a1.54 1.54 0 0 1 0-3.079c13.131 0 23.813 10.682 23.813 23.812 0 .85-.69 1.54-1.539 1.54h-.001ZM142.999 85.812c-13.13 0-23.811-10.681-23.811-23.812a1.54 1.54 0 1 1 3.078 0c0 11.433 9.3 20.733 20.733 20.733a1.54 1.54 0 0 1 0 3.079ZM149.682 63.54a1.54 1.54 0 0 1-1.54-1.54A5.147 5.147 0 0 0 143 56.859a1.54 1.54 0 0 1 0-3.079c4.534 0 8.222 3.688 8.222 8.22 0 .851-.69 1.54-1.54 1.54ZM142.999 70.222c-4.533 0-8.221-3.688-8.221-8.222a1.54 1.54 0 0 1 3.079 0 5.147 5.147 0 0 0 5.141 5.142 1.54 1.54 0 0 1 0 3.079h.001Z"
+ />
+ <path
+ d="M157.477 63.54c-.85 0-1.54-.69-1.54-1.54 0-7.133-5.804-12.937-12.938-12.937a1.54 1.54 0 0 1 0-3.078c8.832 0 16.017 7.185 16.017 16.016 0 .85-.69 1.54-1.539 1.54v-.002ZM142.999 78.017c-8.831 0-16.016-7.185-16.016-16.017a1.54 1.54 0 0 1 3.079 0c0 7.134 5.804 12.938 12.936 12.938a1.54 1.54 0 0 1 0 3.08h.001Z"
+ />
+ </g>
+ <defs>
+ <clippath
+ id="sqcireq"
+ >
+ <path
+ d="M0 0h48v48H0z"
+ fill="#fff"
+ transform="translate(119 38)"
+ />
+ </clippath>
+ </defs>
+ </svg>
+</div>
+`;
+
+exports[`should render enterprise edition (variant connected true) correctly 1`] = `
+<div>
+ <svg
+ aria-hidden="true"
+ fill="none"
+ height="98"
+ viewBox="0 0 179 98"
+ width="179"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ clip-rule="evenodd"
+ d="M72.005 26h-50.01c-8.836 0-16 7.163-16 16v40c0 8.837 7.164 16 16 16h135c8.837 0 16-7.163 16-16V42c0-8.837-7.163-16-16-16h-57.4l-2 2h59.4c7.732 0 14 6.268 14 14v40c0 7.732-6.268 14-14 14h-135c-7.732 0-14-6.268-14-14V42c0-7.732 6.268-14 14-14h52.01l-2-2Z"
+ fill="var(--echoes-color-icon-success)"
+ fill-rule="evenodd"
+ />
+ <path
+ d="M66.545 64.34c0 1.08-1.23 1.71-2.1 1.08-.96-.72-1.56-1.86-2.04-2.76-.66-1.26-1.14-2.01-1.74-2.01-.6 0-1.05.75-1.74 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.74-2.01-.63 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.66-1.26-1.11-2.01-1.71-2.01-.6 0-1.05.75-1.71 2.01-.78 1.47-1.86 3.48-4.14 3.48-2.28 0-3.36-2.01-4.14-3.48-.48-.87-.84-1.53-1.2-1.83-.3-.24-.51-.57-.51-.96v-.21c0-1.08 1.23-1.71 2.1-1.08.96.72 1.56 1.86 2.04 2.76.66 1.26 1.11 2.01 1.71 2.01.6 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.71-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.66 1.26 1.11 2.01 1.74 2.01.63 0 1.05-.75 1.74-2.01.78-1.47 1.86-3.48 4.14-3.48 2.28 0 3.36 2.01 4.14 3.48.48.87.84 1.53 1.23 1.83.3.24.51.57.51.96v.21h-.03ZM46.355 83.18c-4.95 0-9.66-1.71-13.47-4.83-.6-.51-.66-1.44-.12-2.01.51-.54 1.32-.57 1.86-.12 3.42 2.85 7.71 4.32 12.21 4.2 4.5-.12 8.7-1.83 11.97-4.83.54-.48 1.35-.48 1.86 0 .57.54.57 1.47 0 2.01-3.75 3.48-8.61 5.43-13.77 5.58h-.57.03ZM32.045 48.41c-.57-.54-.57-1.47 0-2.01 3.87-3.57 8.79-5.43 13.77-5.55 4.98-.12 9.96 1.47 14.04 4.83.6.51.66 1.44.12 2.01-.51.51-1.32.57-1.86.12-3.51-2.88-7.8-4.29-12.09-4.2-4.29.09-8.67 1.71-12.09 4.83-.54.48-1.35.48-1.86 0l-.03-.03Z"
+ fill="var(--echoes-logos-colors-brand)"
+ />
+ <path
+ d="M90.316 63.612h5.232v1.632h-5.232V70.5h-1.632v-5.256h-5.232v-1.632h5.232v-5.256h1.632v5.256Z"
+ fill="var(--echoes-color-text-subdued)"
+ />
+ <g
+ clip-path="url(#sqciok)"
+ fill="var(--echoes-logos-colors-brand)"
+ >
+ <path
+ d="M155.268 63.54a1.54 1.54 0 0 1-1.539-1.54c0-11.433-9.301-20.733-20.734-20.733a1.54 1.54 0 0 1 0-3.079c13.131 0 23.814 10.682 23.814 23.812 0 .85-.69 1.54-1.54 1.54h-.001ZM132.994 85.812c-13.129 0-23.811-10.681-23.811-23.812a1.54 1.54 0 0 1 3.079 0c0 11.433 9.3 20.733 20.732 20.733a1.54 1.54 0 1 1 0 3.079ZM139.677 63.54c-.85 0-1.54-.69-1.54-1.54a5.147 5.147 0 0 0-5.142-5.141 1.54 1.54 0 0 1 0-3.079c4.534 0 8.222 3.688 8.222 8.22 0 .851-.69 1.54-1.539 1.54h-.001ZM132.994 70.222c-4.532 0-8.221-3.688-8.221-8.222a1.54 1.54 0 0 1 3.079 0 5.147 5.147 0 0 0 5.141 5.142 1.54 1.54 0 1 1 0 3.079h.001Z"
+ />
+ <path
+ d="M147.472 63.54a1.54 1.54 0 0 1-1.539-1.54c0-7.133-5.804-12.937-12.939-12.937a1.54 1.54 0 0 1 0-3.078c8.833 0 16.018 7.185 16.018 16.016 0 .85-.69 1.54-1.54 1.54v-.002ZM132.994 78.017c-8.831 0-16.016-7.185-16.016-16.017a1.54 1.54 0 0 1 3.079 0c0 7.134 5.804 12.938 12.936 12.938a1.54 1.54 0 1 1 0 3.08h.001Z"
+ />
+ </g>
+ <path
+ d="M110.658 4.837a2.861 2.861 0 0 1 0 4.044L87.804 31.736a2.861 2.861 0 0 1-4.044 0L72.332 20.308a2.861 2.861 0 0 1 0-4.044 2.861 2.861 0 0 1 4.044 0l9.41 9.401 20.837-20.828a2.86 2.86 0 0 1 4.044 0h-.009Z"
+ fill="var(--echoes-color-icon-success)"
+ />
+ <defs>
+ <clippath
+ id="sqciok"
+ >
+ <path
+ d="M0 0h48v48H0z"
+ fill="#fff"
+ transform="translate(108.995 38)"
+ />
+ </clippath>
+ </defs>
+ </svg>
+</div>
+`;
import { DropdownMenu } from '@sonarsource/echoes-react';
import * as React from 'react';
-import { Image } from '~sonar-aligned/components/common/Image';
import { DocLink } from '../../helpers/doc-links';
import { translate } from '../../helpers/l10n';
import { SuggestionLink } from '../../types/types';
import { DocItemLink } from './DocItemLink';
import { SuggestionsContext } from './SuggestionsContext';
-function IconLink({
- icon = 'embed-doc/sq-icon.svg',
- link,
- text,
-}: {
- icon?: string;
- link: string;
- text: string;
-}) {
- return (
- <DropdownMenu.ItemLink
- prefix={
- <Image
- alt={text}
- aria-hidden
- className="sw-mr-2"
- height="18"
- src={`/images/${icon}`}
- width="18"
- />
- }
- to={link}
- >
- {text}
- </DropdownMenu.ItemLink>
- );
-}
-
function Suggestions({ suggestions }: Readonly<{ suggestions: SuggestionLink[] }>) {
return (
<>
<DropdownMenu.GroupLabel>{translate('docs.stay_connected')}</DropdownMenu.GroupLabel>
- <IconLink
- link="https://www.sonarsource.com/products/sonarqube/whats-new/?referrer=sonarqube"
- text={translate('docs.news')}
- />
-
- <IconLink
- link="https://www.sonarsource.com/products/sonarqube/roadmap/?referrer=sonarqube"
- text={translate('docs.roadmap')}
- />
-
- <IconLink
- icon="embed-doc/x-icon-black.svg"
- link="https://twitter.com/SonarQube"
- text="X @SonarQube"
- />
+ <DropdownMenu.ItemLink to="https://www.sonarsource.com/products/sonarqube/whats-new/?referrer=sonarqube">
+ {translate('docs.news')}
+ </DropdownMenu.ItemLink>
+
+ <DropdownMenu.ItemLink to="https://www.sonarsource.com/products/sonarqube/roadmap/?referrer=sonarqube">
+ {translate('docs.roadmap')}
+ </DropdownMenu.ItemLink>
+
+ <DropdownMenu.ItemLink to="https://twitter.com/SonarQube">X @SonarQube</DropdownMenu.ItemLink>
</>
);
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { ComponentProps } from 'react';
+import { FormattedMessage } from 'react-intl';
+
+type Props = ComponentProps<typeof FormattedMessage>;
+
+export function TranslatedMessage(props: Props) {
+ return <FormattedMessage {...props} />;
+}
import { getInstanceVersionNumber } from '../../helpers/strings';
import { isCurrentVersionEOLActive } from '../../helpers/system';
import { useSystemUpgrades } from '../../queries/system';
+import { EditionKey } from '../../types/editions';
export default function AppVersionStatus() {
const { data } = useSystemUpgrades();
- const { version, versionEOL } = useAppState();
+ const { edition, version, versionEOL } = useAppState();
const isActiveVersion = useMemo(() => {
if (data?.installedVersionActive !== undefined) {
{ id: `footer.version` },
{
version: getInstanceVersionNumber(version),
- status: (
+ status: edition && edition !== EditionKey.community && (
<LinkStandalone className="sw-ml-1" highlight={LinkHighlight.CurrentColor} to={docUrl}>
<FormattedMessage
id={`footer.version.status.${isActiveVersion ? 'active' : 'inactive'}`}
almBinding,
projectBinding,
)}/admin/addon/admin/pipelines/repository-variables`}
- target="_blank"
+ shouldOpenInNewTab
>
{translate('onboarding.tutorial.with.bitbucket_pipelines.variables.intro.link')}
</LinkStandalone>
height={20}
src="/images/alm/github.svg"
/>
- <LinkStandalone target="_blank" to={link}>
+ <LinkStandalone shouldOpenInNewTab to={link}>
sonarsource-cfamily-examples
</LinkStandalone>
</div>
almBinding && projectBinding ? (
<LinkStandalone
to={`${buildGithubLink(almBinding, projectBinding)}/settings/secrets`}
- target="_blank"
+ shouldOpenInNewTab
>
{translate('onboarding.tutorial.with.github_action.secret.intro.link')}
</LinkStandalone>
expiresInSelect: byRole('combobox', { name: '' }),
tokenValue: byText('generatedtoken2'),
linkToRepo: byRole('link', {
- name: `onboarding.tutorial.with.${CI_TRANSLATE_MAP[ci]}.${
- ci === TutorialModes.GitHubActions ? 'secret' : 'variables'
- }.intro.link`,
+ name: new RegExp(
+ `onboarding.tutorial.with.${CI_TRANSLATE_MAP[ci]}.${
+ ci === TutorialModes.GitHubActions ? 'secret' : 'variables'
+ }.intro.link`,
+ ),
}),
allSetSentence: byText('onboarding.tutorial.ci_outro.done'),
};
<Link
className="sw-ml-2"
to="https://www.sonarsource.com/products/sonarqube/downloads/?referrer=sonarqube"
- target="_blank"
+ shouldOpenInNewTab
>
{translate('learn_more')}
</Link>
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { IntlShape } from 'react-intl';
import { Dict } from '../../types/types';
import {
getLocalizedCategoryMetricName,
translate,
translateWithParameters,
} from '../l10n';
-import { getMessages } from '../l10nBundle';
+import { getIntl, getMessages } from '../l10nBundle';
const MSG = 'my_message';
jest.unmock('../l10n');
-jest.mock('../l10nBundle', () => ({
- getMessages: jest.fn().mockReturnValue({}),
-}));
+jest.mock('../l10nBundle', () => {
+ const bundle = jest.requireActual('../l10nBundle');
+ return {
+ ...bundle,
+ getIntl: jest.fn().mockReturnValue({ formatMessage: jest.fn(({ id }) => `${id}`) }),
+ getMessages: jest.fn().mockReturnValue({}),
+ };
+});
+
+const resetMessages = (messages: Dict<string>) => {
+ jest.mocked(getMessages).mockReturnValue(messages);
-const resetMessages = (messages: Dict<string>) =>
- (getMessages as jest.Mock).mockReturnValue(messages);
+ jest.mocked(getIntl).mockReturnValue({
+ formatMessage: jest.fn(({ id }) => {
+ return id ? (messages[id] ?? id) : `${id}`;
+ }),
+ } as unknown as IntlShape);
+};
beforeEach(() => {
resetMessages({});
expect(translate('random', 'key')).toBe('random.key');
expect(translate('composite.random', 'key')).toBe('composite.random.key');
});
+
+ it('should fall back to the old system when intl is undefined', () => {
+ jest.mocked(getIntl).mockReturnValueOnce(undefined as unknown as IntlShape);
+ resetMessages({ exists: 'this exists' });
+
+ expect(translate('exists')).toBe('this exists');
+ });
});
describe('translateWithParameters', () => {
import { fetchL10nBundle } from '../../api/l10n';
import { loadL10nBundle } from '../l10nBundle';
+import { mockAppState } from '../testMocks';
beforeEach(() => {
jest.clearAllMocks();
}),
}));
+const APP_STATE = mockAppState({});
+
describe('#loadL10nBundle', () => {
it('should fetch bundle without any timestamp', async () => {
- await loadL10nBundle();
+ await loadL10nBundle(APP_STATE);
expect(fetchL10nBundle).toHaveBeenCalledWith({ locale: 'de', ts: undefined });
});
const cachedBundle = { timestamp: 'timestamp', locale: 'fr', messages: { cache: 'cache' } };
(window as unknown as any).sonarQubeL10nBundle = cachedBundle;
- await loadL10nBundle();
+ await loadL10nBundle(APP_STATE);
expect(fetchL10nBundle).toHaveBeenCalledWith({ locale: 'de', ts: undefined });
});
const cachedBundle = { timestamp: 'timestamp', locale: 'de', messages: { cache: 'cache' } };
(window as unknown as any).sonarQubeL10nBundle = cachedBundle;
- await loadL10nBundle();
+ await loadL10nBundle(APP_STATE);
expect(fetchL10nBundle).toHaveBeenCalledWith({ locale: 'de', ts: cachedBundle.timestamp });
});
(fetchL10nBundle as jest.Mock).mockRejectedValueOnce({ status: 304 });
(window as unknown as any).sonarQubeL10nBundle = cachedBundle;
- const bundle = await loadL10nBundle();
+ const bundle = await loadL10nBundle(APP_STATE);
expect(bundle).toEqual(
expect.objectContaining({ locale: cachedBundle.locale, messages: cachedBundle.messages }),
import { mockQualityGateStatusCondition } from '../mocks/quality-gates';
import { mockMeasure, mockMeasureEnhanced, mockMetric } from '../testMocks';
+jest.mock('../l10nBundle', () => {
+ const bundle = jest.requireActual('../l10nBundle');
+ return {
+ ...bundle,
+ getIntl: () => ({ formatMessage: jest.fn(({ id }) => `${id}`) }),
+ };
+});
+
describe('enhanceConditionWithMeasure', () => {
it('should correctly map enhance conditions with measure data', () => {
const measures = [
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { getMessages } from './l10nBundle';
+import { getIntl, getMessages } from './l10nBundle';
export function hasMessage(...keys: string[]): boolean {
const messageKey = keys.join('.');
console.error(`No message for: ${messageKey}`);
}
- return l10nMessages[messageKey] || messageKey;
+ const intl = getIntl();
+ // fallback to old if in extension
+ return intl ? intl.formatMessage({ id: messageKey }) : l10nMessages[messageKey];
}
+/**
+ * @param messageKey @deprecated Use react-intl instead
+ */
export function translateWithParameters(
messageKey: string,
...parameters: Array<string | number>
import { IntlShape, createIntl, createIntlCache } from 'react-intl';
import { fetchL10nBundle } from '../api/l10n';
+import { AppState } from '../types/appstate';
+import { EditionKey } from '../types/editions';
import { L10nBundle, L10nBundleRequestParams } from '../types/l10nBundle';
import { Dict } from '../types/types';
import { toISO8601WithOffsetString } from './dates';
+import { isDefined } from './types';
const DEFAULT_LOCALE = 'en';
const DEFAULT_MESSAGES: Dict<string> = {
return getL10nBundleFromCache();
}
-export async function loadL10nBundle() {
+export async function loadL10nBundle(appState: AppState | undefined) {
const browserLocale = getPreferredLanguage();
const cachedBundle = getL10nBundleFromCache();
{
locale: effectiveLocale,
messages,
+
+ /*
+ * This sets a default value for translations, so devs do not need to pass the {productName}
+ * value to every instance of FormattedMessage.
+ * It is a bit of a hack, abusing this config item that is normally for tag replacement only,
+ * hence the ts-expect-error tag
+ */
+ defaultRichTextElements: {
+ // @ts-expect-error
+ productName: getProductName(appState),
+ },
},
cache,
);
function persistL10nBundleInCache(bundle: L10nBundle) {
(window as unknown as any).sonarQubeL10nBundle = bundle;
}
+
+function getProductName(appState?: AppState) {
+ if (isDefined(appState?.edition)) {
+ return appState?.edition === EditionKey.community
+ ? 'SonarQube Community Build'
+ : 'SonarQube Server';
+ }
+
+ return 'SonarQube';
+}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { IntlShape } from 'react-intl';
import { MetricType } from '~sonar-aligned/types/metrics';
-import { getMessages } from '../../../helpers/l10nBundle';
+import { getIntl, getMessages } from '../../../helpers/l10nBundle';
import { Dict } from '../../../types/types';
import { formatMeasure } from '../measures';
jest.mock('../../../helpers/l10nBundle', () => ({
getCurrentLocale: jest.fn().mockReturnValue('us'),
getMessages: jest.fn().mockReturnValue({}),
+ getIntl: jest.fn().mockReturnValue({ formatMessage: jest.fn(({ id }) => `${id}`) }),
}));
-const resetMessages = (messages: Dict<string>) =>
+const resetMessages = (messages: Dict<string>) => {
jest.mocked(getMessages).mockReturnValue(messages);
+ jest.mocked(getIntl).mockReturnValue({
+ formatMessage: jest.fn(({ id }) => {
+ return id ? (messages[id] ?? id) : `${id}`;
+ }),
+ } as unknown as IntlShape);
+};
+
beforeAll(() => {
resetMessages({
'work_duration.x_days': '{0}d',
languageName: node
linkType: hard
-"@babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7":
+"@babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7":
version: 7.25.6
resolution: "@babel/runtime@npm:7.25.6"
dependencies:
languageName: node
linkType: hard
+"@babel/runtime@npm:^7.20.13":
+ version: 7.26.0
+ resolution: "@babel/runtime@npm:7.26.0"
+ dependencies:
+ regenerator-runtime: "npm:^0.14.0"
+ checksum: 10/9f4ea1c1d566c497c052d505587554e782e021e6ccd302c2ad7ae8291c8e16e3f19d4a7726fb64469e057779ea2081c28b7dbefec6d813a22f08a35712c0f699
+ languageName: node
+ linkType: hard
+
"@babel/template@npm:^7.12.13, @babel/template@npm:^7.25.7":
version: 7.25.7
resolution: "@babel/template@npm:7.25.7"
languageName: node
linkType: hard
-"@floating-ui/dom@npm:^1.0.0, @floating-ui/dom@npm:^1.0.1":
+"@floating-ui/dom@npm:^1.0.0":
+ version: 1.6.12
+ resolution: "@floating-ui/dom@npm:1.6.12"
+ dependencies:
+ "@floating-ui/core": "npm:^1.6.0"
+ "@floating-ui/utils": "npm:^0.2.8"
+ checksum: 10/5c8e5fdcd3843140a606ab6dc6c12ad740f44e66b898966ef877393faaede0bbe14586e1049e2c2f08856437da8847e884a2762e78275fefa65a5a9cd71e580d
+ languageName: node
+ linkType: hard
+
+"@floating-ui/dom@npm:^1.0.1":
version: 1.6.10
resolution: "@floating-ui/dom@npm:1.6.10"
dependencies:
languageName: node
linkType: hard
-"@floating-ui/react-dom@npm:^2.0.0, @floating-ui/react-dom@npm:^2.1.1":
- version: 2.1.1
- resolution: "@floating-ui/react-dom@npm:2.1.1"
+"@floating-ui/react-dom@npm:^2.0.0, @floating-ui/react-dom@npm:^2.1.2":
+ version: 2.1.2
+ resolution: "@floating-ui/react-dom@npm:2.1.2"
dependencies:
"@floating-ui/dom": "npm:^1.0.0"
peerDependencies:
react: ">=16.8.0"
react-dom: ">=16.8.0"
- checksum: 10/cafabfb5dd0b25547863520b3bcf6faee7f087d0c3187a8779910a6838d496bf494f237bf1fe883bbfae1a7fcc399611ae52377b696065d8118bd7c1b9c0d253
+ checksum: 10/2a67dc8499674e42ff32c7246bded185bb0fdd492150067caf9568569557ac4756a67787421d8604b0f241e5337de10762aee270d9aeef106d078a0ff13596c4
languageName: node
linkType: hard
"@floating-ui/react@npm:^0.26.9":
- version: 0.26.23
- resolution: "@floating-ui/react@npm:0.26.23"
+ version: 0.26.27
+ resolution: "@floating-ui/react@npm:0.26.27"
dependencies:
- "@floating-ui/react-dom": "npm:^2.1.1"
- "@floating-ui/utils": "npm:^0.2.7"
+ "@floating-ui/react-dom": "npm:^2.1.2"
+ "@floating-ui/utils": "npm:^0.2.8"
tabbable: "npm:^6.0.0"
peerDependencies:
react: ">=16.8.0"
react-dom: ">=16.8.0"
- checksum: 10/a2ffeb0bae72cac9e6583d9651e75e94c261a9e78ca4a5e862b7d33f2c19ae014cbe272627a0a0a5a2b526280efab17ec687d32ba02f6ce4e924bec562ae06ab
+ checksum: 10/ab6d05e5cc2c29272a6830c06dff07e8330f2b90234674f2d74ed8084659ebe3ac9472770a5f0e76007dd2ae89f9da75189d188437aea4b8ac2789afc21bb6b2
languageName: node
linkType: hard
languageName: node
linkType: hard
+"@floating-ui/utils@npm:^0.2.8":
+ version: 0.2.8
+ resolution: "@floating-ui/utils@npm:0.2.8"
+ checksum: 10/3e3ea3b2de06badc4baebdf358b3dbd77ccd9474a257a6ef237277895943db2acbae756477ec64de65a2a1436d94aea3107129a1feeef6370675bf2b161c1abc
+ languageName: node
+ linkType: hard
+
"@formatjs/ecma402-abstract@npm:2.0.0":
version: 2.0.0
resolution: "@formatjs/ecma402-abstract@npm:2.0.0"
languageName: node
linkType: hard
-"@mantine/core@patch:@mantine/core@7.12.2#./config/patches/@mantine-core-npm-7.12.2-7aad505c0f.patch::locator=%40sonarsource%2Fechoes-react%40npm%3A0.9.0":
+"@mantine/core@patch:@mantine/core@7.12.2#./config/patches/@mantine-core-npm-7.12.2-7aad505c0f.patch::locator=%40sonarsource%2Fechoes-react%40npm%3A0.10.1":
version: 7.12.2
- resolution: "@mantine/core@patch:@mantine/core@npm%3A7.12.2#./config/patches/@mantine-core-npm-7.12.2-7aad505c0f.patch::version=7.12.2&hash=cab555&locator=%40sonarsource%2Fechoes-react%40npm%3A0.9.0"
+ resolution: "@mantine/core@patch:@mantine/core@npm%3A7.12.2#./config/patches/@mantine-core-npm-7.12.2-7aad505c0f.patch::version=7.12.2&hash=cab555&locator=%40sonarsource%2Fechoes-react%40npm%3A0.10.1"
dependencies:
"@floating-ui/react": "npm:^0.26.9"
clsx: "npm:^2.1.1"
languageName: node
linkType: hard
-"@sonarsource/echoes-react@npm:0.9.0":
- version: 0.9.0
- resolution: "@sonarsource/echoes-react@npm:0.9.0"
+"@sonarsource/echoes-react@npm:0.10.1":
+ version: 0.10.1
+ resolution: "@sonarsource/echoes-react@npm:0.10.1"
dependencies:
"@mantine/core": "patch:@mantine/core@7.12.2#./config/patches/@mantine-core-npm-7.12.2-7aad505c0f.patch"
"@mantine/hooks": "npm:7.12.2"
react-dom: ^18.0.0
react-intl: ^6.0.0
react-router-dom: ^6.0.0
- checksum: 10/d67803889b7a1954fb5759954086f85b95a33b7e154863cddea6a4b134d30c66b59c864d3ec93b382035a9564d682c22452f5a5b9f40c83fd1cc642584af957a
+ checksum: 10/326e46fcf08468afbf9c6dc7b8f07d09d18d1634a63fd5f0335966e0cf6162fdee94f03e9e86cbb2eef6331afee284cc14d15aaa1e749078251fcd1733ea41e4
languageName: node
linkType: hard
"@primer/octicons-react": "npm:19.11.0"
"@react-spring/rafz": "npm:9.7.4"
"@react-spring/web": "npm:9.7.4"
- "@sonarsource/echoes-react": "npm:0.9.0"
+ "@sonarsource/echoes-react": "npm:0.10.1"
"@tanstack/react-query": "npm:5.56.2"
"@testing-library/dom": "npm:10.4.0"
"@testing-library/jest-dom": "npm:6.5.0"
linkType: hard
"tslib@npm:^2.1.0":
- version: 2.6.3
- resolution: "tslib@npm:2.6.3"
- checksum: 10/52109bb681f8133a2e58142f11a50e05476de4f075ca906d13b596ae5f7f12d30c482feb0bff167ae01cfc84c5803e575a307d47938999246f5a49d174fc558c
+ version: 2.8.1
+ resolution: "tslib@npm:2.8.1"
+ checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7
languageName: node
linkType: hard
# Admin notification
#
#------------------------------------------------------------------------------
-admin_notification.update.new_patch=There’s an update available for your SonarQube instance. Please update to make sure you benefit from the latest security and bug fixes.
-admin_notification.update.new_version=There’s a new version of SonarQube available. Upgrade to the latest active version to access new updates and features.
-admin_notification.update.current_version_inactive=You’re running a version of SonarQube that is no longer active. Please upgrade to an active version immediately.
+admin_notification.update.new_patch=There’s an update available for your {productName} instance. Please update to make sure you benefit from the latest security and bug fixes.
+admin_notification.update.new_version=There’s a new version of {productName} available. Upgrade to the latest active version to access new updates and features.
+admin_notification.update.current_version_inactive=You’re running a version of {productName} that is no longer active. Please upgrade to an active version immediately.
#------------------------------------------------------------------------------
#
event.category.VERSION=Version
event.category.QUALITY_GATE=Quality Gate
event.category.QUALITY_PROFILE=Quality Profile
-event.category.SQ_UPGRADE=SonarQube upgrade
+event.category.SQ_UPGRADE={productName} upgrade
event.category.DEFINITION_CHANGE=Definition Change
event.category.ISSUE_DETECTION=Issue Detection
event.category.OTHER=Other
event.definition_change.branch_removed={project} {branch} removed
event.definition_change.branch_replaced={project} {oldBranch} replaced with {newBranch}
event.failed_conditions=Failed Conditions:
-event.sqUpgrade=First analysis since upgrading to SonarQube {sqVersion}
+event.sqUpgrade=First analysis since upgrading to {productName} {sqVersion}
#------------------------------------------------------------------------------
#
layout.settings.SVW=Portfolio Settings
layout.security_reports=Security Reports
layout.nav.home_logo_alt=Logo, link to homepage
-layout.nav.home_sonarqube_logo_alt=SonarQube logo, link to homepage
+layout.nav.home_sonarqube_logo_alt={productName} logo, link to homepage
layout.must_be_configured=This will be available once your project is configured and analyzed.
layout.all_project_must_be_accessible=You need access to all projects within this {0} to access it.
baseline.specific_analysis=Specific analysis
baseline.specific_analysis.description=Choose an analysis as the baseline for the new code.
-baseline.specific_analysis.compliance_warning.title=Choosing the "Specific analysis" option from the SonarQube UI is not compliant with the Clean as You Code methodology
+baseline.specific_analysis.compliance_warning.title=Choosing the "Specific analysis" option from the {productName} UI is not compliant with the Clean as You Code methodology
baseline.specific_analysis.compliance_warning.explanation=It has been deprecated. The option remains available through the Web API.
baseline.specific_analysis.compliance_warning.link=Defining New Code
baseline.reference_branch=Reference branch
baseline.next_analysis_notice=Changes will take effect after the next analysis
baseline.reference_branch.choose=Choose a branch
-baseline.reference_branch.does_not_exist=Branch {0} could not be found in SonarQube.
+baseline.reference_branch.does_not_exist=Branch {branch} could not be found in {productName}.
baseline.reference_branch.cannot_be_itself=A branch cannot be used as its own reference branch
baseline.reference_branch.invalid_branch_setting=Branch {0} cannot use itself as a reference. Define a specific setting instead of using the project-level setting.
baseline.edit_branch_setting=Edit the branch's setting
#
#------------------------------------------------------------------------------
-page_title.template.default=%s - SonarQube
-page_title.template.with_category=%s - {0} - SonarQube
-page_title.template.with_instance={0} - %s - SonarQube
+page_title.template.default=%s - {productName}
+page_title.template.with_category=%s - {page} - {productName}
+page_title.template.with_instance={project} - %s - {productName}
overview.page=Overview
code.page=Code
permissions.page=Permissions
hotspots.comment.open=Comment
hotspots.comment.submit=Comment
hotspots.open_in_ide.success=Success. Switch to your IDE to see the security hotspot.
-hotspots.open_in_ide.failure=Unable to connect to your IDE to open the Security Hotspot. Please make sure you're running the latest version of SonarLint.
+hotspots.open_in_ide.failure=Unable to connect to your IDE to open the Security Hotspot. Please make sure you're running the latest version of SonarQube for IDE.
hotspots.assignee.select_user=Select a user...
hotspots.assignee.change_user=Click to change assignee
issue.assign.to_me=to me
issue.quick_fix=Quick fix
issue.quick_fix_available_with_sonarlint=Quick fix available in {link}
-issue.quick_fix_available_with_sonarlint_no_link=Quick fix available in SonarLint
+issue.quick_fix_available_with_sonarlint_no_link=Quick fix available in SonarQube for IDE
issue.comment.add_comment=Add Comment
issue.comment.add_comment.cancel=Cancel adding comment
issue.comment.enter_comment=Enter Comment
settings._default=(default)
settings.boolean.true=True
settings.boolean.false=False
-settings.default.no_value=<no value>
-settings.default.complex_value=<complex value>
-settings.default.password=<password>
+settings.default.no_value='<no value>'
+settings.default.complex_value='<complex value>'
+settings.default.password='<password>'
settings.reset_confirm.title=Reset Setting
settings.reset_confirm.description=Are you sure that you want to reset this setting?
settings.definition.reset=Reset "{0}" to default values
settings.projects.change_visibility_form.submit=Change Default Visibility
settings.almintegration.title=DevOps Platform Integrations
-settings.almintegration.description=DevOps Platform integrations allow SonarQube to interact with your DevOps Platform. This enables things like authentication, or providing analysis details and a Quality Gate to your Pull Requests directly in your DevOps Platform's interface.
-settings.almintegration.empty.server_base_url=You need to set the Server Base URL in General > {serverBaseUrl} to have correct links from the DevOps Platform to your SonarQube instance.
+settings.almintegration.description=DevOps Platform integrations allow {productName} to interact with your DevOps Platform. This enables things like authentication, or providing analysis details and a Quality Gate to your Pull Requests directly in your DevOps Platform's interface.
+settings.almintegration.empty.server_base_url=You need to set the Server Base URL in General > {serverBaseUrl} to have correct links from the DevOps Platform to your {productName} instance.
settings.almintegration.empty.server_base_url.setting_link=Server Base URL
settings.almintegration.tab.github=GitHub
settings.almintegration.tab.bitbucket=Bitbucket
settings.almintegration.tab.gitlab=GitLab
settings.almintegration.github.info=You need to install a GitHub App with specific settings and permissions to enable Pull Request Decoration on your Organization or Repository. {link}
settings.almintegration.github.additional_permission=If Quality Gate status reporting fails on private projects, you might need to add an additional permission to the GitHub App. {link}
-settings.almintegration.bitbucketcloud.info=SonarQube needs you to create an {oauth} in your Bitbucket Cloud workspace settings to report the Quality Gate status on Pull Requests. It needs to be a private consumer with {permission} permission. An OAuth callback URL is required by Bitbucket Cloud but not used by SonarQube so any URL works. {doc_link}
+settings.almintegration.bitbucketcloud.info={productName} needs you to create an {oauth} in your Bitbucket Cloud workspace settings to report the Quality Gate status on Pull Requests. It needs to be a private consumer with {permission} permission. An OAuth callback URL is required by Bitbucket Cloud but not used by {productName} so any URL works. {doc_link}
settings.almintegration.bitbucketcloud.oauth=OAuth consumer
-settings.almintegration.empty.azure=Create your first Azure DevOps configuration to start analyzing your repositories on SonarQube.
-settings.almintegration.empty.bitbucket=Create your first Bitbucket configuration to start analyzing your repositories on SonarQube.
-settings.almintegration.empty.bitbucketcloud=Create your first Bitbucket Cloud configuration to start analyzing your repositories on SonarQube.
-settings.almintegration.empty.github=Create your first GitHub configuration to start analyzing your repositories on SonarQube.
-settings.almintegration.empty.gitlab=Create your first GitLab configuration to start analyzing your repositories on SonarQube.
+settings.almintegration.empty.azure=Create your first Azure DevOps configuration to start analyzing your repositories on {productName}.
+settings.almintegration.empty.bitbucket=Create your first Bitbucket configuration to start analyzing your repositories on {productName}.
+settings.almintegration.empty.bitbucketcloud=Create your first Bitbucket Cloud configuration to start analyzing your repositories on {productName}.
+settings.almintegration.empty.github=Create your first GitHub configuration to start analyzing your repositories on {productName}.
+settings.almintegration.empty.gitlab=Create your first GitLab configuration to start analyzing your repositories on {productName}.
settings.almintegration.create=Create configuration
settings.almintegration.create.tooltip=Upgrade to {link} to integrate with multiple {alm} instances.
settings.almintegration.create.tooltip.link=Enterprise Edition
settings.almintegration.form.webhook_secret.github=Webhook Secret
settings.almintegration.form.webhook_secret.github.help=Leave this field empty unless you are using GitHub Code Scanning Alert feature. See documentation for more details.
settings.almintegration.form.personal_access_token=Personal Access Token
-settings.almintegration.form.personal_access_token.azure.help=SonarQube needs a {pat} to report the Quality Gate status on Pull Requests in Azure DevOps. To create this token, we recommend using a dedicated Azure DevOps account with administration permissions. The token itself needs {permission} permission. {doc_link}
+settings.almintegration.form.personal_access_token.azure.help={productName} needs a {pat} to report the Quality Gate status on Pull Requests in Azure DevOps. To create this token, we recommend using a dedicated Azure DevOps account with administration permissions. The token itself needs {permission} permission. {doc_link}
settings.almintegration.form.personal_access_token.azure.help.url=Personal Access Token
-settings.almintegration.form.personal_access_token.gitlab.help=SonarQube needs a {pat} to report the Quality Gate status on Merge Requests in GitLab. To create this token, we recommend using a dedicated GitLab account with {permission} permission to all target projects. The token itself needs the {scope} scope. {doc_link}
+settings.almintegration.form.personal_access_token.gitlab.help={productName} needs a {pat} to report the Quality Gate status on Merge Requests in GitLab. To create this token, we recommend using a dedicated GitLab account with {permission} permission to all target projects. The token itself needs the {scope} scope. {doc_link}
settings.almintegration.form.personal_access_token.gitlab.help.url=Personal Access Token
-settings.almintegration.form.personal_access_token.bitbucket.help=SonarQube needs a {pat} to report the Quality Gate status on Pull Requests in Bitbucket Server. To create this token, we recommend using a dedicated Bitbucket Server account with administration permissions. The token itself needs {permission} permission. {doc_link}
+settings.almintegration.form.personal_access_token.bitbucket.help={productName} needs a {pat} to report the Quality Gate status on Pull Requests in Bitbucket Server. To create this token, we recommend using a dedicated Bitbucket Server account with administration permissions. The token itself needs {permission} permission. {doc_link}
settings.almintegration.form.personal_access_token.bitbucket.help.url=Personal Access Token
settings.almintegration.form.save=Save configuration
settings.almintegration.form.cancel=Cancel
settings.almintegration.feature.pr_decoration.disabled.no_branches=Upgrade to {link} to enable this feature.
settings.almintegration.feature.pr_decoration.disabled.no_branches.link=Developer Edition
settings.almintegration.feature.alm_repo_import.title=Import repositories from your DevOps Platform
-settings.almintegration.feature.alm_repo_import.description=Select repositories from your DevOps Platform, and import them into SonarQube.
+settings.almintegration.feature.alm_repo_import.description=Select repositories from your DevOps Platform, and import them into {productName}.
settings.almintegration.feature.alm_repo_import.disabled=Disabled
settings.almintegration.feature.alm_repo_import.disabled.no_url=This feature is disabled because your configured instance has no URL.
settings.almintegration.tabs.authentication_moved=You can delegate authentication to this DevOps Platform. The relevant settings are under the {link} section.
settings.authentication.github.confirm.AUTO_PROVISIONING=Switch to automatic provisioning
settings.authentication.github.confirm.JIT=Switch to Just-in-Time provisioning
settings.authentication.github.confirm.insecure=Potentially insecure configuration
-settings.authentication.github.confirm.AUTO_PROVISIONING.description=Once you transition to automatic provisioning, groups, users, group memberships, and permissions on GitHub projects will be inherited from GitHub. You will no longer have the ability to edit them within SonarQube. Do you want to proceed with this change?
+settings.authentication.github.confirm.AUTO_PROVISIONING.description=Once you transition to automatic provisioning, groups, users, group memberships, and permissions on GitHub projects will be inherited from GitHub. You will no longer have the ability to edit them within {productName}. Do you want to proceed with this change?
settings.authentication.github.confirm.JIT.description=Switching to Just-in-Time provisioning removes the automatic synchronization of users, groups, and group memberships. Users are provisioned and group memberships are updated only at user login. Are you sure?
settings.authentication.github.provisioning_change.confirm_changes=Confirm change
settings.authentication.github.provisioning_change.insecure_config=Please be aware that your configuration is potentially insecure because you didn't add any organization to the allowlist. If your GitHub App is public, anyone can install it and gain access to your instance.
settings.authentication.github.form.legacy_configured.link=Learn more about how to create a GitHub App configuration
settings.authentication.github.enable_first=Enable your GitHub configuration for more provisioning options.
settings.authentication.github.form.allowedOrganizations.name=Organizations
-settings.authentication.github.form.allowedOrganizations.description=Only members of these organizations will be able to authenticate to the server. ⚠ if not set, users from any organization where the GitHub App is installed will be able to login to this SonarQube instance.
+settings.authentication.github.form.allowedOrganizations.description=Only members of these organizations will be able to authenticate to the server. ⚠ if not set, users from any organization where the GitHub App is installed will be able to login to this {productName} instance.
settings.authentication.github.form.apiUrl.name=The API url for a GitHub instance.
settings.authentication.github.form.apiUrl.description=The API url for a GitHub instance. https://api.github.com/ for GitHub.com, https://github.company.com/api/v3/ when using GitHub Enterprise
settings.authentication.github.form.applicationId.name=App ID
settings.authentication.github.form.privateKey.name=Private Key
settings.authentication.github.form.privateKey.description=Your GitHub App's private key. You can generate a .pem file from your GitHub App's page under Private keys. Copy and paste the whole contents of the file here.
settings.authentication.github.form.synchronizeGroups.name=Synchronize teams as groups
-settings.authentication.github.form.synchronizeGroups.description=Synchronize GitHub team with SonarQube group memberships when users log in to SonarQube. For each GitHub team they belong to, users will be associated to a group of the same name if it exists in SonarQube.
+settings.authentication.github.form.synchronizeGroups.description=Synchronize GitHub team with {productName} group memberships when users log in to {productName}. For each GitHub team they belong to, users will be associated to a group of the same name if it exists in {productName}.
settings.authentication.github.form.webUrl.name=The WEB url for a GitHub instance.
settings.authentication.github.form.webUrl.description=The WEB url for a GitHub instance. https://github.com/ for GitHub.com, https://github.company.com/ when using GitHub Enterprise.
settings.authentication.github.form.private_key.required_for_url_change=Please provide your private key again to update the API URL or the Web URL.
settings.authentication.github.form.provisioning_with_github_short.jit=Just-in-Time provisioning
settings.authentication.github.form.provisioning_with_github.description=Users, groups and permissions are automatically provisioned from your GitHub organizations. Once activated, users and groups can only be created and modified from your GitHub organizations/teams. Existing local users will be kept and can only be deactivated. {documentation}
settings.authentication.github.form.description.doc=For more details, see {documentation}.
-settings.authentication.github.form.provisioning_at_login.description=Users and groups are synchronized only when users log in to SonarQube. {documentation}
+settings.authentication.github.form.provisioning_at_login.description=Users and groups are synchronized only when users log in to {productName}. {documentation}
settings.authentication.github.form.provisioning.disabled=Your current edition does not support provisioning with GitHub. See the {documentation} for more information.
settings.authentication.github.form.allowUsersToSignUp.name=Allow users to sign up
settings.authentication.github.form.allowUsersToSignUp.description=Allow new users to authenticate. When set to disabled, only existing users will be able to authenticate to the server.
settings.authentication.github.form.projectVisibility.name=Provision project visibility
-settings.authentication.github.form.projectVisibility.description=Change project visibility based on GitHub repository visibility. If disabled, every provisioned project will be private in SonarQube and visible only to users with explicit GitHub permissions for the corresponding repository. Changes take effect at the next synchronization.
+settings.authentication.github.form.projectVisibility.description=Change project visibility based on GitHub repository visibility. If disabled, every provisioned project will be private in {productName} and visible only to users with explicit GitHub permissions for the corresponding repository. Changes take effect at the next synchronization.
settings.authentication.github.synchronize_now=Synchronize now
settings.authentication.github.synchronization_finish=Synchronization is done.
settings.authentication.github.configuration.validation.details=View details
settings.authentication.github.configuration.validation.details.valid_label=Valid
settings.authentication.github.configuration.validation.details.invalid_label=Invalid
settings.authentication.github.configuration.validation.details.org_not_found={0} (not found or app not installed)
-settings.authentication.github.configuration.roles_mapping.description=When synchronizing users and groups, SonarQube assigns permissions based on GitHub user and team roles. You can customize the mapping of permissions. The new mapping will take effect at the next synchronization.
+settings.authentication.github.configuration.roles_mapping.description=When synchronizing users and groups, {productName} assigns permissions based on GitHub user and team roles. You can customize the mapping of permissions. The new mapping will take effect at the next synchronization.
settings.authentication.github.configuration.roles_mapping.save_success=GitHub roles mapping saved successfully.
settings.authentication.github.configuration.roles_mapping.dialog.custom_roles_description=When a custom role name added here matches an existing GitHub custom role in any of your organizations, the mapping applies to all users with this custom role. If an existing GitHub custom role has no exact match in this list, the permissions of its inherited base role are mapped.
settings.authentication.github.configuration.unsaved_changes=You have unsaved changes.
settings.authentication.gitlab.form.secret.description=Secret provided by GitLab when registering the application.
settings.authentication.gitlab.form.secret.required_for_url_change=Please provide your secret again to update the URL.
settings.authentication.gitlab.form.synchronizeGroups.name=Synchronize user groups
-settings.authentication.gitlab.form.synchronizeGroups.description=For each GitLab group they belong to, the user will be associated to a group with the same name (if it exists) in SonarQube. If enabled, the GitLab OAuth 2 application will need to provide the api scope.
+settings.authentication.gitlab.form.synchronizeGroups.description=For each GitLab group they belong to, the user will be associated to a group with the same name (if it exists) in {productName}. If enabled, the GitLab OAuth 2 application will need to provide the api scope.
settings.authentication.gitlab.form.allowedGroups.name=Allowed groups
-settings.authentication.gitlab.form.allowedGroups.description.JIT=Only members of these groups (and sub-groups) will be allowed to authenticate. Enter the group slug as it appears in the GitLab URL, for instance `my-gitlab-group`. ⚠︎ When you turn on `Allow users to sign up`, make sure to also turn on group synchronization and provide a list of allowed groups. Otherwise, any GitLab user will be able to log in to this SonarQube instance.
+settings.authentication.gitlab.form.allowedGroups.description.JIT=Only members of these groups (and sub-groups) will be allowed to authenticate. Enter the group slug as it appears in the GitLab URL, for instance `my-gitlab-group`. ⚠︎ When you turn on `Allow users to sign up`, make sure to also turn on group synchronization and provide a list of allowed groups. Otherwise, any GitLab user will be able to log in to this {productName} instance.
settings.authentication.gitlab.form.allowedGroups.description.AUTO_PROVISIONING=Only members of these groups (and sub-groups) will be provisioned. Please enter the group slug as it appears in the GitLab URL, for instance `my-gitlab-group`.
settings.authentication.gitlab.form.allowUsersToSignUp.name=Allow users to sign up
settings.authentication.gitlab.form.allowUsersToSignUp.description=Allow new users to authenticate. When set to disabled, only existing users will be able to authenticate to the server.
settings.authentication.gitlab.applicationId.name=App ID: {0}
settings.authentication.gitlab.enable_first=Enable your GitLab configuration for more provisioning options.
settings.authentication.gitlab.provisioning_at_login=Just-in-Time user provisioning (default)
-settings.authentication.gitlab.provisioning_at_login.description=Users are synchronized only when users log in to SonarQube. {documentation}
+settings.authentication.gitlab.provisioning_at_login.description=Users are synchronized only when users log in to {productName}. {documentation}
settings.authentication.gitlab.description.JIT.learn_more=Learn more about Just-in-Time provisioning with GitLab
settings.authentication.gitlab.description.AUTO_PROVISIONING.learn_more=Learn more about automatic provisioning with GitLab
settings.authentication.gitlab.confirm.AUTO_PROVISIONING=Switch to automatic provisioning
settings.authentication.gitlab.confirm.JIT=Switch to Just-in-Time provisioning
-settings.authentication.gitlab.confirm.AUTO_PROVISIONING.description=Once you transition to automatic provisioning users, groups and permissions on GitLab projects will be inherited from GitLab. You will no longer have the ability to edit them within SonarQube. Do you want to proceed with this change?
+settings.authentication.gitlab.confirm.AUTO_PROVISIONING.description=Once you transition to automatic provisioning users, groups and permissions on GitLab projects will be inherited from GitLab. You will no longer have the ability to edit them within {productName}. Do you want to proceed with this change?
settings.authentication.gitlab.confirm.JIT.description=Switching to Just-in-Time provisioning removes the automatic synchronization of users, groups and permissions. Users are provisioned and updated only at user login. Are you sure?
settings.authentication.gitlab.confirm.insecure=Potentially insecure configuration
settings.authentication.gitlab.provisioning_change.confirm_changes=Confirm change
settings.authentication.gitlab.configuration.unsaved_changes=You have unsaved changes.
settings.authentication.gitlab.configuration.valid.JIT=Configuration is valid for Just-in-Time provisioning.
settings.authentication.gitlab.configuration.valid.AUTO_PROVISIONING=Configuration is valid for Automatic provisioning.
-settings.authentication.gitlab.configuration.roles_mapping.description=When synchronizing users and groups, SonarQube assigns permissions based on Gitlab user roles. You can customize the mapping of permissions. The new mapping will take effect at the next synchronization.
+settings.authentication.gitlab.configuration.roles_mapping.description=When synchronizing users and groups, {productName} assigns permissions based on Gitlab user roles. You can customize the mapping of permissions. The new mapping will take effect at the next synchronization.
settings.authentication.gitlab.configuration.roles_mapping.save_success=GitLab roles mapping saved successfully.
settings.authentication.gitlab.configuration.roles_mapping.dialog.custom_roles_description=When a custom role name added here matches an existing GitLab custom role in any of your groups or projects, the mapping applies to all users with this custom role. If an existing GitLab custom role has no exact match in this list, the permissions of its inherited base role are mapped.
settings.authentication.saml.configuration=SAML Configuration
settings.authentication.saml.confirm.scim=Switch to automatic provisioning
settings.authentication.saml.confirm.jit=Switch to Just-in-Time provisioning
-settings.authentication.saml.confirm.scim.description=Once you transition to automatic provisioning, groups, users and group memberships will be managed by your identity provider. You will no longer have the ability to edit them within SonarQube. Do you want to proceed with this change?
+settings.authentication.saml.confirm.scim.description=Once you transition to automatic provisioning, groups, users and group memberships will be managed by your identity provider. You will no longer have the ability to edit them within {productName}. Do you want to proceed with this change?
settings.authentication.saml.confirm.jit.description=Switching to Just-in-Time provisioning removes all information provided while automatic provisioning through SCIM was active. These changes cannot be reverted. Are you sure?
settings.authentication.saml.form.loading=Loading SAML configuration
settings.authentication.saml.form.not_configured=SAML is not configured
settings.pr_decoration.binding.form.name.help=Each DevOps Platform instance must be configured globally first, and given a unique name. Pick the instance your project is hosted on.
settings.pr_decoration.binding.form.monorepo=Enable monorepository support
settings.pr_decoration.binding.form.monorepo.help=Enable this setting if your project is part of a monorepository. {doc_link}
-settings.pr_decoration.binding.form.monorepo.warning=This setting must be enabled for all SonarQube projects that are part of a monorepository.
+settings.pr_decoration.binding.form.monorepo.warning=This setting must be enabled for all {productName} projects that are part of a monorepository.
settings.pr_decoration.binding.form.azure.project=Project name
settings.pr_decoration.binding.form.azure.project.help=The name of the Azure DevOps project containing your repository. You can find this name on your project's Overview page.
settings.pr_decoration.binding.form.azure.repository=Repository name
settings.mode.standard.name=Standard Experience
settings.mode.mqr.name=Multi-Quality Rule (MQR) Mode
settings.mode.standard.description.line1=Encompasses the traditional use of rule types such as bugs, code smells, and vulnerabilities, with a single category and severity level for each rule.
-settings.mode.standard.description.line2=This approach focuses on assigning severity to a rule and its issues based on the single software quality (for example, security, reliability or maintainability) it has the largest impact on. This is the rule categorization used in SonarQube 9.9 LTA and earlier.
+settings.mode.standard.description.line2=This approach focuses on assigning severity to a rule and its issues based on the single software quality (for example, security, reliability or maintainability) it has the largest impact on. This is the rule categorization used in {productName} 9.9 LTA and earlier.
settings.mode.mqr.description.line1=Aims to more accurately represent the impact issues have on all software qualities. Very few issues impact only a single software quality. For instance, most vulnerabilities are also bugs. And vice versa. The MQR mode maps each rule to each of the qualities it impacts, with a separate severity rating for each quality.
settings.mode.mqr.description.line2=This approach focuses on ensuring the impact of an issue on all software qualities is clear, not just the most severe one.
settings.mode.save.warning=Save changes to see them reflected in your instance
property.codefix.admin.promoted_section.content1=This no cost trial is offered to you at Sonar’s discretion. Sonar can decide to stop this trial anytime.
property.codefix.admin.promoted_section.content2=At the end of the trial, this feature will be deactivated and your choice to “enable AI CodeFix” below will be ignored. Your organisation will not be charged.
property.codefix.admin.serviceCheck.title=Test the AI CodeFix service
-property.codefix.admin.serviceCheck.description1=Make sure this SonarQube instance can communicate with the AI CodeFix service, which requires network connectivity to function.
+property.codefix.admin.serviceCheck.description1=Make sure this {productName} instance can communicate with the AI CodeFix service, which requires network connectivity to function.
property.codefix.admin.serviceCheck.description2=This test is free and should only take a few seconds.
property.codefix.admin.serviceCheck.learnMore=Read more about enabling AI CodeFix
property.codefix.admin.serviceCheck.action=Test AI CodeFix service
property.codefix.admin.serviceCheck.result.success=The AI CodeFix service responded successfully.
property.codefix.admin.serviceCheck.result.unresponsive.message=The AI CodeFix service does not respond or is not reachable.
property.codefix.admin.serviceCheck.result.unresponsive.causes.title=Here are some possible causes of this error:
-property.codefix.admin.serviceCheck.result.unresponsive.causes.1=The network may not be properly configured on this SonarQube instance. Please check the firewall and connectivity settings.
+property.codefix.admin.serviceCheck.result.unresponsive.causes.1=The network may not be properly configured on this {productName} instance. Please check the firewall and connectivity settings.
property.codefix.admin.serviceCheck.result.unresponsive.causes.2=The AI CodeFix service may be down.
property.codefix.admin.serviceCheck.result.requestError=Error checking the AI CodeFix service:
property.codefix.admin.serviceCheck.result.serviceError=The AI CodeFix service is reachable but returned an error. Check logs for more details.
-property.codefix.admin.serviceCheck.result.unauthorized=This SonarQube instance is not allowed to use AI CodeFix.
+property.codefix.admin.serviceCheck.result.unauthorized=This {productName} instance is not allowed to use AI CodeFix.
property.codefix.admin.serviceCheck.result.unknown=The AI CodeFix service returned an unexpected message:
#------------------------------------------------------------------------------
project.info.make_home.title=Use as homepage
project.info.make_home.label=Make this project my homepage
application.info.make_home.label=Make this application my homepage
-project.info.make_home.tooltip=This means you'll be redirected to this project whenever you log in to SonarQube or click on the top-left SonarQube logo.
-application.info.make_home.tooltip=This means you'll be redirected to this application whenever you log in to SonarQube or click on the top-left SonarQube logo.
+project.info.make_home.tooltip=This means you'll be redirected to this project whenever you log in to {productName} or click on the top-left {productName} logo.
+application.info.make_home.tooltip=This means you'll be redirected to this application whenever you log in to {productName} or click on the top-left {productName} logo.
overview.project_key.tooltip.TRK=Your project key is a unique identifier for your project. If you are using Maven, make sure the key matches the "groupId:artifactId" format.
overview.project_key.tooltip.APP=Your application key is a unique identifier for your application.
project.info.ai_code_assurance.title=AI Code Assurance
quality_profiles.changelog.impact_changed=Software impact set to {newSoftwareQuality} with severity {newSeverity}, was {oldSoftwareQuality} with severity {oldSeverity}
quality_profiles.changelog.impact_added=Software impact {newSoftwareQuality} with severity {newSeverity} was added
quality_profiles.changelog.impact_removed=Software impact {oldSoftwareQuality} with severity {oldSeverity} was removed
-quality_profiles.changelog.sq_upgrade=Instance upgraded to SonarQube {sqVersion}
+quality_profiles.changelog.sq_upgrade=Instance upgraded to {productName} {sqVersion}
quality_profiles.deleted_profile=The profile {0} doesn't exist anymore
quality_profiles.projects_for_default=Every project not specifically associated with a quality profile will be associated to this one by default.
quality_profile.x_rules={count} rule(s)
coding_rules.context.others.description.do=Do use libraries that are compatible with the frameworks you are using.
coding_rules.context.others.description.dont=Don’t blindly copy and paste the fixups into your code.
coding_rules.context.others.title_feedback=Help us improve
-coding_rules.context.others.feedback_description_1=Let us know if the instructions we provide do not work for you. Tell us which framework you use and why our solution does not work by submitting an idea on the SonarQube productboard.
+coding_rules.context.others.feedback_description_1=Let us know if the instructions we provide do not work for you. Tell us which framework you use and why our solution does not work by submitting an idea on the {productName} productboard.
coding_rules.context.others.feedback_description_2=We will do our best to provide you with more relevant instructions in the future.
coding_rules.context.others.feedback_description.link=Submit an idea
coding_rules.create=Create
coding_rules.custom_rule.activation_notice=Note: parameters of a custom rule are not customizable on rule activation, only during creation/edit.
coding_rules.custom_rule.software_quality_x={quality} software quality
coding_rules.custom_rule.select_software_quality=Please select at least one software quality.
-coding_rules.custom_rule.removal=Only custom rules may be deleted. When a custom rule is deleted, it is not removed from the SonarQube instance. Instead its status is set to "REMOVED", allowing relevant issues to continue to be displayed properly.
+coding_rules.custom_rule.removal=Only custom rules may be deleted. When a custom rule is deleted, it is not removed from the {productName} instance. Instead its status is set to "REMOVED", allowing relevant issues to continue to be displayed properly.
coding_rules.custom_rules=Custom Rules
coding_rules.deactivate_in_quality_profile=Deactivate In Quality Profile
coding_rules.deactivate_in_quality_profile_x=Deactivate In Quality Profile {0}
email_notification.form.from_address=From address
email_notification.form.from_address.description=Address emails will come from.
email_notification.form.from_name=From name
-email_notification.form.from_name.description=Name emails will come from (usually "SonarQube").
+email_notification.form.from_name.description=Name emails will come from (usually "{productName}").
email_notification.form.subject_prefix=Subject prefix
-email_notification.form.subject_prefix.description=Prefix added to email so they can be easily recognized (usually "[SonarQube]").
+email_notification.form.subject_prefix.description=Prefix added to email so they can be easily recognized (usually "[{productName}]").
email_notification.form.save_configuration=Save configuration
email_notification.form.save_configuration.create_success=Email configuration saved successfully.
email_notification.form.save_configuration.update_success=Email configuration updated successfully.
email_notification.test.to_address=To
email_notification.test.subject=Subject
email_notification.test.message=Message
-email_notification.test.message_text=This is a test message from SonarQube.
+email_notification.test.message_text=This is a test message from {productName}.
email_notification.test.create_test_email=Create test email
email_notification.test.submit=Send test email
email_notification.test.success=Your email was sent successfully
user.confirm_password.no_match=Passwords do not match
login.page=Log in
-login.login_to_sonarqube=Log in to SonarQube
+login.login_to_sonarqube=Log in to {productName}
login.login_with_x=Log in with {0}
login.more_options=Log in with credentials
login.unauthorized_access_alert=You are not authorized to access this page. Please log in with more privileges and try again.
#
#------------------------------------------------------------------------------
-promotion.sonarlint.title=Get the most out of SonarQube!
-promotion.sonarlint.content=Take advantage of the whole ecosystem by using SonarLint, a free IDE plugin that helps you find and fix issues earlier in your workflow. Connect SonarLint to SonarQube to sync rule sets and issue states.
+promotion.sonarlint.title=Get the most out of {productName}!
+promotion.sonarlint.content=Take advantage of the whole ecosystem by using SonarQube for IDE, a free IDE plugin that helps you find and fix issues earlier in your workflow. Connect SonarQube for IDE to {productName} to sync rule sets and issue states.
#------------------------------------------------------------------------------
#
#
#------------------------------------------------------------------------------
-sonarlint-connection.request.title=Allow SonarLint connection?
-sonarlint-connection.request.description=SonarLint for {0} is requesting access to SonarQube.
-sonarlint-connection.request.description2=Do you allow SonarLint to connect? This will create a token and share it with SonarLint.
+sonarlint-connection.request.title=Allow SonarQube for IDE connection?
+sonarlint-connection.request.description=SonarQube for IDE for {ideName} is requesting access to {productName}.
+sonarlint-connection.request.description2=Do you allow SonarQube for IDE to connect? This will create a token and share it with SonarQube for IDE.
sonarlint-connection.request.action=Allow connection
sonarlint-connection.token-error.title=Token generation failed
-sonarlint-connection.token-error.description=SonarQube was not able to generate a token.
-sonarlint-connection.token-error.description2=Go back to your IDE and start again, or go to the {link} of your SonarQube account to create a new user token manually.
+sonarlint-connection.token-error.description={productName} was not able to generate a token.
+sonarlint-connection.token-error.description2=Go back to your IDE and start again, or go to the {link} of your {productName} account to create a new user token manually.
sonarlint-connection.token-error.description2.link=Security section
sonarlint-connection.connection-error.title=Token created
sonarlint-connection.connection-error.token-value=Token value
sonarlint-connection.connection-error.next-steps=Next steps
sonarlint-connection.connection-error.step1=Copy the above token.
-sonarlint-connection.connection-error.step2=Go back to your IDE and paste the token in SonarLint.
+sonarlint-connection.connection-error.step2=Go back to your IDE and paste the token in SonarQube for IDE.
-sonarlint-connection.success.title=SonarLint connection is almost ready!
-sonarlint-connection.success.description=A new '{0}' token was created and sent to SonarLint in your IDE.
+sonarlint-connection.success.title=SonarQube for IDE connection is almost ready!
+sonarlint-connection.success.description=A new '{0}' token was created and sent to SonarQube for IDE in your IDE.
sonarlint-connection.success.last-step=Last step
sonarlint-connection.success.step=Go back to your IDE to complete the setup.
sonarlint-connection.unspecified-ide=an unspecified IDE
-sonarlint-connected-mode-doc=documentation about SonarLint Connected Mode
+sonarlint-connected-mode-doc=documentation about SonarQube for IDE Connected Mode
#------------------------------------------------------------------------------
#
# HELP
#------------------------------------------------------------------------------
keyboard_shortcuts_modal.title=Keyboard Shortcuts
keyboard_shortcuts_modal.disable_link=Disable shortcuts
-keyboard_shortcuts_modal.description= You can use the following shortcuts when navigating within SonarCloud
keyboard_shortcuts_modal.global= Global
keyboard_shortcuts_modal.global.open_search_bar= Open search bar
keyboard_shortcuts_modal.global.open_keyboard_shortcuts_modal= Open keyboard shortcuts modal
#
#------------------------------------------------------------------------------
marketplace.page=Marketplace
-marketplace.page.description=Discover the additional benefits offered in SonarQube Commercial Editions
-marketplace.page.description_best_edition=This edition includes access to all the SonarQube-SonarLint Ecosystem features!
+marketplace.page.description=Discover the additional benefits offered in SonarQube Server Commercial Editions
+marketplace.page.description_best_edition=This edition includes access to all the SonarQube Server-SonarQube for IDE Ecosystem features!
marketplace.page.you_are_running.community=You are currently running a Community Edition.
marketplace.page.you_are_running.developer=You are currently running a Developer Edition.
marketplace.page.you_are_running.enterprise=You are currently running an Enterprise Edition.
component_navigation.status.in_progress_X.admin.help=The {type} is in progress.
component_navigation.status.last_blocked_due_to_bad_license_X=Last analysis blocked due to an invalid license, which has since been corrected. Please reanalyze this {0}.
-component_navigation.pr_deco.error_detected_X=We've detected an issue with your configuration. Your SonarQube instance won't be able to perform any pull request decoration. {action}
+component_navigation.pr_deco.error_detected_X=We've detected an issue with your configuration. Your {productName} instance won't be able to perform any pull request decoration. {action}
component_navigation.pr_deco.action.check_project_settings=Please check your project settings.
component_navigation.pr_deco.action.contact_project_admin=Please contact your project administrator.
#
#------------------------------------------------------------------------------
project_dump.page=Import / Export
-project_dump.page.description1=Moving a project from one SonarQube instance to another is a 3 step operation:
-project_dump.page.description2=Export the project, copy the generated dump on the target server, and finally import that dump from this page on the target SonarQube instance.
+project_dump.page.description1=Moving a project from one {productName} instance to another is a 3 step operation:
+project_dump.page.description2=Export the project, copy the generated dump on the target server, and finally import that dump from this page on the target {productName} instance.
project_dump.page.description_without_import1=Export project issues, measures and measure history for import into an Enterprise Edition or higher instance of the same version and similar configuration. The export file will be generated to the file system. It must then be copied to the target file system for import.
project_dump.page.description_without_import2=The export file will be generated to the file system. It must then be copied to the target file system for import.
project_dump.refresh=Refresh
system.log_level.info=Your selection does not affect the Search Engine.
system.logs_level=Logs level
system.logs_level.change=Change logs level
-system.new_version_available=A new version of SonarQube is available.
+system.new_version_available=A new version of {productName} is available.
system.restart_does_not_reload_sonar_properties=Also note that a restart will not reload the sonar.properties file.
system.see_whats_new=See what's new!
system.release_notes=Release Notes
system.restart_server=Restart Server
system.instance_restarting={instance} restart is in progress. Ongoing {link} are completing.
system.search_nodes_title=Search Nodes
-system.see_sonarqube_downloads=See All SonarQube Downloads
+system.see_sonarqube_downloads=See All {productName} Downloads
system.not_production_database_warning=This server ID is valid only for the embedded database, which should be considered disposable. Consider configuring an external database for long-term use prior to requesting your license.
system.server_id=Server ID
system.set_log_level=Set logs level
overview.project.main_branch_empty=The main branch of this project is empty.
overview.project.branch_needs_new_analysis=The branch data is incomplete. Run a new analysis to update it.
overview.project.last_analysis.date_time=Last analysis started on {0}
-overview.project.next_steps.set_up_pr_deco_and_ci.admin=To benefit from more of SonarQube's features, {link_ci} and set up DevOps platform integration in your {link_project_settings}.
-overview.project.next_steps.set_up_pr_deco_and_ci=To benefit from more of SonarQube's features, {link_ci} and ask a project administrator to set up DevOps platform integration.
-overview.project.next_steps.set_up_pr_deco.admin=To benefit from more of SonarQube's features, set up DevOps platform integration in your {link_project_settings}.
-overview.project.next_steps.set_up_pr_deco=To benefit from more of SonarQube's features, ask a project administrator to set up DevOps platform integration.
-overview.project.next_steps.set_up_ci=To benefit from more of SonarQube's features, {link}.
+overview.project.next_steps.set_up_pr_deco_and_ci.admin=To benefit from more of {productName}'s features, {link_ci} and set up DevOps platform integration in your {link_project_settings}.
+overview.project.next_steps.set_up_pr_deco_and_ci=To benefit from more of {productName}'s features, {link_ci} and ask a project administrator to set up DevOps platform integration.
+overview.project.next_steps.set_up_pr_deco.admin=To benefit from more of {productName}'s features, set up DevOps platform integration in your {link_project_settings}.
+overview.project.next_steps.set_up_pr_deco=To benefit from more of {productName}'s features, ask a project administrator to set up DevOps platform integration.
+overview.project.next_steps.set_up_ci=To benefit from more of {productName}'s features, {link}.
overview.project.next_steps.links.project_settings=project settings
overview.project.next_steps.links.set_up_ci=set up analysis in your favorite CI
overview.project.software_impact.has_rating=Software Quality {softwareQuality} has rating {rating}
overview.deleted_profile={0} has been deleted since the last analysis.
overview.link_to_x_profile_y=Go to {0} profile "{1}"
-overview.sonarlint_ad.header=Catch issues before they fail your Quality Gate with our IDE extension, SonarLint
+overview.sonarlint_ad.header=Catch issues before they fail your Quality Gate with our IDE extension, SonarQube for IDE
overview.sonarlint_ad.details_1=The power of Sonar analyzers directly as you type
overview.sonarlint_ad.details_2=No need to wait for your PR to pass all checks
overview.sonarlint_ad.details_3=Repair flagged issues in real-time with quick fixes
overview.sonarlint_ad.details_4=12 major IDE's supported (including key JetBrains and Microsoft IDE's
overview.sonarlint_ad.details_5=Free forever
-overview.sonarlint_ad.learn_more=Learn more about SonarLint
-overview.sonarlint_ad.close_promotion=Close SonarLint promotion
+overview.sonarlint_ad.learn_more=Learn more about SonarQube for IDE
+overview.sonarlint_ad.close_promotion=Close SonarQube for IDE promotion
overview.badges.get_badge=Badges
overview.badges.title=Get project badges
overview.badges.renew.description=If your project badge security token has leaked to an unsafe environment, you can renew it:
overview.badges.deprecated_badge_x_y=Badges displaying {0} are deprecated and will be removed in a future version. Please choose another badge for your {1}.
-overview.quality_profiles_update_after_sq_upgrade.message=Upgrade to SonarQube {sqVersion} has updated your Quality Profiles. Issues on your project may have been affected. {link}
+overview.quality_profiles_update_after_sq_upgrade.message=Upgrade to {productName} {sqVersion} has updated your Quality Profiles. Issues on your project may have been affected. {link}
overview.quality_profiles_update_after_sq_upgrade.link=See more details
overview.activity.variations.new_analysis=New analysis:
guiding.cayc_promotion.3.title=Green is clean
guiding.cayc_promotion.3.content.1=Quality Gate Status tells you if your new code is clean or not. Keep it green as often as possible, and your project will be production-ready.
guiding.cayc_promotion.4.title=Clean at all levels
-guiding.cayc_promotion.4.content.1=With SonarLint, clean code as you write it in your {value}.
+guiding.cayc_promotion.4.content.1=With SonarQube for IDE, clean code as you write it in your {value}.
guiding.cayc_promotion.4.content.2=When a feature is ready, analyze your {value} (commercial edition only) and make sure no issue is missed.
guiding.cayc_promotion.4.content.3=Finally, rely on a thorough {value} analysis to ensure the new code is clean.
guiding.replay_tour_button.1.title=Replay tour
new_code_definition.reference_branch.usecase=Recommended for projects using feature branches.
new_code_definition.reference_branch.notice=The main branch will be set as the reference branch when the project is created. You will be able to choose another branch as the reference branch when your project will have more branches.
-new_code_definition.auto_update.branch.message=The new code definition of the following branch(es) was automatically changed on {date}, following a SonarQube upgrade, as it was exceeding the maximum value: {branchesList} {link}
+new_code_definition.auto_update.branch.message=The new code definition of the following branch(es) was automatically changed on {date}, following a {productName} upgrade, as it was exceeding the maximum value: {branchesList} {link}
new_code_definition.auto_update.branch.list_item={branchName}: Number of days was changed from {previousDays} to {days}.
-new_code_definition.auto_update.global.message=The global new code definition was automatically changed from {previousDays} to {days} days on {date}, following a SonarQube upgrade, as it was exceeding the maximum value. {link}
-new_code_definition.auto_update.ncd_page.message=The number of days was automatically changed from {previousDays} to {days} on {date}, following a SonarQube upgrade, as it was exceeding the maximum value. {link}
-new_code_definition.auto_update.project.message=This project's new code definition was automatically changed from {previousDays} to {days} days on {date}, following a SonarQube upgrade, as it was exceeding the maximum value. {link}
+new_code_definition.auto_update.global.message=The global new code definition was automatically changed from {previousDays} to {days} days on {date}, following a {productName} upgrade, as it was exceeding the maximum value. {link}
+new_code_definition.auto_update.ncd_page.message=The number of days was automatically changed from {previousDays} to {days} on {date}, following a {productName} upgrade, as it was exceeding the maximum value. {link}
+new_code_definition.auto_update.project.message=This project's new code definition was automatically changed from {previousDays} to {days} days on {date}, following a {productName} upgrade, as it was exceeding the maximum value. {link}
new_code_definition.auto_update.review_link=Review new code definition
#------------------------------------------------------------------------------
onboarding.alm.gitlab=GitLab
onboarding.project_analysis.header=Analyze your project
-onboarding.project_analysis.description=We initialized your project on SonarQube, now it's up to you to launch analyses!
+onboarding.project_analysis.description=We initialized your project on {productName}, now it's up to you to launch analyses!
onboarding.project_analysis.guide_to_integrate_pipelines=follow the guide to integrating with Pipelines
onboarding.create_project.manual.step1=1 of 2
onboarding.create_project.manual.title=Create a local project
onboarding.create_project.select_method=How do you want to create your project?
onboarding.create_project.select_method.manually=Are you just testing or have an advanced use-case? Create a local project.
-onboarding.create_project.select_method.devops_platform=Do you want to benefit from all of SonarQube's features (like repository import and Pull Request decoration)?
+onboarding.create_project.select_method.devops_platform=Do you want to benefit from all of {productName}'s features (like repository import and Pull Request decoration)?
onboarding.create_project.select_method.devops_platform_second=Create your project from your favorite DevOps platform.
onboarding.create_project.select_method.no_alm_yet.admin=First, you need to set up a DevOps platform configuration.
onboarding.create_application.key.description=If specified, this value is used as the key instead of generating it from the name of the Application. Only letters, digits, dashes and underscores can be used.
onboarding.create_project.pat_form.title=Grant access to your repositories
-onboarding.create_project.pat_form.help.azure=SonarQube needs a personal access token to access and list your repositories from Azure DevOps.
-onboarding.create_project.pat_form.help.bitbucket=SonarQube needs a personal access token to access and list your repositories from Bitbucket Server.
-onboarding.create_project.pat_form.help.bitbucket_cloud=SonarQube needs an app password to access and list your repositories from Bitbucket Cloud.
-onboarding.create_project.pat_form.help.gitlab=SonarQube needs a personal access token to access and list your projects from GitLab.
+onboarding.create_project.pat_form.help.azure={productName} needs a personal access token to access and list your repositories from Azure DevOps.
+onboarding.create_project.pat_form.help.bitbucket={productName} needs a personal access token to access and list your repositories from Bitbucket Server.
+onboarding.create_project.pat_form.help.bitbucket_cloud={productName} needs an app password to access and list your repositories from Bitbucket Cloud.
+onboarding.create_project.pat_form.help.gitlab={productName} needs a personal access token to access and list your projects from GitLab.
onboarding.create_project.pat_form.pat_required=Please enter a personal access token
onboarding.create_project.wrong_binding_count=You must have at least 1 {alm} instance configured in order to use this method, but none were found. Either create a local project, or contact your system administrator.
onboarding.create_project.wrong_binding_count.admin=You must have at least 1 {alm} instance configured in order to use this method. You can configure instances under {url}.
onboarding.create_project.pat_help.instructions.azure=To create a Personal Access Token on Azure, {link} and make sure to select the “Code (Read & Write)” scope.
onboarding.create_project.pat_help.instructions.link.azure=generate a token
-onboarding.create_project.pat_help.instructions.gitlab=To create a Personal Access Token on GitLab, {link} by setting a name, for example “SonarQube” and selecting the “read_api” scope.
+onboarding.create_project.pat_help.instructions.gitlab=To create a Personal Access Token on GitLab, {link} by setting a name, for example “{productName}” and selecting the “read_api” scope.
onboarding.create_project.pat_help.instructions.gitlab.link=generate a token
onboarding.enter_username.instructions.bitbucket_cloud=You can find your username in your {link}
onboarding.enter_username.instructions.bitbucket_cloud.link=BitBucket profile settings
-onboarding.create_project.enter_password.instructions.bitbucket_cloud=To create an app password on BitBucket, {link} by setting a name, for example “SonarQube” and selecting the “Repositories: Read” permissions.
+onboarding.create_project.enter_password.instructions.bitbucket_cloud=To create an app password on BitBucket, {link} by setting a name, for example “{productName}” and selecting the “Repositories: Read” permissions.
onboarding.create_project.enter_password.instructions.bitbucket_cloud.link=add an app password
-onboarding.create_project.pat_help.instructions.bitbucket_server=To create a Personal Access Token on BitBucket Server, go to {link} and click on “Create token”. Set a name, for example “SonarQube” and select the following permissions “Projects: Read” “Repositories: Read”.
+onboarding.create_project.pat_help.instructions.bitbucket_server=To create a Personal Access Token on BitBucket Server, go to {link} and click on “Create token”. Set a name, for example “{productName}” and select the following permissions “Projects: Read” “Repositories: Read”.
onboarding.create_project.pat_help.instructions.bitbucket_server.link=HTTP access tokens
-onboarding.create_project.pat_help.instructions2.bitbucket=Set a name, for example "SonarQube", and select the following permissions:
-onboarding.create_project.pat_help.instructions2.bitbucketcloud=Set a name, for example "SonarQube", and select the following permissions:
+onboarding.create_project.pat_help.instructions2.bitbucket=Set a name, for example "{productName}", and select the following permissions:
+onboarding.create_project.pat_help.instructions2.bitbucketcloud=Set a name, for example "{productName}", and select the following permissions:
-onboarding.create_project.pat_help.instructions2.gitlab=Set a name, for example "SonarQube", and select the following scope:
+onboarding.create_project.pat_help.instructions2.gitlab=Set a name, for example "{productName}", and select the following scope:
onboarding.create_project.pat_help.gitlab.read_api_permission=read_api
onboarding.create_project.no_bbs_projects=No projects could be fetched from Bitbucket Server. Contact your system administrator, or {link}.
onboarding.create_project.bitbucket.subtitle=Import projects from one of your Bitbucket server workspaces
onboarding.create_project.bitbucket.subtitle.with_monorepo=Import projects from one of your Bitbucket server workspaces or {monorepoSetupLink}.
onboarding.create_project.x_repositories_selected={count} {count, plural, one {repository} other {repositories}} selected
-onboarding.create_project.x_repository_created={count} {count, plural, one {repository} other {repositories}} will be created as {count, plural, one {a project} other {projects}} in SonarQube
+onboarding.create_project.x_repository_created={count} {count, plural, one {repository} other {repositories}} will be created as {count, plural, one {a project} other {projects}} in {productName}
onboarding.create_project.please_dont_leave=If you leave the page the import could fail. Are you sure you want to leave?
onboarding.create_project.import_in_progress={count} of {total} projects imported. Please do not close this page until the import is complete.
onboarding.create_project.monorepo.title={almName} monorepo project onboarding
-onboarding.create_project.monorepo.subtitle=Create multiple SonarQube projects corresponding to the same monorepo and bound to the same repository.
+onboarding.create_project.monorepo.subtitle=Create multiple {productName} projects corresponding to the same monorepo and bound to the same repository.
onboarding.create_project.monorepo.doc_link=Learn more and get help setting up your monorepo
onboarding.create_project.monorepo.choose_organization_and_repository=Choose the organization and the repository
onboarding.create_project.monorepo.choose_dop_setting=Choose the {almKey} configuration
onboarding.create_project.monorepo.choose_organization.placeholder=List of organizations
onboarding.create_project.monorepo.choose_repository=Choose the repository
onboarding.create_project.monorepo.choose_repository.placeholder=List of repositories
-onboarding.create_project.monorepo.choose_repository.no_already_bound_projects=This repository has no imported projects in SonarQube
-onboarding.create_project.monorepo.choose_repository.existing_already_bound_projects=This repository has already been imported, and it's linked to these projects in SonarQube:
+onboarding.create_project.monorepo.choose_repository.no_already_bound_projects=This repository has no imported projects in {productName}
+onboarding.create_project.monorepo.choose_repository.existing_already_bound_projects=This repository has already been imported, and it's linked to these projects in {productName}:
onboarding.create_project.monorepo.no_orgs=We couldn't load any organizations with your key. Contact an administrator.
onboarding.create_project.monorepo.no_orgs_admin=We couldn't load any organizations. Make sure the {almKey} App is installed in at least one organization and check the {almKey} instance configuration in the {link}.
onboarding.create_project.monorepo.no_projects=No projects could be fetch from {almKey}. Contact your system administrator.
onboarding.tutorial.ci_outro.done=And you are done!
onboarding.tutorial.ci_outro.refresh_text=If everything is running successfully, once the analysis is complete you'll be redirected to the Overview page of your project where the new analysis results will be displayed. This can take a few minutes.
onboarding.tutorial.ci_outro.commit=Commit and push your code to start the analysis.
-onboarding.tutorial.ci_outro.commit.why.gitlab=Each new push you make on your branches or merge requests will trigger a new analysis in SonarQube. We will decorate merge requests directly on GitLab for you.
-onboarding.tutorial.ci_outro.commit.why.github=Each new push you make on your branches or pull requests will trigger a new analysis in SonarQube. We will decorate pull requests directly on GitHub for you.
-onboarding.tutorial.ci_outro.commit.why.bitbucket=Each new push you make on your branches or pull requests will trigger a new analysis in SonarQube. We will decorate pull requests directly on Bitbucket for you.
-onboarding.tutorial.ci_outro.commit.why.bitbucketcloud=Each new push you make on your branches or pull requests will trigger a new analysis in SonarQube. We will decorate pull requests directly on Bitbucket for you.
-onboarding.tutorial.ci_outro.commit.why.azure=Each new push you make on your branches or pull requests will trigger a new analysis in SonarQube. We will decorate pull requests directly on Azure for you.
-onboarding.tutorial.ci_outro.commit.why.no_branches=Each new push you make on your main branch will trigger a new analysis in SonarQube.
+onboarding.tutorial.ci_outro.commit.why.gitlab=Each new push you make on your branches or merge requests will trigger a new analysis in {productName}. We will decorate merge requests directly on GitLab for you.
+onboarding.tutorial.ci_outro.commit.why.github=Each new push you make on your branches or pull requests will trigger a new analysis in {productName}. We will decorate pull requests directly on GitHub for you.
+onboarding.tutorial.ci_outro.commit.why.bitbucket=Each new push you make on your branches or pull requests will trigger a new analysis in {productName}. We will decorate pull requests directly on Bitbucket for you.
+onboarding.tutorial.ci_outro.commit.why.bitbucketcloud=Each new push you make on your branches or pull requests will trigger a new analysis in {productName}. We will decorate pull requests directly on Bitbucket for you.
+onboarding.tutorial.ci_outro.commit.why.azure=Each new push you make on your branches or pull requests will trigger a new analysis in {productName}. We will decorate pull requests directly on Azure for you.
+onboarding.tutorial.ci_outro.commit.why.no_branches=Each new push you make on your main branch will trigger a new analysis in {productName}.
onboarding.tutorial.ci_outro.refresh=This page will then refresh with your analysis results.
onboarding.tutorial.ci_outro.refresh.why=If the page doesn't refresh after a while, please double-check the analysis configuration, and check your logs.
onboarding.tutorial.other.project_key.sentence=Create a {file} file in your repository and paste the following code:
onboarding.tutorial.other.project_key.monorepo.info=Repeat this step for all the projects in your monorepo
onboarding.tutorial.cfamilly.compilation_database_info=If you have trouble using the Build Wrapper, you can try one of the alternative methods to {link}.
onboarding.tutorial.cfamilly.compilation_database_info.link=generate a compilation database
-onboarding.tutorial.cfamily.examples_repositories_description=Check out our C and C++ sample projects with SonarQube analysis configured
+onboarding.tutorial.cfamily.examples_repositories_description=Check out our C and C++ sample projects with {productName} analysis configured
onboarding.tutorial.page.title=Analysis Method
onboarding.tutorial.breadcrumbs.azure-pipelines=Azure Pipelines
onboarding.tutorial.breadcrumbs.bitbucket-pipelines=Bitbucket Pipelines
onboarding.mode.help.manual=Use this for testing or advanced use-case. Other modes are recommended to help you set up your CI environment.
-onboarding.mode.help.otherci=SonarQube integrates with your workflow no matter which CI tool you're using.
+onboarding.mode.help.otherci={productName} integrates with your workflow no matter which CI tool you're using.
onboarding.tutorial.with.yaml.gradle=Update your {groovy} or {kotlin} file with the {sq} plugin and its configuration:
onboarding.tutorial.with.gitlab_ci.variables.title=Add environment variables
onboarding.tutorial.with.gitlab_ci.variables.description.link=Settings > CI/CD > Variables
-onboarding.tutorial.with.gitlab_ci.variables.section.title=Define the SonarQube Token environment variable.
+onboarding.tutorial.with.gitlab_ci.variables.section.title=Define the {productName} Token environment variable.
onboarding.tutorial.with.gitlab_ci.variables.section.description=In GitLab, go to {link} to add the following variable and make sure it is available for your project:
onboarding.tutorial.with.gitlab_ci.variables.edit.token.tooltip=Use an existing token or generate a new one.
onboarding.tutorial.with.gitlab_ci.variables.step1=Key {value} {extra}
onboarding.tutorial.with.gitlab_ci.variables.step3.value=Protect Variable
onboarding.tutorial.with.gitlab_ci.variables.section.step4=Check the {value} checkbox.
onboarding.tutorial.with.gitlab_ci.variables.section.step4.value=Mask Variable
-onboarding.tutorial.with.gitlab_ci.variables.section2.title=Define the SonarQube URL environment variable.
+onboarding.tutorial.with.gitlab_ci.variables.section2.title=Define the {productName} URL environment variable.
onboarding.tutorial.with.gitlab_ci.variables.section2.description=Still in {link} add a new variable and make sure it is available for your project:
onboarding.tutorial.with.gitlab_ci.variables.section2.step4=Leave the {value} checkbox unchecked.
onboarding.tutorial.with.gitlab_ci.yaml.title=Create or update the configuration file
onboarding.tutorial.with.gitlab_ci.yaml.description=Create or update your {filename} file with the following content.
onboarding.tutorial.with.gitlab_ci.yaml.filename=.gitlab-ci.yml
-onboarding.tutorial.with.gitlab_ci.yaml.baseconfig=Note that this is a minimal base configuration to run a SonarQube analysis on your main branch and merge requests, and fetch the vulnerability report (if applicable).
+onboarding.tutorial.with.gitlab_ci.yaml.baseconfig=Note that this is a minimal base configuration to run a {productName} analysis on your main branch and merge requests, and fetch the vulnerability report (if applicable).
onboarding.tutorial.with.gitlab_ci.yaml.existing=If you already have a pipeline configured and running, you might want to add the example above to your existing yml file.
onboarding.tutorial.with.gitlab_ci.yaml.premium=GitLab vulnerability report is only available with GitLab Ultimate. You may safely remove the sonarqube-vulnerability-report stage if you have not subscribed to this service.
onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source.github=GitHub Branch Source plugin for Jenkins - version 2.7.1 or later
onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source.gitlab=GitLab Branch Source plugin for Jenkins - version 1.5.3 or later
onboarding.tutorial.with.jenkins.prereqs.plugins.gitlab_plugin=GitLab plugin for Jenkins - version 1.5.13 or later
-onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner=SonarQube Scanner plugin for Jenkins - version 2.11 or later
+onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner={productName} Scanner plugin for Jenkins - version 2.11 or later
onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide=For a step by step guide on installing and configuring those plugins in Jenkins, visit the {link} documentation page.
onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide.link=Analysis Prerequisites
onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations=We recommend using the configuration in the following steps for the best results, but you can customize it as needed.
onboarding.tutorial.with.jenkins.dotnet.scanner.prereqs.step5.sentence.install_from=Install from GitHub
onboarding.tutorial.with.jenkins.dotnet.scanner.prereqs.step5.sentence.install_auto=Install automatically
-onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.replace.sentence=Make sure to replace {default} with the name you gave to your SonarQube Scanner tool {in_jenkins}.
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.replace.sentence=Make sure to replace {default} with the name you gave to your {productName} Scanner tool {in_jenkins}.
onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.replace.sentence.default=SonarScanner
onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.replace.sentence.in_jenkins=in Jenkins
-onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help1.sentence=To get the name of your SonarQube Scanner tool in Jenkins, navigate to {path}.
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help1.sentence=To get the name of your {productName} Scanner tool in Jenkins, navigate to {path}.
onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help1.sentence.path=Manage Jenkins > Global Tool Configuration
onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence=The name is located under the {path} section, in the {name} field.
-onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence.path=SonarQube Scanner > SonarQube Scanner installations
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence.path={productName} Scanner > {productName} Scanner installations
onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence.name=Name
onboarding.tutorial.with.jenkins.jenkinsfile.cfamilly.agent_setup=We assume the Jenkins agent has the necessary tools to build your project.
onboarding.tutorial.with.azure_pipelines.os=What is your agent host?
onboarding.tutorial.with.azure_pipelines.architecture=What is your agent architecture?
onboarding.tutorial.with.azure_pipelines.title=Analyze your project with Azure DevOps Pipelines
-onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.title=Install SonarQube extension for Azure DevOps
+onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.title=Install {productName} extension for Azure DevOps
onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.sentence=From your Azure DevOps instance, navigate to the Visual Studio Marketplace and install the {link} by clicking the {button} button.
-onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.sentence.link=SonarQube extension
+onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.sentence.link={productName} extension
onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.sentence.button=Get it free
-onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.title=Add a new SonarQube Service Endpoint in your project
+onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.title=Add a new {productName} Service Endpoint in your project
onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step1.sentence=In Azure DevOps, go to {menu}.
onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step1.sentence.menu=Project settings > Service connections
onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step2.sentence=Add a new service connection of type {type}.
-onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step2.sentence.type=SonarQube
-onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step3.sentence=Enter your SonarQube server url: {url} {button}
+onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step2.sentence.type={productName}
+onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step3.sentence=Enter your {productName} server url: {url} {button}
onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step4.sentence=Enter an existing token, or a newly generated one
onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step5.sentence=Enter a memorable connection name.
onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step6.sentence=Create the service connection.
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.sentence.task=Prepare Analysis Configuration
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.sentence.before=before
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint.sentence=Select the {endpoint} you created in Step 2.
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint.sentence.endpoint=SonarQube server endpoint
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint.sentence.endpoint={productName} server endpoint
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis=Under {section}, select {run_analysis_value}.
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section=Choose the way to run the analysis
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.dotnet=Integrate with MSBuild
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java=Edit or add a new {0} task:
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings.sentence=Under {section}, check {option}
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings.sentence.section=Code Analysis
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings.sentence.option=Run SonarQube or SonarCloud Analysis
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.sentence=Add a new {task} task to publish SonarQube's Quality Gate results on your build pipeline summary.
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.info.sentence1=This task may increase your build time as your pipeline will have to wait for SonarQube to process the analysis report. It is highly recommended but optional.
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings.sentence.option=Run {productName} Analysis
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.sentence=Add a new {task} task to publish {productName}'s Quality Gate results on your build pipeline summary.
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.info.sentence1=This task may increase your build time as your pipeline will have to wait for {productName} to process the analysis report. It is highly recommended but optional.
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.sentence.task=Publish Quality Gate Result
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration.sentence=Under the {tab} tab of your pipeline, check {continuous_integration} and select all the branches for which you want the SonarQube analysis to run automatically.
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration.sentence=Under the {tab} tab of your pipeline, check {continuous_integration} and select all the branches for which you want the {productName} analysis to run automatically.
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration.sentence.tab=Triggers
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration.sentence.continuous_integration=Enable continuous integration
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration.no_branches.sentence=Under the {tab} tab of your pipeline, check {continuous_integration} and select the main branch
branch_like_navigation.orphan_pull_requests.tooltip=When the base of a Pull Request is deleted, this Pull Request becomes orphan.
branch_like_navigation.for_merge_into_x_from_y=for merge into {target} from {branch}
branch_like_navigation.for_merge_into_x_from_y.title=for merge into {0} from {1}
-branch_like_navigation.no_branch_support.title=Get the most out of SonarQube with branch and PR/MR analysis
-branch_like_navigation.no_branch_support.title.pr=Get the most out of SonarQube with branch and PR analysis
-branch_like_navigation.no_branch_support.title.mr=Get the most out of SonarQube with branch and MR analysis
-branch_like_navigation.no_branch_support.content=With Developer Edition you can analyze every pull/merge request. You can also watch the quality of your release branches by analyzing each one individually in SonarQube.
-branch_like_navigation.no_branch_support.content_x.pr=With Developer Edition you can analyze every pull request and get the results in {0}. You can also watch the quality of your release branches by analyzing each one individually in SonarQube.
-branch_like_navigation.no_branch_support.content_x.mr=With Developer Edition you can analyze every merge request and get the results in {0}. You can also watch the quality of your release branches by analyzing each one individually in SonarQube.
-branch_like_navigation.only_one_branch.title=Learn how to analyze branches in SonarQube
+branch_like_navigation.no_branch_support.title=Get the most out of {productName} with branch and PR/MR analysis
+branch_like_navigation.no_branch_support.title.pr=Get the most out of {productName} with branch and PR analysis
+branch_like_navigation.no_branch_support.title.mr=Get the most out of {productName} with branch and MR analysis
+branch_like_navigation.no_branch_support.content=With Developer Edition you can analyze every pull/merge request. You can also watch the quality of your release branches by analyzing each one individually in {productName}.
+branch_like_navigation.no_branch_support.content_x.pr=With Developer Edition you can analyze every pull request and get the results in {alm}. You can also watch the quality of your release branches by analyzing each one individually in {productName}.
+branch_like_navigation.no_branch_support.content_x.mr=With Developer Edition you can analyze every merge request and get the results in {alm}. You can also watch the quality of your release branches by analyzing each one individually in {productName}.
+branch_like_navigation.only_one_branch.title=Learn how to analyze branches in {productName}
branch_like_navigation.only_one_branch.content=Quickly set up branch analysis and get separate insights for each of your branches and Pull Requests.
branch_like_navigation.only_one_branch.documentation=Branches documentation
branch_like_navigation.only_one_branch.pr_analysis=Pull Request analysis
users.email=Email
users.email.invalid=Invalid email
users.last_connection=Last connection
-users.last_sonarlint_connection=Last SonarLint connection
-users.last_sonarlint_connection.help_text=The time of the last connection from SonarLint indicates that the user used SonarLint in connected mode.
+users.last_sonarlint_connection=Last SonarQube for IDE connection
+users.last_sonarlint_connection.help_text=The time of the last connection from SonarQube for IDE indicates that the user used SonarQube for IDE in connected mode.
users.update_users_groups=Update {0}'s group membership
users.view_users_groups=View {0}'s group membership
users.update_groups=Update Groups
users.search_description=Search users by login or name
users.activity_filter.label=Filter users by activity
users.activity_filter.placeholder=All users
-users.activity_filter.helptext.sonarqube=Users are considered active if they connected to SonarQube at least once in the past 30 days.
-users.activity_filter.helptext.sonarlint=Users are considered active with SonarLint if they used SonarLint in connected mode at least once in the past 30 days.
+users.activity_filter.helptext.sonarqube=Users are considered active if they connected to {productName} at least once in the past 30 days.
+users.activity_filter.helptext.sonarlint=Users are considered active with SonarQube for IDE if they used SonarQube for IDE in connected mode at least once in the past 30 days.
users.activity_filter.all_users=All users
-users.activity_filter.active_sonarlint_users=Active users with SonarLint
-users.activity_filter.active_sonarqube_users=Active users without SonarLint
+users.activity_filter.active_sonarlint_users=Active users with SonarQube for IDE
+users.activity_filter.active_sonarqube_users=Active users without SonarQube for IDE
users.activity_filter.inactive_users=Inactive users
users.tokens=Tokens
users.user_X_tokens=Tokens of {user}
users.generate_new_token=Generate New Token
users.new_token=New token value
users.change_admin_password.page=Change password
-users.change_admin_password.instance_is_at_risk=Secure your SonarQube instance
+users.change_admin_password.instance_is_at_risk=Secure your {productName} instance
users.change_admin_password.header=Default Administrator credentials are still used
-users.change_admin_password.description=Your SonarQube instance is still using default administrator credentials. You must change the password for the 'admin' account to secure your SonarQube instance.
+users.change_admin_password.description=Your {productName} instance is still using default administrator credentials. You must change the password for the 'admin' account to secure your {productName} instance.
users.change_admin_password.form.header=Change the password for user 'admin'
users.change_admin_password.form.success=The admin user's password was successfully changed.
-users.change_admin_password.form.continue_to_app=Continue to SonarQube
+users.change_admin_password.form.continue_to_app=Continue to {productName}
users.filter.by=Filter by
#------------------------------------------------------------------------------
maintenance.upgrade_database=Upgrade Database
maintenance.upgrade_database.1=The database upgrade can take several minutes.
maintenance.upgrade_database.2=It is mandatory to back up database before upgrading.
-maintenance.upgrade_database.3=Make sure you have followed the steps from the SonarQube Upgrade guide.
+maintenance.upgrade_database.3=Make sure you have followed the steps from the {productName} Upgrade guide.
maintenance.upgrade=Upgrade
maintenance.database_migration=Database Migration
maintenance.database_is_up_to_date=Database is up-to-date
maintenance.try_again=Try Again
maintenance.is_under_maintenance={instance} is under maintenance
maintenance.sonarqube_is_under_maintenance.1=While waiting, install {link} in your IDE!
-maintenance.sonarqube_is_under_maintenance_link.1=SonarLint
+maintenance.sonarqube_is_under_maintenance_link.1=SonarQube for IDE
maintenance.sonarqube_is_under_maintenance.2=If you are an administrator and have no idea why this message is being shown, you should read the {link}.
maintenance.sonarqube_is_under_maintenance_link.2=upgrade guide
maintenance.is_starting={instance} is starting
maintenance.is_up={instance} is up
maintenance.all_systems_opetational=All systems operational.
maintenance.is_offline={instance} is offline
-maintenance.sonarqube_is_offline.text=The connection to SonarQube is lost. Please contact your system administrator.
+maintenance.sonarqube_is_offline.text=The connection to {productName} is lost. Please contact your system administrator.
maintenance.running.progress={completed} migrations completed out of {total}
maintenance.running.estimate=Estimated completion time: {date}
indexation.progression_with_error={count} out of {total} projects reindexed with some {link}.
indexation.progression_with_error.link=tasks failing
indexation.completed=All project data has been reloaded.
-indexation.completed_with_error=SonarQube completed the reload of project data. Some {link} causing some projects to remain unavailable.
+indexation.completed_with_error={productName} completed the reload of project data. Some {link} causing some projects to remain unavailable.
indexation.completed_with_error.link=tasks failed or canceled
indexation.admin_link=See {link} for more information.
indexation.page_unavailable.title.issues=Issues page is temporarily unavailable
indexation.page_unavailable.title.portfolios=Portfolios page is temporarily unavailable
indexation.page_unavailable.title={componentQualifier} {componentName} is temporarily unavailable
-indexation.page_unavailable.description=SonarQube is reindexing project data.
+indexation.page_unavailable.description={productName} is reindexing project data.
indexation.page_unavailable.description.additional_information=This page is unavailable until this process is complete. {link}
indexation.filter_unavailable.description=This filter is unavailable until this process is complete.
indexation.learn_more=Learn more: