mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Enable ESLint rule that enforces t
when preferable to Trans
(#15253)
GitOrigin-RevId: d11b3f587b462d400a8d68128dc8be342415bf7d
This commit is contained in:
parent
0c81bccfca
commit
7755203ff7
29 changed files with 170 additions and 172 deletions
|
@ -114,7 +114,7 @@
|
||||||
//
|
//
|
||||||
"files": ["**/frontend/js/**/components/**/*.{js,jsx,ts,tsx}", "**/frontend/js/**/hooks/**/*.{js,jsx,ts,tsx}"],
|
"files": ["**/frontend/js/**/components/**/*.{js,jsx,ts,tsx}", "**/frontend/js/**/hooks/**/*.{js,jsx,ts,tsx}"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"@overleaf/no-empty-trans": "off",
|
"@overleaf/no-empty-trans": "error",
|
||||||
"@overleaf/should-unescape-trans": "error",
|
"@overleaf/should-unescape-trans": "error",
|
||||||
|
|
||||||
// https://astexplorer.net/
|
// https://astexplorer.net/
|
||||||
|
|
|
@ -92,7 +92,7 @@
|
||||||
"back_to_subscription": "",
|
"back_to_subscription": "",
|
||||||
"back_to_your_projects": "",
|
"back_to_your_projects": "",
|
||||||
"beta_program_already_participating": "",
|
"beta_program_already_participating": "",
|
||||||
"beta_program_benefits": "<0></0>",
|
"beta_program_benefits": "",
|
||||||
"beta_program_not_participating": "",
|
"beta_program_not_participating": "",
|
||||||
"binary_history_error": "",
|
"binary_history_error": "",
|
||||||
"blank_project": "",
|
"blank_project": "",
|
||||||
|
@ -288,7 +288,7 @@
|
||||||
"dropbox_sync_now_rate_limited": "",
|
"dropbox_sync_now_rate_limited": "",
|
||||||
"dropbox_sync_now_running": "",
|
"dropbox_sync_now_running": "",
|
||||||
"dropbox_sync_out": "",
|
"dropbox_sync_out": "",
|
||||||
"dropbox_sync_troubleshoot": "<0></0>",
|
"dropbox_sync_troubleshoot": "",
|
||||||
"dropbox_synced": "",
|
"dropbox_synced": "",
|
||||||
"dropbox_unlinked_premium_feature": "",
|
"dropbox_unlinked_premium_feature": "",
|
||||||
"duplicate_file": "",
|
"duplicate_file": "",
|
||||||
|
@ -305,7 +305,7 @@
|
||||||
"edit_tag": "",
|
"edit_tag": "",
|
||||||
"editing": "",
|
"editing": "",
|
||||||
"editing_captions": "",
|
"editing_captions": "",
|
||||||
"editor_and_pdf": "&",
|
"editor_and_pdf": "",
|
||||||
"editor_disconected_click_to_reconnect": "",
|
"editor_disconected_click_to_reconnect": "",
|
||||||
"editor_only_hide_pdf": "",
|
"editor_only_hide_pdf": "",
|
||||||
"editor_theme": "",
|
"editor_theme": "",
|
||||||
|
@ -567,7 +567,7 @@
|
||||||
"labels_help_you_to_easily_reference_your_figures": "",
|
"labels_help_you_to_easily_reference_your_figures": "",
|
||||||
"labels_help_you_to_reference_your_tables": "",
|
"labels_help_you_to_reference_your_tables": "",
|
||||||
"labs_program_already_participating": "",
|
"labs_program_already_participating": "",
|
||||||
"labs_program_benefits": "<0></0>",
|
"labs_program_benefits": "",
|
||||||
"labs_program_not_participating": "",
|
"labs_program_not_participating": "",
|
||||||
"large_or_high-resolution_images_taking_too_long": "",
|
"large_or_high-resolution_images_taking_too_long": "",
|
||||||
"last_active": "",
|
"last_active": "",
|
||||||
|
@ -1050,7 +1050,7 @@
|
||||||
"something_went_wrong_loading_pdf_viewer": "",
|
"something_went_wrong_loading_pdf_viewer": "",
|
||||||
"something_went_wrong_processing_the_request": "",
|
"something_went_wrong_processing_the_request": "",
|
||||||
"something_went_wrong_rendering_pdf": "",
|
"something_went_wrong_rendering_pdf": "",
|
||||||
"something_went_wrong_rendering_pdf_expected": "<0></0>",
|
"something_went_wrong_rendering_pdf_expected": "",
|
||||||
"something_went_wrong_server": "",
|
"something_went_wrong_server": "",
|
||||||
"somthing_went_wrong_compiling": "",
|
"somthing_went_wrong_compiling": "",
|
||||||
"sorry_your_table_cant_be_displayed_at_the_moment": "",
|
"sorry_your_table_cant_be_displayed_at_the_moment": "",
|
||||||
|
|
|
@ -171,7 +171,7 @@ function LayoutDropdownButton() {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
icon={<IconSplit />}
|
icon={<IconSplit />}
|
||||||
text={<Trans i18nKey="editor_and_pdf">&</Trans>}
|
text={t('editor_and_pdf')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<LayoutMenuItem
|
<LayoutMenuItem
|
||||||
|
|
|
@ -2,7 +2,7 @@ import ControlLabel from 'react-bootstrap/lib/ControlLabel'
|
||||||
import { Alert, FormControl } from 'react-bootstrap'
|
import { Alert, FormControl } from 'react-bootstrap'
|
||||||
import FormGroup from 'react-bootstrap/lib/FormGroup'
|
import FormGroup from 'react-bootstrap/lib/FormGroup'
|
||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useFileTreeCreateName } from '../../contexts/file-tree-create-name'
|
import { useFileTreeCreateName } from '../../contexts/file-tree-create-name'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import {
|
import {
|
||||||
|
@ -57,7 +57,7 @@ export default function FileTreeCreateNameInput({
|
||||||
|
|
||||||
{touchedName && !validName && (
|
{touchedName && !validName && (
|
||||||
<Alert bsStyle="danger" className="row-spaced-small">
|
<Alert bsStyle="danger" className="row-spaced-small">
|
||||||
<Trans i18nKey="files_cannot_include_invalid_characters" />
|
{t('files_cannot_include_invalid_characters')}
|
||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -77,6 +77,8 @@ FileTreeCreateNameInput.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ErrorMessage({ error }) {
|
function ErrorMessage({ error }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
// if (typeof error === 'string') {
|
// if (typeof error === 'string') {
|
||||||
// return error
|
// return error
|
||||||
// }
|
// }
|
||||||
|
@ -85,21 +87,21 @@ function ErrorMessage({ error }) {
|
||||||
case DuplicateFilenameError:
|
case DuplicateFilenameError:
|
||||||
return (
|
return (
|
||||||
<Alert bsStyle="danger" className="row-spaced-small">
|
<Alert bsStyle="danger" className="row-spaced-small">
|
||||||
<Trans i18nKey="file_already_exists" />
|
{t('file_already_exists')}
|
||||||
</Alert>
|
</Alert>
|
||||||
)
|
)
|
||||||
|
|
||||||
case InvalidFilenameError:
|
case InvalidFilenameError:
|
||||||
return (
|
return (
|
||||||
<Alert bsStyle="danger" className="row-spaced-small">
|
<Alert bsStyle="danger" className="row-spaced-small">
|
||||||
<Trans i18nKey="files_cannot_include_invalid_characters" />
|
{t('files_cannot_include_invalid_characters')}
|
||||||
</Alert>
|
</Alert>
|
||||||
)
|
)
|
||||||
|
|
||||||
case BlockedFilenameError:
|
case BlockedFilenameError:
|
||||||
return (
|
return (
|
||||||
<Alert bsStyle="danger" className="row-spaced-small">
|
<Alert bsStyle="danger" className="row-spaced-small">
|
||||||
<Trans i18nKey="blocked_filename" />
|
{t('blocked_filename')}
|
||||||
</Alert>
|
</Alert>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -154,21 +154,15 @@ function CompileTimeoutMessages() {
|
||||||
content={
|
content={
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<span>
|
<span>{t('your_project_near_compile_timeout_limit')}</span>
|
||||||
<Trans i18nKey="your_project_near_compile_timeout_limit" />
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
{showNewCompileTimeoutUI === 'active' ? (
|
{showNewCompileTimeoutUI === 'active' ? (
|
||||||
<>
|
<>
|
||||||
<strong>
|
<strong>{t('upgrade_for_12x_more_compile_time')}</strong>
|
||||||
<Trans i18nKey="upgrade_for_12x_more_compile_time" />
|
|
||||||
</strong>
|
|
||||||
{'. '}
|
{'. '}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<strong>
|
<strong>{t('upgrade_for_plenty_more_compile_time')}</strong>
|
||||||
<Trans i18nKey="upgrade_for_plenty_more_compile_time" />
|
|
||||||
</strong>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -204,7 +198,7 @@ function CompileTimeoutMessages() {
|
||||||
shouldUnescape
|
shouldUnescape
|
||||||
tOptions={{ interpolation: { escapeValue: true } }}
|
tOptions={{ interpolation: { escapeValue: true } }}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
<Trans i18nKey="and_you_can_upgrade_for_plenty_more_compile_time" />
|
{t('and_you_can_upgrade_for_plenty_more_compile_time')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -229,7 +223,9 @@ function CompileTimeoutMessages() {
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
<p className="row-spaced">
|
<p className="row-spaced">
|
||||||
<Trans i18nKey="tell_the_project_owner_to_upgrade_plan_for_more_compile_time" />
|
{t(
|
||||||
|
'tell_the_project_owner_to_upgrade_plan_for_more_compile_time'
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,17 @@ function PdfPreviewError({ error }) {
|
||||||
headerTitle={t('pdf_rendering_error')}
|
headerTitle={t('pdf_rendering_error')}
|
||||||
formattedContent={
|
formattedContent={
|
||||||
<>
|
<>
|
||||||
<Trans i18nKey="something_went_wrong_rendering_pdf_expected">
|
<Trans
|
||||||
<Button
|
i18nKey="something_went_wrong_rendering_pdf_expected"
|
||||||
bsSize="xs"
|
components={[
|
||||||
bsStyle="info"
|
// eslint-disable-next-line react/jsx-key
|
||||||
onClick={() => startCompile()}
|
<Button
|
||||||
/>
|
bsSize="xs"
|
||||||
</Trans>
|
bsStyle="info"
|
||||||
|
onClick={() => startCompile()}
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<Trans
|
<Trans
|
||||||
|
|
|
@ -78,10 +78,10 @@ const CompileTimeout = memo(function CompileTimeout({
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<strong>
|
<strong>{t('upgrade_for_12x_more_compile_time')}</strong>{' '}
|
||||||
<Trans i18nKey="upgrade_for_12x_more_compile_time" />
|
{t(
|
||||||
</strong>{' '}
|
'plus_additional_collaborators_document_history_track_changes_and_more'
|
||||||
<Trans i18nKey="plus_additional_collaborators_document_history_track_changes_and_more" />
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -154,9 +154,7 @@ export default function INRBanner({ variant, splitTestName }: INRBannerProps) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>{t('inr_discount_modal_info')}</p>
|
||||||
<Trans i18nKey="inr_discount_modal_info" />
|
|
||||||
</p>
|
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
<Modal.Footer>
|
<Modal.Footer>
|
||||||
<Button bsStyle="default" onClick={handleMaybeLater}>
|
<Button bsStyle="default" onClick={handleMaybeLater}>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import * as eventTracking from '../../../../infrastructure/event-tracking'
|
||||||
import getMeta from '../../../../utils/meta'
|
import getMeta from '../../../../utils/meta'
|
||||||
import customLocalStorage from '../../../../infrastructure/local-storage'
|
import customLocalStorage from '../../../../infrastructure/local-storage'
|
||||||
import { useProjectListContext } from '../../context/project-list-context'
|
import { useProjectListContext } from '../../context/project-list-context'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const variants = ['did-you-know', 'on-premise', 'people', 'FOMO'] as const
|
const variants = ['did-you-know', 'on-premise', 'people', 'FOMO'] as const
|
||||||
type GroupsAndEnterpriseBannerVariant = typeof variants[number]
|
type GroupsAndEnterpriseBannerVariant = typeof variants[number]
|
||||||
|
@ -64,7 +64,7 @@ export default function GroupsAndEnterpriseBanner() {
|
||||||
return (
|
return (
|
||||||
<Notification bsStyle="info" onDismiss={handleClose}>
|
<Notification bsStyle="info" onDismiss={handleClose}>
|
||||||
<Notification.Body>
|
<Notification.Body>
|
||||||
<span>{getText(groupsAndEnterpriseBannerVariant)}</span>
|
<BannerContent variant={groupsAndEnterpriseBannerVariant} />
|
||||||
</Notification.Body>
|
</Notification.Body>
|
||||||
<Notification.Action>
|
<Notification.Action>
|
||||||
<a
|
<a
|
||||||
|
@ -85,16 +85,40 @@ function isVariantValid(variant: GroupsAndEnterpriseBannerVariant) {
|
||||||
return variants.includes(variant)
|
return variants.includes(variant)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getText(variant: GroupsAndEnterpriseBannerVariant) {
|
function BannerContent({
|
||||||
|
variant,
|
||||||
|
}: {
|
||||||
|
variant: GroupsAndEnterpriseBannerVariant
|
||||||
|
}) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
case 'did-you-know':
|
case 'did-you-know':
|
||||||
return <Trans i18nKey="did_you_know_that_overleaf_offers" />
|
return <span>{t('did_you_know_that_overleaf_offers')}</span>
|
||||||
case 'on-premise':
|
case 'on-premise':
|
||||||
return 'Overleaf On-Premises: Does your company want to keep its data within its firewall? Overleaf offers Server Pro, an on-premises solution for companies. Get in touch to learn more.'
|
return (
|
||||||
|
<span>
|
||||||
|
Overleaf On-Premises: Does your company want to keep its data within
|
||||||
|
its firewall? Overleaf offers Server Pro, an on-premises solution for
|
||||||
|
companies. Get in touch to learn more.
|
||||||
|
</span>
|
||||||
|
)
|
||||||
case 'people':
|
case 'people':
|
||||||
return 'Other people at your company may already be using Overleaf. Save money with Overleaf group and company-wide subscriptions. Request more information.'
|
return (
|
||||||
|
<span>
|
||||||
|
Other people at your company may already be using Overleaf. Save money
|
||||||
|
with Overleaf group and company-wide subscriptions. Request more
|
||||||
|
information.
|
||||||
|
</span>
|
||||||
|
)
|
||||||
case 'FOMO':
|
case 'FOMO':
|
||||||
return 'Why do Fortune 500 companies and top research institutions trust Overleaf to streamline their collaboration? Get in touch to learn more.'
|
return (
|
||||||
|
<span>
|
||||||
|
Why do Fortune 500 companies and top research institutions trust
|
||||||
|
Overleaf to streamline their collaboration? Get in touch to learn
|
||||||
|
more.
|
||||||
|
</span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useTranslation, Trans } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import { useUserContext } from '../../../shared/context/user-context'
|
import { useUserContext } from '../../../shared/context/user-context'
|
||||||
|
|
||||||
function BetaProgramSection() {
|
function BetaProgramSection() {
|
||||||
|
@ -10,9 +10,8 @@ function BetaProgramSection() {
|
||||||
<h3>{t('sharelatex_beta_program')}</h3>
|
<h3>{t('sharelatex_beta_program')}</h3>
|
||||||
{betaProgram ? null : (
|
{betaProgram ? null : (
|
||||||
<p className="small">
|
<p className="small">
|
||||||
<Trans i18nKey="beta_program_benefits">
|
{/* eslint-disable-next-line react/jsx-key */}
|
||||||
<span />
|
<Trans i18nKey="beta_program_benefits" components={[<span />]} />
|
||||||
</Trans>
|
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<p className="small">
|
<p className="small">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useTranslation, Trans } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import { useUserContext } from '../../../shared/context/user-context'
|
import { useUserContext } from '../../../shared/context/user-context'
|
||||||
|
|
||||||
function LabsProgramSection() {
|
function LabsProgramSection() {
|
||||||
|
@ -10,9 +10,8 @@ function LabsProgramSection() {
|
||||||
<h3>{t('overleaf_labs')}</h3>
|
<h3>{t('overleaf_labs')}</h3>
|
||||||
{labsProgram ? null : (
|
{labsProgram ? null : (
|
||||||
<p className="small">
|
<p className="small">
|
||||||
<Trans i18nKey="labs_program_benefits">
|
{/* eslint-disable-next-line react/jsx-key */}
|
||||||
<span />
|
<Trans i18nKey="labs_program_benefits" components={[<span />]} />
|
||||||
</Trans>
|
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<p className="small">
|
<p className="small">
|
||||||
|
|
|
@ -7,13 +7,13 @@ export default function AddCollaboratorsUpgradeContentDefault() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p className="text-center">
|
<p className="text-center">
|
||||||
<Trans i18nKey="need_to_upgrade_for_more_collabs" />. {t('also')}:
|
{t('need_to_upgrade_for_more_collabs')}. {t('also')}:
|
||||||
</p>
|
</p>
|
||||||
<ul className="list-unstyled">
|
<ul className="list-unstyled">
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
|
||||||
<Trans i18nKey="unlimited_projects" />
|
{t('unlimited_projects')}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
@ -28,22 +28,22 @@ export default function AddCollaboratorsUpgradeContentDefault() {
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
|
||||||
<Trans i18nKey="full_doc_history" />
|
{t('full_doc_history')}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
|
||||||
<Trans i18nKey="sync_to_dropbox" />
|
{t('sync_to_dropbox')}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
|
||||||
<Trans i18nKey="sync_to_github" />
|
{t('sync_to_github')}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
|
||||||
<Trans i18nKey="compile_larger_projects" />
|
{t('compile_larger_projects')}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import Icon from '../../../shared/components/icon'
|
import Icon from '../../../shared/components/icon'
|
||||||
import { Trans } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
export default function AddCollaboratorsUpgradeContentVariant() {
|
export default function AddCollaboratorsUpgradeContentVariant() {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-xs-10 col-xs-offset-1">
|
<div className="col-xs-10 col-xs-offset-1">
|
||||||
<p className="text-center">
|
<p className="text-center">
|
||||||
<Trans i18nKey="need_to_upgrade_for_more_collabs_variant" />
|
{t('need_to_upgrade_for_more_collabs_variant')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,7 +18,7 @@ export default function AddCollaboratorsUpgradeContentVariant() {
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
|
||||||
<Trans i18nKey="unlimited_projects" />
|
{t('unlimited_projects')}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
@ -31,24 +33,24 @@ export default function AddCollaboratorsUpgradeContentVariant() {
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
|
||||||
<Trans i18nKey="full_doc_history" />
|
{t('full_doc_history')}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul className="list-unstyled col-xs-5">
|
<ul className="list-unstyled col-xs-5">
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
|
||||||
<Trans i18nKey="sync_to_dropbox" />
|
{t('sync_to_dropbox')}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
|
||||||
<Trans i18nKey="sync_to_github" />
|
{t('sync_to_github')}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Icon type="check" />
|
<Icon type="check" />
|
||||||
|
|
||||||
<Trans i18nKey="compile_larger_projects" />
|
{t('compile_larger_projects')}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { Trans } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Button } from 'react-bootstrap'
|
import { Button } from 'react-bootstrap'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import AddCollaboratorsUpgradeContentVariant from './add-collaborators-upgrade-c
|
||||||
import { useSplitTestContext } from '../../../shared/context/split-test-context'
|
import { useSplitTestContext } from '../../../shared/context/split-test-context'
|
||||||
|
|
||||||
export default function AddCollaboratorsUpgrade() {
|
export default function AddCollaboratorsUpgrade() {
|
||||||
|
const { t } = useTranslation()
|
||||||
const user = useUserContext({
|
const user = useUserContext({
|
||||||
allowedFreeTrial: PropTypes.bool,
|
allowedFreeTrial: PropTypes.bool,
|
||||||
})
|
})
|
||||||
|
@ -45,14 +46,12 @@ export default function AddCollaboratorsUpgrade() {
|
||||||
setStartedFreeTrial(true)
|
setStartedFreeTrial(true)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Trans i18nKey="upgrade" />
|
{t('upgrade')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
{startedFreeTrial && (
|
{startedFreeTrial && (
|
||||||
<p className="small">
|
<p className="small">{t('refresh_page_after_starting_free_trial')}</p>
|
||||||
<Trans i18nKey="refresh_page_after_starting_free_trial" />
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useState, useMemo } from 'react'
|
import { useState, useMemo } from 'react'
|
||||||
import { useTranslation, Trans } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Form, FormGroup, FormControl, Button } from 'react-bootstrap'
|
import { Form, FormGroup, FormControl, Button } from 'react-bootstrap'
|
||||||
import { useMultipleSelection } from 'downshift'
|
import { useMultipleSelection } from 'downshift'
|
||||||
import { useShareProjectContext } from './share-project-modal'
|
import { useShareProjectContext } from './share-project-modal'
|
||||||
|
@ -152,7 +152,7 @@ export default function AddCollaborators() {
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<span> </span>
|
<span> </span>
|
||||||
<Button type="submit" bsStyle="primary">
|
<Button type="submit" bsStyle="primary">
|
||||||
<Trans i18nKey="share" />
|
{t('share')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useShareProjectContext } from './share-project-modal'
|
import { useShareProjectContext } from './share-project-modal'
|
||||||
import TransferOwnershipModal from './transfer-ownership-modal'
|
import TransferOwnershipModal from './transfer-ownership-modal'
|
||||||
import { removeMemberFromProject, updateMember } from '../utils/api'
|
import { removeMemberFromProject, updateMember } from '../utils/api'
|
||||||
|
@ -137,7 +137,7 @@ function RemoveMemberAction({ member }) {
|
||||||
<FormControl.Static className="text-center">
|
<FormControl.Static className="text-center">
|
||||||
<Tooltip
|
<Tooltip
|
||||||
id="remove-collaborator"
|
id="remove-collaborator"
|
||||||
description={<Trans i18nKey="remove_collaborator" />}
|
description={t('remove_collaborator')}
|
||||||
overlayProps={{ placement: 'bottom' }}
|
overlayProps={{ placement: 'bottom' }}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
|
@ -163,16 +163,18 @@ RemoveMemberAction.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ChangePrivilegesActions({ handleReset }) {
|
function ChangePrivilegesActions({ handleReset }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<Button type="submit" bsSize="sm" bsStyle="primary">
|
<Button type="submit" bsSize="sm" bsStyle="primary">
|
||||||
<Trans i18nKey="change_or_cancel-change" />
|
{t('change_or_cancel-change')}
|
||||||
</Button>
|
</Button>
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<Trans i18nKey="change_or_cancel-or" />
|
{t('change_or_cancel-or')}
|
||||||
|
|
||||||
<Button type="button" className="btn-inline-link" onClick={handleReset}>
|
<Button type="button" className="btn-inline-link" onClick={handleReset}>
|
||||||
<Trans i18nKey="change_or_cancel-cancel" />
|
{t('change_or_cancel-cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,20 +4,21 @@ import { useShareProjectContext } from './share-project-modal'
|
||||||
import Icon from '../../../shared/components/icon'
|
import Icon from '../../../shared/components/icon'
|
||||||
import { Button, Col, Row } from 'react-bootstrap'
|
import { Button, Col, Row } from 'react-bootstrap'
|
||||||
import Tooltip from '../../../shared/components/tooltip'
|
import Tooltip from '../../../shared/components/tooltip'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import MemberPrivileges from './member-privileges'
|
import MemberPrivileges from './member-privileges'
|
||||||
import { resendInvite, revokeInvite } from '../utils/api'
|
import { resendInvite, revokeInvite } from '../utils/api'
|
||||||
import { useProjectContext } from '../../../shared/context/project-context'
|
import { useProjectContext } from '../../../shared/context/project-context'
|
||||||
import { sendMB } from '../../../infrastructure/event-tracking'
|
import { sendMB } from '../../../infrastructure/event-tracking'
|
||||||
|
|
||||||
export default function Invite({ invite, isProjectOwner }) {
|
export default function Invite({ invite, isProjectOwner }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
return (
|
return (
|
||||||
<Row className="project-invite">
|
<Row className="project-invite">
|
||||||
<Col xs={7}>
|
<Col xs={7}>
|
||||||
<div>{invite.email}</div>
|
<div>{invite.email}</div>
|
||||||
|
|
||||||
<div className="small">
|
<div className="small">
|
||||||
<Trans i18nKey="invite_not_accepted" />
|
{t('invite_not_accepted')}
|
||||||
.
|
.
|
||||||
{isProjectOwner && <ResendInvite invite={invite} />}
|
{isProjectOwner && <ResendInvite invite={invite} />}
|
||||||
</div>
|
</div>
|
||||||
|
@ -42,6 +43,7 @@ Invite.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ResendInvite({ invite }) {
|
function ResendInvite({ invite }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
const { monitorRequest } = useShareProjectContext()
|
const { monitorRequest } = useShareProjectContext()
|
||||||
const { _id: projectId } = useProjectContext()
|
const { _id: projectId } = useProjectContext()
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ function ResendInvite({ invite }) {
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
// ref={buttonRef}
|
// ref={buttonRef}
|
||||||
>
|
>
|
||||||
<Trans i18nKey="resend" />
|
{t('resend')}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -99,7 +101,7 @@ function RevokeInvite({ invite }) {
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
id="revoke-invite"
|
id="revoke-invite"
|
||||||
description={<Trans i18nKey="revoke_invite" />}
|
description={t('revoke_invite')}
|
||||||
overlayProps={{ placement: 'bottom' }}
|
overlayProps={{ placement: 'bottom' }}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useCallback, useState, useEffect } from 'react'
|
import { useCallback, useState, useEffect } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Button, Col, Row } from 'react-bootstrap'
|
import { Button, Col, Row } from 'react-bootstrap'
|
||||||
import { Trans } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Tooltip from '../../../shared/components/tooltip'
|
import Tooltip from '../../../shared/components/tooltip'
|
||||||
import Icon from '../../../shared/components/icon'
|
import Icon from '../../../shared/components/icon'
|
||||||
import { useShareProjectContext } from './share-project-modal'
|
import { useShareProjectContext } from './share-project-modal'
|
||||||
|
@ -86,10 +86,11 @@ LinkSharing.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function PrivateSharing({ setAccessLevel, inflight, projectId }) {
|
function PrivateSharing({ setAccessLevel, inflight, projectId }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
return (
|
return (
|
||||||
<Row className="public-access-level">
|
<Row className="public-access-level">
|
||||||
<Col xs={12} className="text-center">
|
<Col xs={12} className="text-center">
|
||||||
<Trans i18nKey="link_sharing_is_off" />
|
{t('link_sharing_is_off')}
|
||||||
<span> </span>
|
<span> </span>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -101,7 +102,7 @@ function PrivateSharing({ setAccessLevel, inflight, projectId }) {
|
||||||
}}
|
}}
|
||||||
disabled={inflight}
|
disabled={inflight}
|
||||||
>
|
>
|
||||||
<Trans i18nKey="turn_on_link_sharing" />
|
{t('turn_on_link_sharing')}
|
||||||
</Button>
|
</Button>
|
||||||
<span> </span>
|
<span> </span>
|
||||||
<LinkSharingInfo />
|
<LinkSharingInfo />
|
||||||
|
@ -117,6 +118,7 @@ PrivateSharing.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function TokenBasedSharing({ setAccessLevel, inflight, canAddCollaborators }) {
|
function TokenBasedSharing({ setAccessLevel, inflight, canAddCollaborators }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
const { _id: projectId } = useProjectContext()
|
const { _id: projectId } = useProjectContext()
|
||||||
|
|
||||||
const [tokens, setTokens] = useState(null)
|
const [tokens, setTokens] = useState(null)
|
||||||
|
@ -132,9 +134,7 @@ function TokenBasedSharing({ setAccessLevel, inflight, canAddCollaborators }) {
|
||||||
return (
|
return (
|
||||||
<Row className="public-access-level">
|
<Row className="public-access-level">
|
||||||
<Col xs={12} className="text-center">
|
<Col xs={12} className="text-center">
|
||||||
<strong>
|
<strong>{t('link_sharing_is_on')}</strong>
|
||||||
<Trans i18nKey="link_sharing_is_on" />
|
|
||||||
</strong>
|
|
||||||
<span> </span>
|
<span> </span>
|
||||||
<Button
|
<Button
|
||||||
bsStyle="link"
|
bsStyle="link"
|
||||||
|
@ -142,16 +142,14 @@ function TokenBasedSharing({ setAccessLevel, inflight, canAddCollaborators }) {
|
||||||
onClick={() => setAccessLevel('private')}
|
onClick={() => setAccessLevel('private')}
|
||||||
disabled={inflight}
|
disabled={inflight}
|
||||||
>
|
>
|
||||||
<Trans i18nKey="turn_off_link_sharing" />
|
{t('turn_off_link_sharing')}
|
||||||
</Button>
|
</Button>
|
||||||
<span> </span>
|
<span> </span>
|
||||||
<LinkSharingInfo />
|
<LinkSharingInfo />
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={12} className="access-token-display-area">
|
<Col xs={12} className="access-token-display-area">
|
||||||
<div className="access-token-wrapper">
|
<div className="access-token-wrapper">
|
||||||
<strong>
|
<strong>{t('anyone_with_link_can_edit')}</strong>
|
||||||
<Trans i18nKey="anyone_with_link_can_edit" />
|
|
||||||
</strong>
|
|
||||||
<AccessToken
|
<AccessToken
|
||||||
token={tokens?.readAndWrite}
|
token={tokens?.readAndWrite}
|
||||||
path="/"
|
path="/"
|
||||||
|
@ -159,9 +157,7 @@ function TokenBasedSharing({ setAccessLevel, inflight, canAddCollaborators }) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="access-token-wrapper">
|
<div className="access-token-wrapper">
|
||||||
<strong>
|
<strong>{t('anyone_with_link_can_view')}</strong>
|
||||||
<Trans i18nKey="anyone_with_link_can_view" />
|
|
||||||
</strong>
|
|
||||||
<AccessToken
|
<AccessToken
|
||||||
token={tokens?.readOnly}
|
token={tokens?.readOnly}
|
||||||
path="/read/"
|
path="/read/"
|
||||||
|
@ -180,16 +176,14 @@ TokenBasedSharing.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function LegacySharing({ accessLevel, setAccessLevel, inflight }) {
|
function LegacySharing({ accessLevel, setAccessLevel, inflight }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className="public-access-level">
|
<Row className="public-access-level">
|
||||||
<Col xs={12} className="text-center">
|
<Col xs={12} className="text-center">
|
||||||
<strong>
|
<strong>
|
||||||
{accessLevel === 'readAndWrite' && (
|
{accessLevel === 'readAndWrite' && t('this_project_is_public')}
|
||||||
<Trans i18nKey="this_project_is_public" />
|
{accessLevel === 'readOnly' && t('this_project_is_public_read_only')}
|
||||||
)}
|
|
||||||
{accessLevel === 'readOnly' && (
|
|
||||||
<Trans i18nKey="this_project_is_public_read_only" />
|
|
||||||
)}
|
|
||||||
</strong>
|
</strong>
|
||||||
<span> </span>
|
<span> </span>
|
||||||
<Button
|
<Button
|
||||||
|
@ -199,7 +193,7 @@ function LegacySharing({ accessLevel, setAccessLevel, inflight }) {
|
||||||
onClick={() => setAccessLevel('private')}
|
onClick={() => setAccessLevel('private')}
|
||||||
disabled={inflight}
|
disabled={inflight}
|
||||||
>
|
>
|
||||||
<Trans i18nKey="make_private" />
|
{t('make_private')}
|
||||||
</Button>
|
</Button>
|
||||||
<span> </span>
|
<span> </span>
|
||||||
<LinkSharingInfo />
|
<LinkSharingInfo />
|
||||||
|
@ -215,6 +209,7 @@ LegacySharing.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ReadOnlyTokenLink() {
|
export function ReadOnlyTokenLink() {
|
||||||
|
const { t } = useTranslation()
|
||||||
const { _id: projectId } = useProjectContext()
|
const { _id: projectId } = useProjectContext()
|
||||||
|
|
||||||
const [tokens, setTokens] = useState(null)
|
const [tokens, setTokens] = useState(null)
|
||||||
|
@ -231,9 +226,7 @@ export function ReadOnlyTokenLink() {
|
||||||
<Row className="public-access-level">
|
<Row className="public-access-level">
|
||||||
<Col xs={12} className="access-token-display-area">
|
<Col xs={12} className="access-token-display-area">
|
||||||
<div className="access-token-wrapper">
|
<div className="access-token-wrapper">
|
||||||
<strong>
|
<strong>{t('anyone_with_link_can_view')}</strong>
|
||||||
<Trans i18nKey="anyone_with_link_can_view" />
|
|
||||||
</strong>
|
|
||||||
<AccessToken
|
<AccessToken
|
||||||
token={tokens?.readOnly}
|
token={tokens?.readOnly}
|
||||||
path="/read/"
|
path="/read/"
|
||||||
|
@ -246,14 +239,13 @@ export function ReadOnlyTokenLink() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function AccessToken({ token, path, tooltipId }) {
|
function AccessToken({ token, path, tooltipId }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
const { isAdmin } = useUserContext()
|
const { isAdmin } = useUserContext()
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return (
|
return (
|
||||||
<pre className="access-token">
|
<pre className="access-token">
|
||||||
<span>
|
<span>{t('loading')}…</span>
|
||||||
<Trans i18nKey="loading" />…
|
|
||||||
</span>
|
|
||||||
</pre>
|
</pre>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -279,10 +271,12 @@ AccessToken.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function LinkSharingInfo() {
|
function LinkSharingInfo() {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
id="link-sharing-info"
|
id="link-sharing-info"
|
||||||
description={<Trans i18nKey="learn_more_about_link_sharing" />}
|
description={t('learn_more_about_link_sharing')}
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href="/learn/how-to/What_is_Link_Sharing%3F"
|
href="/learn/how-to/What_is_Link_Sharing%3F"
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Trans } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
export default function MemberPrivileges({ privileges }) {
|
export default function MemberPrivileges({ privileges }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
switch (privileges) {
|
switch (privileges) {
|
||||||
case 'readAndWrite':
|
case 'readAndWrite':
|
||||||
return <Trans i18nKey="can_edit" />
|
return t('can_edit')
|
||||||
|
|
||||||
case 'readOnly':
|
case 'readOnly':
|
||||||
return <Trans i18nKey="read_only" />
|
return t('read_only')
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
import { useProjectContext } from '../../../shared/context/project-context'
|
import { useProjectContext } from '../../../shared/context/project-context'
|
||||||
import { Col, Row } from 'react-bootstrap'
|
import { Col, Row } from 'react-bootstrap'
|
||||||
import { Trans } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
export default function OwnerInfo() {
|
export default function OwnerInfo() {
|
||||||
|
const { t } = useTranslation()
|
||||||
const { owner } = useProjectContext()
|
const { owner } = useProjectContext()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className="project-member">
|
<Row className="project-member">
|
||||||
<Col xs={7}>{owner?.email}</Col>
|
<Col xs={7}>{owner?.email}</Col>
|
||||||
<Col xs={3} className="text-left">
|
<Col xs={3} className="text-left">
|
||||||
<Trans i18nKey="owner" />
|
{t('owner')}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useEffect, useMemo, useState, useRef, useCallback } from 'react'
|
import { useEffect, useMemo, useState, useRef, useCallback } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { matchSorter } from 'match-sorter'
|
import { matchSorter } from 'match-sorter'
|
||||||
import { useCombobox } from 'downshift'
|
import { useCombobox } from 'downshift'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
@ -19,6 +19,7 @@ export default function SelectCollaborators({
|
||||||
placeholder,
|
placeholder,
|
||||||
multipleSelectionProps,
|
multipleSelectionProps,
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useTranslation()
|
||||||
const {
|
const {
|
||||||
getSelectedItemProps,
|
getSelectedItemProps,
|
||||||
getDropdownProps,
|
getDropdownProps,
|
||||||
|
@ -141,7 +142,7 @@ export default function SelectCollaborators({
|
||||||
<div className="tags-input">
|
<div className="tags-input">
|
||||||
{/* eslint-disable-next-line jsx-a11y/label-has-for */}
|
{/* eslint-disable-next-line jsx-a11y/label-has-for */}
|
||||||
<label className="small" {...getLabelProps()}>
|
<label className="small" {...getLabelProps()}>
|
||||||
<Trans i18nKey="share_with_your_collabs" />
|
{t('share_with_your_collabs')}
|
||||||
|
|
||||||
{loading && <Icon type="refresh" spin />}
|
{loading && <Icon type="refresh" spin />}
|
||||||
</label>
|
</label>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Col, Row } from 'react-bootstrap'
|
import { Col, Row } from 'react-bootstrap'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Trans } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useProjectContext } from '../../../shared/context/project-context'
|
import { useProjectContext } from '../../../shared/context/project-context'
|
||||||
|
|
||||||
export default function SendInvitesNotice() {
|
export default function SendInvitesNotice() {
|
||||||
|
@ -16,12 +16,13 @@ export default function SendInvitesNotice() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function AccessLevel({ level }) {
|
function AccessLevel({ level }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case 'private':
|
case 'private':
|
||||||
return <Trans i18nKey="to_add_more_collaborators" />
|
return t('to_add_more_collaborators')
|
||||||
|
|
||||||
case 'tokenBased':
|
case 'tokenBased':
|
||||||
return <Trans i18nKey="to_change_access_permissions" />
|
return t('to_change_access_permissions')
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Button, Modal, Grid } from 'react-bootstrap'
|
import { Button, Modal, Grid } from 'react-bootstrap'
|
||||||
import { Trans } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Icon from '../../../shared/components/icon'
|
import Icon from '../../../shared/components/icon'
|
||||||
import AccessibleModal from '../../../shared/components/accessible-modal'
|
import AccessibleModal from '../../../shared/components/accessible-modal'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
@ -23,6 +23,8 @@ export default function ShareProjectModalContent({
|
||||||
inFlight,
|
inFlight,
|
||||||
error,
|
error,
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const { isRestrictedTokenMember } = useEditorContext({
|
const { isRestrictedTokenMember } = useEditorContext({
|
||||||
isRestrictedTokenMember: PropTypes.bool,
|
isRestrictedTokenMember: PropTypes.bool,
|
||||||
})
|
})
|
||||||
|
@ -30,9 +32,7 @@ export default function ShareProjectModalContent({
|
||||||
return (
|
return (
|
||||||
<AccessibleModal show={show} onHide={cancel} animation={animation}>
|
<AccessibleModal show={show} onHide={cancel} animation={animation}>
|
||||||
<Modal.Header closeButton>
|
<Modal.Header closeButton>
|
||||||
<Modal.Title>
|
<Modal.Title>{t('share_project')}</Modal.Title>
|
||||||
<Trans i18nKey="share_project" />
|
|
||||||
</Modal.Title>
|
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
|
|
||||||
<Modal.Body className="modal-body-share">
|
<Modal.Body className="modal-body-share">
|
||||||
|
@ -65,7 +65,7 @@ export default function ShareProjectModalContent({
|
||||||
className="btn-secondary"
|
className="btn-secondary"
|
||||||
disabled={inFlight}
|
disabled={inFlight}
|
||||||
>
|
>
|
||||||
<Trans i18nKey="close" />
|
{t('close')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Modal.Footer>
|
</Modal.Footer>
|
||||||
|
@ -81,24 +81,26 @@ ShareProjectModalContent.propTypes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ErrorMessage({ error }) {
|
function ErrorMessage({ error }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case 'cannot_invite_non_user':
|
case 'cannot_invite_non_user':
|
||||||
return <Trans i18nKey="cannot_invite_non_user" />
|
return t('cannot_invite_non_user')
|
||||||
|
|
||||||
case 'cannot_verify_user_not_robot':
|
case 'cannot_verify_user_not_robot':
|
||||||
return <Trans i18nKey="cannot_verify_user_not_robot" />
|
return t('cannot_verify_user_not_robot')
|
||||||
|
|
||||||
case 'cannot_invite_self':
|
case 'cannot_invite_self':
|
||||||
return <Trans i18nKey="cannot_invite_self" />
|
return t('cannot_invite_self')
|
||||||
|
|
||||||
case 'invalid_email':
|
case 'invalid_email':
|
||||||
return <Trans i18nKey="invalid_email" />
|
return t('invalid_email')
|
||||||
|
|
||||||
case 'too_many_requests':
|
case 'too_many_requests':
|
||||||
return <Trans i18nKey="too_many_requests" />
|
return t('too_many_requests')
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return <Trans i18nKey="generic_something_went_wrong" />
|
return t('generic_something_went_wrong')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ErrorMessage.propTypes = {
|
ErrorMessage.propTypes = {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { Modal, Button } from 'react-bootstrap'
|
import { Modal, Button } from 'react-bootstrap'
|
||||||
import { Trans } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import Icon from '../../../shared/components/icon'
|
import Icon from '../../../shared/components/icon'
|
||||||
import { transferProjectOwnership } from '../utils/api'
|
import { transferProjectOwnership } from '../utils/api'
|
||||||
|
@ -9,6 +9,8 @@ import { useProjectContext } from '../../../shared/context/project-context'
|
||||||
import { useLocation } from '../../../shared/hooks/use-location'
|
import { useLocation } from '../../../shared/hooks/use-location'
|
||||||
|
|
||||||
export default function TransferOwnershipModal({ member, cancel }) {
|
export default function TransferOwnershipModal({ member, cancel }) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const [inflight, setInflight] = useState(false)
|
const [inflight, setInflight] = useState(false)
|
||||||
const [error, setError] = useState(false)
|
const [error, setError] = useState(false)
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
@ -32,9 +34,7 @@ export default function TransferOwnershipModal({ member, cancel }) {
|
||||||
return (
|
return (
|
||||||
<AccessibleModal show onHide={cancel}>
|
<AccessibleModal show onHide={cancel}>
|
||||||
<Modal.Header closeButton>
|
<Modal.Header closeButton>
|
||||||
<Modal.Title>
|
<Modal.Title>{t('change_project_owner')}</Modal.Title>
|
||||||
<Trans i18nKey="change_project_owner" />
|
|
||||||
</Modal.Title>
|
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
<p>
|
<p>
|
||||||
|
@ -47,16 +47,14 @@ export default function TransferOwnershipModal({ member, cancel }) {
|
||||||
tOptions={{ interpolation: { escapeValue: true } }}
|
tOptions={{ interpolation: { escapeValue: true } }}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>{t('project_ownership_transfer_confirmation_2')}</p>
|
||||||
<Trans i18nKey="project_ownership_transfer_confirmation_2" />
|
|
||||||
</p>
|
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
<Modal.Footer>
|
<Modal.Footer>
|
||||||
<div className="modal-footer-left">
|
<div className="modal-footer-left">
|
||||||
{inflight && <Icon type="refresh" spin />}
|
{inflight && <Icon type="refresh" spin />}
|
||||||
{error && (
|
{error && (
|
||||||
<span className="text-danger">
|
<span className="text-danger">
|
||||||
<Trans i18nKey="generic_something_went_wrong" />
|
{t('generic_something_went_wrong')}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -68,7 +66,7 @@ export default function TransferOwnershipModal({ member, cancel }) {
|
||||||
onClick={cancel}
|
onClick={cancel}
|
||||||
disabled={inflight}
|
disabled={inflight}
|
||||||
>
|
>
|
||||||
<Trans i18nKey="cancel" />
|
{t('cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -76,7 +74,7 @@ export default function TransferOwnershipModal({ member, cancel }) {
|
||||||
onClick={confirm}
|
onClick={confirm}
|
||||||
disabled={inflight}
|
disabled={inflight}
|
||||||
>
|
>
|
||||||
<Trans i18nKey="change_owner" />
|
{t('change_owner')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Modal.Footer>
|
</Modal.Footer>
|
||||||
|
|
|
@ -9,13 +9,9 @@ export const FigureModalHelp = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p>
|
<p>{t('this_tool_helps_you_insert_figures')}</p>
|
||||||
<Trans i18nKey="this_tool_helps_you_insert_figures" />
|
|
||||||
</p>
|
|
||||||
<b>{t('editing_captions')}</b>
|
<b>{t('editing_captions')}</b>
|
||||||
<p>
|
<p>{t('when_you_tick_the_include_caption_box')}</p>
|
||||||
<Trans i18nKey="when_you_tick_the_include_caption_box" />
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<b>{t('understanding_labels')}</b>
|
<b>{t('understanding_labels')}</b>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -410,7 +410,7 @@
|
||||||
"edit_tag": "Redigér tag",
|
"edit_tag": "Redigér tag",
|
||||||
"editing": "Redigering",
|
"editing": "Redigering",
|
||||||
"editing_captions": "Redigering af billedtekster",
|
"editing_captions": "Redigering af billedtekster",
|
||||||
"editor_and_pdf": "Skrivevindue <0></0> PDF",
|
"editor_and_pdf": "Skrivevindue & PDF",
|
||||||
"editor_disconected_click_to_reconnect": "Skriveprogrammets forbindelse afbrudt, klik hvor som helst for at forbinde igen.",
|
"editor_disconected_click_to_reconnect": "Skriveprogrammets forbindelse afbrudt, klik hvor som helst for at forbinde igen.",
|
||||||
"editor_only_hide_pdf": "Kun skrivevindue <0>(gem PDF)</0>",
|
"editor_only_hide_pdf": "Kun skrivevindue <0>(gem PDF)</0>",
|
||||||
"editor_resources": "Læringsmidler til skriveprogrammet",
|
"editor_resources": "Læringsmidler til skriveprogrammet",
|
||||||
|
|
|
@ -412,7 +412,7 @@
|
||||||
"edit_tag": "Schlagwort bearbeiten",
|
"edit_tag": "Schlagwort bearbeiten",
|
||||||
"editing": "Bearbeitung",
|
"editing": "Bearbeitung",
|
||||||
"editing_captions": "Beschriftungen bearbeiten",
|
"editing_captions": "Beschriftungen bearbeiten",
|
||||||
"editor_and_pdf": "Editor <0></0> PDF",
|
"editor_and_pdf": "Editor & PDF",
|
||||||
"editor_disconected_click_to_reconnect": "Editor wurde getrennt",
|
"editor_disconected_click_to_reconnect": "Editor wurde getrennt",
|
||||||
"editor_only_hide_pdf": "Nur Editor <0>(PDF ausblenden)</0>",
|
"editor_only_hide_pdf": "Nur Editor <0>(PDF ausblenden)</0>",
|
||||||
"editor_resources": "Editor-Literatur",
|
"editor_resources": "Editor-Literatur",
|
||||||
|
|
|
@ -460,7 +460,7 @@
|
||||||
"edit_tag": "Edit Tag",
|
"edit_tag": "Edit Tag",
|
||||||
"editing": "Editing",
|
"editing": "Editing",
|
||||||
"editing_captions": "Editing captions",
|
"editing_captions": "Editing captions",
|
||||||
"editor_and_pdf": "Editor <0></0> PDF",
|
"editor_and_pdf": "Editor & PDF",
|
||||||
"editor_disconected_click_to_reconnect": "Editor disconnected, click anywhere to reconnect.",
|
"editor_disconected_click_to_reconnect": "Editor disconnected, click anywhere to reconnect.",
|
||||||
"editor_only_hide_pdf": "Editor only <0>(hide PDF)</0>",
|
"editor_only_hide_pdf": "Editor only <0>(hide PDF)</0>",
|
||||||
"editor_resources": "Editor Resources",
|
"editor_resources": "Editor Resources",
|
||||||
|
|
|
@ -31,30 +31,6 @@ describe('i18n', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Trans', function () {
|
describe('Trans', function () {
|
||||||
it('translates a plain string', function () {
|
|
||||||
const Test = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Trans i18nKey="accept" />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
cy.mount(<Test />)
|
|
||||||
cy.findByText('Accept')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('uses defaultValues', function () {
|
|
||||||
const Test = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Trans i18nKey="welcome_to_sl" />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
cy.mount(<Test />)
|
|
||||||
cy.findByText('Welcome to Overleaf!')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('uses values', function () {
|
it('uses values', function () {
|
||||||
const Test = () => {
|
const Test = () => {
|
||||||
return (
|
return (
|
||||||
|
|
Loading…
Reference in a new issue