diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json
index 85a4846a38..dd38d566b7 100644
--- a/services/web/frontend/extracted-translations.json
+++ b/services/web/frontend/extracted-translations.json
@@ -1,6 +1,8 @@
{
"access_your_projects_with_git": "",
"account_settings": "",
+ "add_files": "",
+ "also": "",
"anyone_with_link_can_edit": "",
"anyone_with_link_can_view": "",
"ask_proj_owner_to_upgrade_for_git_bridge": "",
@@ -69,6 +71,7 @@
"fast": "",
"file_already_exists": "",
"file_already_exists_in_this_location": "",
+ "file_name": "",
"file_name_in_this_project": "",
"file_outline": "",
"files_cannot_include_invalid_characters": "",
@@ -76,6 +79,8 @@
"first_error_popup_label": "",
"following_paths_conflict": "",
"free_accounts_have_timeout_upgrade_to_increase": "",
+ "from_another_project": "",
+ "from_external_url": "",
"full_doc_history": "",
"full_screen": "",
"generic_something_went_wrong": "",
@@ -102,6 +107,28 @@
"headers": "",
"hide_outline": "",
"history": "",
+ "hotkey_add_a_comment": "",
+ "hotkey_autocomplete_menu": "",
+ "hotkey_beginning_of_document": "",
+ "hotkey_bold_text": "",
+ "hotkey_compile": "",
+ "hotkey_delete_current_line": "",
+ "hotkey_end_of_document": "",
+ "hotkey_find_and_replace": "",
+ "hotkey_go_to_line": "",
+ "hotkey_indent_selection": "",
+ "hotkey_insert_candidate": "",
+ "hotkey_italic_text": "",
+ "hotkey_redo": "",
+ "hotkey_search_references": "",
+ "hotkey_select_all": "",
+ "hotkey_select_candidate": "",
+ "hotkey_to_lowercase": "",
+ "hotkey_to_uppercase": "",
+ "hotkey_toggle_comment": "",
+ "hotkey_toggle_review_panel": "",
+ "hotkey_toggle_track_changes": "",
+ "hotkey_undo": "",
"hotkeys": "",
"if_error_persists_try_relinking_provider": "",
"ignore_validation_errors": "",
@@ -113,6 +140,7 @@
"importing_and_merging_changes_in_github": "",
"invalid_email": "",
"invalid_file_name": "",
+ "invalid_request": "",
"invite_not_accepted": "",
"learn_how_to_make_documents_compile_quickly": "",
"learn_more_about_link_sharing": "",
@@ -154,6 +182,7 @@
"new_name": "",
"no_messages": "",
"no_new_commits_in_github": "",
+ "no_other_projects_found": "",
"no_preview_available": "",
"normal": "",
"off": "",
@@ -170,6 +199,9 @@
"pdf_rendering_error": "",
"please_compile_pdf_before_download": "",
"please_refresh": "",
+ "please_select_a_file": "",
+ "please_select_a_project": "",
+ "please_select_an_output_file": "",
"please_set_main_file": "",
"plus_upgraded_accounts_receive": "",
"private": "",
@@ -198,6 +230,7 @@
"refresh_page_after_starting_free_trial": "",
"refreshing": "",
"remote_service_error": "",
+ "remove": "",
"remove_collaborator": "",
"rename": "",
"repository_name": "",
@@ -205,22 +238,28 @@
"review": "",
"revoke_invite": "",
"run_syntax_check_now": "",
+ "select_a_file": "",
+ "select_a_project": "",
+ "select_an_output_file": "",
+ "select_from_output_files": "",
+ "select_from_source_files": "",
"select_from_your_computer": "",
"send_first_message": "",
"server_error": "",
+ "session_error": "",
"session_expired_redirecting_to_login": "",
"share": "",
"share_project": "",
"share_with_your_collabs": "",
"show_outline": "",
"something_went_wrong_rendering_pdf": "",
+ "something_went_wrong_server": "",
"somthing_went_wrong_compiling": "",
"split_screen": "",
"start_free_trial": "",
"stop_compile": "",
"stop_on_validation_error": "",
"store_your_work": "",
- "submit": "",
"submit_title": "",
"sure_you_want_to_delete": "",
"sync_project_to_github_explanation": "",
@@ -234,6 +273,7 @@
"to_change_access_permissions": "",
"toggle_compile_options_menu": "",
"toggle_output_files_list": "",
+ "too_many_attempts": "",
"too_many_files_uploaded_throttled_short_period": "",
"too_many_requests": "",
"too_recently_compiled": "",
@@ -247,6 +287,7 @@
"upgrade": "",
"upgrade_for_longer_compiles": "",
"upload": "",
+ "url_to_fetch_the_file_from": "",
"use_your_own_machine": "",
"validation_issue_description": "",
"validation_issue_entry_description": "",
diff --git a/services/web/frontend/js/features/binary-file/components/binary-file-header.js b/services/web/frontend/js/features/binary-file/components/binary-file-header.js
index eb082314c3..b92bf7f1aa 100644
--- a/services/web/frontend/js/features/binary-file/components/binary-file-header.js
+++ b/services/web/frontend/js/features/binary-file/components/binary-file-header.js
@@ -129,13 +129,14 @@ export default function BinaryFileHeader({ file, storeReferencesKeys }) {
className="btn btn-info"
>
- {' ' + t('download')}
+
+ {t('download')}
{refreshError && (
- Error: {refreshError}
+ {t('error')}: {refreshError}
{tprLinkedFileRefreshError.map(
({ import: { LinkedFileRefreshError }, path }) => (
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/error-message.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/error-message.js
index 6d4971db3d..e80331a422 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-create/error-message.js
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/error-message.js
@@ -62,32 +62,17 @@ export default function ErrorMessage({ error }) {
// TODO: translations
switch (error.response?.status) {
case 400:
- return (
-
- Invalid Request. Please correct the data and try again.
-
- )
+ return {t('invalid_request')}
case 403:
- return (
-
- Session error. Please check you have cookies enabled. If the
- problem persists, try clearing your cache and cookies.
-
- )
+ return {t('session_error')}
case 429:
- return (
-
- Too many attempts. Please wait for a while and try again.
-
- )
+ return {t('too_many_attempts')}
default:
return (
-
- Something went wrong talking to the server :(. Please try again.
-
+ {t('something_went_wrong_server')}
)
}
}
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-create-name-input.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-create-name-input.js
index 0394f61f96..390568cf49 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-create-name-input.js
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-create-name-input.js
@@ -2,7 +2,7 @@ import ControlLabel from 'react-bootstrap/lib/ControlLabel'
import { Alert, FormControl } from 'react-bootstrap'
import FormGroup from 'react-bootstrap/lib/FormGroup'
import React, { useCallback } from 'react'
-import { Trans } from 'react-i18next'
+import { Trans, useTranslation } from 'react-i18next'
import { useFileTreeCreateName } from '../../contexts/file-tree-create-name'
import PropTypes from 'prop-types'
import {
@@ -16,12 +16,14 @@ import {
* plus a validation warning and/or an error message when needed
*/
export default function FileTreeCreateNameInput({
- label = 'File Name',
+ label,
focusName = false,
classes = {},
- placeholder = 'File Name',
+ placeholder,
error,
}) {
+ const { t } = useTranslation()
+
// the value is stored in a context provider, so it's available elsewhere in the form
const { name, setName, touchedName, validName } = useFileTreeCreateName()
@@ -40,11 +42,11 @@ export default function FileTreeCreateNameInput({
return (
- {label}
+ {label || t('file_name')}
setName(event.target.value)}
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-body.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-body.js
index 5c155a87e3..c1bdf89273 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-body.js
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-body.js
@@ -1,4 +1,5 @@
import React from 'react'
+import { useTranslation } from 'react-i18next'
import FileTreeCreateNewDoc from './modes/file-tree-create-new-doc'
import FileTreeImportFromUrl from './modes/file-tree-import-from-url'
import FileTreeImportFromProject from './modes/file-tree-import-from-project'
@@ -13,6 +14,8 @@ import importOverleafModules from '../../../../../macros/import-overleaf-module.
const createFileModeModules = importOverleafModules('createFileModes')
export default function FileTreeModalCreateFileBody() {
+ const { t } = useTranslation()
+
const { newFileCreateMode } = useFileTreeActionable()
const { fileCount } = useFileTreeMutable()
@@ -29,26 +32,26 @@ export default function FileTreeModalCreateFileBody() {
{window.ExposedSettings.hasLinkUrlFeature && (
)}
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.js
index c23c955a06..a5ee2da3d8 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.js
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.js
@@ -132,8 +132,8 @@ export default function FileTreeImportFromProject() {
>
{isOutputFilesMode
- ? 'select from source files'
- : 'select from output files'}
+ ? t('select_from_source_files')
+ : t('select_from_output_files')}
@@ -153,6 +153,8 @@ export default function FileTreeImportFromProject() {
}
function SelectProject({ projectId, selectedProject, setSelectedProject }) {
+ const { t } = useTranslation()
+
// NOTE: unhandled error
const { data, loading } = useUserProjects()
@@ -166,7 +168,7 @@ function SelectProject({ projectId, selectedProject, setSelectedProject }) {
return (
- Select a Project
+ {t('select_a_project')}
{loading && (
@@ -186,7 +188,7 @@ function SelectProject({ projectId, selectedProject, setSelectedProject }) {
}}
>
{filteredData &&
@@ -198,9 +200,7 @@ function SelectProject({ projectId, selectedProject, setSelectedProject }) {
{filteredData && !filteredData.length && (
-
- No other projects found, please create another project first
-
+ {t('no_other_projects_found')}
)}
)
@@ -216,6 +216,8 @@ function SelectProjectOutputFile({
selectedProjectOutputFile,
setSelectedProjectOutputFile,
}) {
+ const { t } = useTranslation()
+
// NOTE: unhandled error
const { data, loading } = useProjectOutputFiles(selectedProjectId)
@@ -224,7 +226,7 @@ function SelectProjectOutputFile({
className="form-controls row-spaced-small"
controlId="project-output-file-select"
>
-
Select an Output File
+
{t('select_an_output_file')}
{loading && (
@@ -244,7 +246,7 @@ function SelectProjectOutputFile({
}}
>
{data &&
@@ -268,6 +270,8 @@ function SelectProjectEntity({
selectedProjectEntity,
setSelectedProjectEntity,
}) {
+ const { t } = useTranslation()
+
// NOTE: unhandled error
const { data, loading } = useProjectEntities(selectedProjectId)
@@ -276,7 +280,7 @@ function SelectProjectEntity({
className="form-controls row-spaced-small"
controlId="project-entity-select"
>
- Select a File
+ {t('select_a_file')}
{loading && (
@@ -296,7 +300,7 @@ function SelectProjectEntity({
}}
>
{data &&
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.js b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.js
index 2ef4f35cf6..13efa54a0e 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.js
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.js
@@ -51,7 +51,7 @@ export default function FileTreeImportFromUrl() {
onSubmit={handleSubmit}
>
- URL to fetch the file from
+ {t('url_to_fetch_the_file_from')}
- Add Files
+ {t('add_files')}
diff --git a/services/web/frontend/js/features/hotkeys-modal/components/hotkeys-modal.js b/services/web/frontend/js/features/hotkeys-modal/components/hotkeys-modal.js
index e0c02ace12..656a043dfc 100644
--- a/services/web/frontend/js/features/hotkeys-modal/components/hotkeys-modal.js
+++ b/services/web/frontend/js/features/hotkeys-modal/components/hotkeys-modal.js
@@ -33,15 +33,24 @@ export default function HotkeysModal({
+
-
-
+
-
+
@@ -51,17 +60,20 @@ export default function HotkeysModal({
-
+
@@ -69,26 +81,44 @@ export default function HotkeysModal({
-
+
+
-
-
+
+
-
-
-
+
+
@@ -98,17 +128,20 @@ export default function HotkeysModal({
-
+
@@ -123,7 +156,7 @@ export default function HotkeysModal({
@@ -136,19 +169,19 @@ export default function HotkeysModal({
diff --git a/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade.js b/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade.js
index cf178c2e13..fcd670a35e 100644
--- a/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade.js
+++ b/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade.js
@@ -1,17 +1,19 @@
import React, { useState } from 'react'
-import { Trans } from 'react-i18next'
+import { Trans, useTranslation } from 'react-i18next'
import { Button } from 'react-bootstrap'
import Icon from '../../../shared/components/icon'
import { upgradePlan } from '../../../main/account-upgrade'
import StartFreeTrialButton from '../../../shared/components/start-free-trial-button'
export default function AddCollaboratorsUpgrade() {
+ const { t } = useTranslation()
+
const [startedFreeTrial, setStartedFreeTrial] = useState(false)
return (
- . Also:
+ . {t('also')}:
diff --git a/services/web/frontend/js/features/share-project-modal/components/select-collaborators.js b/services/web/frontend/js/features/share-project-modal/components/select-collaborators.js
index 57d55ba1b5..9a8429ba13 100644
--- a/services/web/frontend/js/features/share-project-modal/components/select-collaborators.js
+++ b/services/web/frontend/js/features/share-project-modal/components/select-collaborators.js
@@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useState, useRef, useCallback } from 'react'
import PropTypes from 'prop-types'
-import { Trans } from 'react-i18next'
+import { Trans, useTranslation } from 'react-i18next'
import { matchSorter } from 'match-sorter'
import { useCombobox } from 'downshift'
import classnames from 'classnames'
@@ -286,6 +286,8 @@ function SelectedItem({
getSelectedItemProps,
index,
}) {
+ const { t } = useTranslation()
+
const handleClick = useCallback(
event => {
event.preventDefault()
@@ -306,7 +308,7 @@ function SelectedItem({