From c754eaf5c5503b3bddc60cc7351e7c9e388dc90b Mon Sep 17 00:00:00 2001 From: Mathias Jakobsen Date: Wed, 17 May 2023 08:13:27 +0100 Subject: [PATCH] Merge pull request #13108 from overleaf/mj-figure-modal-translations [web] Translate figure modal GitOrigin-RevId: b9f2c2e9ba3141dfee15c0af572a022a2b21fd47 --- .../web/frontend/extracted-translations.json | 50 ++++++++++++ .../figure-modal/figure-modal-footer.tsx | 16 ++-- .../figure-modal/figure-modal-help.tsx | 81 ++++++++++--------- .../figure-modal/figure-modal-options.tsx | 24 +++--- .../figure-modal-source-picker.tsx | 10 ++- .../components/figure-modal/figure-modal.tsx | 44 +++++----- .../figure-modal/file-name-input.tsx | 4 +- .../figure-modal/file-relocator.tsx | 12 +-- .../figure-modal-edit-figure-source.tsx | 4 +- .../figure-modal-other-project-source.tsx | 24 +++--- .../figure-modal-project-source.tsx | 6 +- .../figure-modal-upload-source.tsx | 8 +- .../file-sources/figure-modal-url-source.tsx | 6 +- .../frontend/js/shared/components/select.tsx | 4 +- services/web/locales/en.json | 51 ++++++++++++ 15 files changed, 245 insertions(+), 99 deletions(-) diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index ecc519ad6f..d939053283 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -1,4 +1,9 @@ { + "1_2_width": "", + "1_4_width": "", + "3_4_width": "", + "a_custom_size_has_been_used_in_the_latex_code": "", + "a_file_with_that_name_already_exists_and_will_be_overriden": "", "a_more_comprehensive_list_of_keyboard_shortcuts": "", "about_to_archive_projects": "", "about_to_delete_projects": "", @@ -48,6 +53,7 @@ "archived_projects": "", "archiving_projects_wont_affect_collaborators": "", "are_you_affiliated_with_an_institution": "", + "are_you_getting_an_undefined_control_sequence_error": "", "are_you_still_at": "", "ascending": "", "ask_proj_owner_to_upgrade_for_full_history": "", @@ -61,6 +67,7 @@ "autocompile_disabled_reason": "", "autocomplete": "", "autocomplete_references": "", + "back": "", "back_to_subscription": "", "back_to_your_projects": "", "beta_program_already_participating": "", @@ -104,6 +111,7 @@ "change_project_owner": "", "change_to_group_plan": "", "change_to_this_plan": "", + "changing_the_position_of_your_figure": "", "chat": "", "chat_error": "", "checking_dropbox_status": "", @@ -166,7 +174,9 @@ "currently_seeing_only_24_hrs_history": "", "currently_subscribed_to_plan": "", "customize_your_group_subscription": "", + "customizing_figures": "", "date_and_owner": "", + "dealing_with_errors": "", "delete": "", "delete_account": "", "delete_account_confirmation_label": "", @@ -174,6 +184,7 @@ "delete_acct_no_existing_pw": "", "delete_and_leave": "", "delete_and_leave_projects": "", + "delete_figure": "", "delete_projects": "", "delete_tag": "", "delete_your_account": "", @@ -201,6 +212,7 @@ "download": "", "download_pdf": "", "drag_here": "", + "drag_here_paste_an_image_or": "", "dropbox_checking_sync_status": "", "dropbox_duplicate_project_names": "", "dropbox_duplicate_project_names_suggestion": "", @@ -225,10 +237,12 @@ "edit_dictionary": "", "edit_dictionary_empty": "", "edit_dictionary_remove": "", + "edit_figure": "", "edit_in_source_to_see_your_entire_latex_code": "", "edit_in_the_left_pane_click_recompile": "", "edit_tag": "", "editing": "", + "editing_captions": "", "editor_and_pdf": "&", "editor_only_hide_pdf": "", "editor_theme": "", @@ -239,6 +253,7 @@ "emails_and_affiliations_explanation": "", "emails_and_affiliations_title": "", "end_of_document": "", + "enter_image_url": "", "error": "", "error_performing_request": "", "example_project": "", @@ -260,6 +275,7 @@ "file_already_exists_in_this_location": "", "file_name": "", "file_name_in_this_project": "", + "file_name_in_this_project_figure_modal": "", "file_outline": "", "files_cannot_include_invalid_characters": "", "find_out_more": "", @@ -270,6 +286,7 @@ "first_name": "", "first_x_days_free_after_that_y_per_month": "", "fold_line": "", + "folder_location": "", "following_paths_conflict": "", "font_family": "", "font_size": "", @@ -280,6 +297,7 @@ "from_external_url": "", "from_provider": "", "full_doc_history": "", + "full_width": "", "galileo_feedback_button": "", "galileo_feedback_detail": "", "galileo_feedback_intro": "", @@ -403,6 +421,9 @@ "if_error_persists_try_relinking_provider": "", "ignore_validation_errors": "", "ill_take_it": "", + "image_file": "", + "image_url": "", + "image_width": "", "import_from_github": "", "import_to_sharelatex": "", "imported_from_another_project_at_date": "", @@ -414,8 +435,15 @@ "importing_and_merging_changes_in_github": "", "in_order_to_match_institutional_metadata_2": "", "in_order_to_match_institutional_metadata_associated": "", + "include_caption": "", + "include_label": "", "increased_compile_timeout": "", "inr_discount_offer": "", + "insert_figure": "", + "insert_from_another_project": "", + "insert_from_project_files": "", + "insert_from_url": "", + "insert_image": "", "institution": "", "institution_account": "", "institution_acct_successfully_linked_2": "", @@ -437,6 +465,7 @@ "joining": "", "keep_current_plan": "", "keybindings": "", + "labels_help_you_to_easily_reference_your_figures": "", "labs_program_already_participating": "", "labs_program_benefits": "<0>", "labs_program_not_participating": "", @@ -447,6 +476,7 @@ "last_resort_trouble_shooting_guide": "", "last_updated_date_by_x": "", "latex_help_guide": "", + "latex_places_figures_according_to_a_special_algorithm": "", "layout": "", "layout_processing": "", "learn_more": "", @@ -553,6 +583,8 @@ "next": "", "next_payment_of_x_collectected_on_y": "", "no_existing_password": "", + "no_folder": "", + "no_image_files_found": "", "no_members": "", "no_messages": "", "no_new_commits_in_github": "", @@ -586,6 +618,7 @@ "organize_projects": "", "other_logs_and_files": "", "other_output_files": "", + "output_file": "", "overall_theme": "", "overleaf": "", "overleaf_history_system": "", @@ -650,6 +683,7 @@ "professional": "", "project": "", "project_approaching_file_limit": "", + "project_figure_modal": "", "project_flagged_too_many_compiles": "", "project_has_too_many_files": "", "project_last_published_at": "", @@ -715,6 +749,11 @@ "removing": "", "rename": "", "rename_project": "", + "replace_figure": "", + "replace_from_another_project": "", + "replace_from_computer": "", + "replace_from_project_files": "", + "replace_from_url": "", "repository_name": "", "republish": "", "resend": "", @@ -765,10 +804,13 @@ "select_all": "", "select_all_projects": "", "select_an_output_file": "", + "select_folder_from_project": "", "select_from_output_files": "", + "select_from_project_files": "", "select_from_source_files": "", "select_from_your_computer": "", "select_github_repository": "", + "select_image_from_project_files": "", "select_project": "", "select_projects": "", "select_tag": "", @@ -865,8 +907,10 @@ "thanks_for_subscribing_you_help_sl": "", "thanks_settings_updated": "", "the_following_files_already_exist_in_this_project": "", + "the_width_you_choose_here_is_based_on_the_width_of_the_text_in_your_document": "", "then_x_price_per_month": "", "then_x_price_per_year": "", + "there_are_lots_of_options_to_edit_and_customize_your_figures": "", "this_action_cannot_be_undone": "", "this_address_will_be_shown_on_the_invoice": "", "this_field_is_required": "", @@ -874,6 +918,7 @@ "this_project_is_public": "", "this_project_is_public_read_only": "", "this_project_will_appear_in_your_dropbox_folder_at": "", + "this_tool_helps_you_insert_figures": "", "timedout": "", "tip": "", "title": "", @@ -933,8 +978,10 @@ "unconfirmed": "", "undelete": "", "undeleting": "", + "understanding_labels": "", "unfold_line": "", "university": "", + "unknown": "", "unlimited_collabs": "", "unlimited_projects": "", "unlink": "", @@ -962,11 +1009,13 @@ "upgrade_now": "", "upgrade_to_get_feature": "", "upload": "", + "upload_from_computer": "", "upload_project": "", "upload_zipped_project": "", "url_to_fetch_the_file_from": "", "use_a_different_password": "", "use_your_own_machine": "", + "used_when_referring_to_the_figure_elsewhere_in_the_document": "", "user_deletion_error": "", "user_deletion_password_reset_tip": "", "user_sessions": "", @@ -987,6 +1036,7 @@ "wed_love_you_to_stay": "", "welcome_to_sl": "", "welcome_to_your_first_project": "", + "when_you_tick_the_include_caption_box": "", "wide": "", "with_premium_subscription_you_also_get": "", "word_count": "", diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-footer.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-footer.tsx index c5ffd92ae2..c6691b9c3f 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-footer.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-footer.tsx @@ -5,12 +5,14 @@ import { } from './figure-modal-context' import Icon from '../../../../shared/components/icon' import { FC } from 'react' +import { useTranslation } from 'react-i18next' export const FigureModalFooter: FC<{ onInsert: () => void onCancel: () => void onDelete: () => void }> = ({ onInsert, onCancel, onDelete }) => { + const { t } = useTranslation() return (
@@ -23,7 +25,7 @@ export const FigureModalFooter: FC<{ type="button" onClick={onCancel} > - Cancel + {t('cancel')}
@@ -32,6 +34,7 @@ export const FigureModalFooter: FC<{ } const HelpToggle = () => { + const { t } = useTranslation() const { helpShown, dispatch } = useFigureModalContext() if (helpShown) { return ( @@ -41,7 +44,7 @@ const HelpToggle = () => { onClick={() => dispatch({ helpShown: false })} > -  Back +  {t('back')} ) } @@ -52,7 +55,7 @@ const HelpToggle = () => { onClick={() => dispatch({ helpShown: true })} > -  Help +  {t('help')} ) } @@ -61,6 +64,7 @@ const FigureModalAction: FC<{ onInsert: () => void onDelete: () => void }> = ({ onInsert, onDelete }) => { + const { t } = useTranslation() const { helpShown, getPath, source, sourcePickerShown } = useFigureModalContext() @@ -76,7 +80,7 @@ const FigureModalAction: FC<{ type="button" onClick={onDelete} > - Delete figure + {t('delete_figure')} ) } @@ -89,7 +93,7 @@ const FigureModalAction: FC<{ type="button" onClick={onInsert} > - Done + {t('done')} ) } @@ -102,7 +106,7 @@ const FigureModalAction: FC<{ disabled={getPath === undefined} onClick={onInsert} > - Insert figure + {t('insert_figure')} ) } diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-help.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-help.tsx index b1c9157b35..f434ddf1f5 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-help.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-help.tsx @@ -1,63 +1,68 @@ import { FC } from 'react' +import { Trans, useTranslation } from 'react-i18next' const LearnWikiLink: FC<{ article: string }> = ({ article, children }) => { return {children} } export const FigureModalHelp = () => { + const { t } = useTranslation() return ( <>

- This tool helps you insert figures into your project without needing to - write the LaTeX code. The following information explains more about the - options in the tool and how to further customize your figures. + +

+ {t('editing_captions')} +

+

- Editing captions + {t('understanding_labels')}

- When you tick the box “Include caption” the image will be inserted into - your document with a placeholder caption. To edit it, you simply select - the placeholder text and type to replace it with your own.{' '} + , + // eslint-disable-next-line react/jsx-key + , + ]} + />

- Understanding labels + {t('customizing_figures')}

- Labels help you to easily reference your figures throughout your - document. To reference a figure within the text, reference the label - using the \ref{...} command. This makes it easy - to reference figures without needing to manually remember the figure - numbering.{' '} - - Learn more - + , + ]} + />

- Customizing figures + {t('changing_the_position_of_your_figure')}

- There are lots of options to edit and customize your figures, such as - wrapping text around the figure, rotating the image, or including - multiple images in a single figure. You’ll need to edit the LaTeX code - to do this.{' '} - Find out how + , + ]} + />

- Changing the position of your figure + {t('dealing_with_errors')}

- LaTeX places figures according to a special algorithm. You can use - something called ‘placement parameters’ to influence the positioning of - the figure.{' '} - - Find out how - -

- - Dealing with errors -

- Are you getting an Undefined Control Sequence error? If you are, make - sure you’ve loaded the graphicx package— - \usepackage{graphicx}—in the preamble - (first section of code) in your document.{' '} - Learn more + , + // eslint-disable-next-line react/jsx-key + , + ]} + />

) diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-options.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-options.tsx index d2662f65bd..f51f49848b 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-options.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-options.tsx @@ -6,8 +6,10 @@ import { useFigureModalExistingFigureContext, } from './figure-modal-context' import { Switcher, SwitcherItem } from '../../../../shared/components/switcher' +import { useTranslation } from 'react-i18next' export const FigureModalFigureOptions: FC = () => { + const { t } = useTranslation() const { includeCaption, includeLabel, dispatch, width } = useFigureModalContext() @@ -22,7 +24,7 @@ export const FigureModalFigureOptions: FC = () => { onChange={event => dispatch({ includeCaption: event.target.checked })} />
@@ -33,20 +35,20 @@ export const FigureModalFigureOptions: FC = () => { onChange={event => dispatch({ includeLabel: event.target.checked })} />
- Image width{' '} + {t('image_width')}{' '} {hasComplexGraphicsArgument ? ( @@ -54,7 +56,9 @@ export const FigureModalFigureOptions: FC = () => { ) : ( @@ -68,10 +72,10 @@ export const FigureModalFigureOptions: FC = () => { defaultValue={width === 1 ? '1.0' : width.toString()} disabled={hasComplexGraphicsArgument} > - - - - + + + +
diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-source-picker.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-source-picker.tsx index cc4d11e1f9..cb0433d7e2 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-source-picker.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal-source-picker.tsx @@ -5,31 +5,33 @@ import { } from './figure-modal-context' import Icon from '../../../../shared/components/icon' import { Button } from 'react-bootstrap' +import { useTranslation } from 'react-i18next' export const FigureModalSourcePicker: FC = () => { + const { t } = useTranslation() return (
diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx index 69e4d1fa78..d9f9dd5071 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx @@ -18,23 +18,7 @@ import { editFigureDataEffect, } from '../../extensions/figure-modal' import { ensureEmptyLine } from '../../extensions/toolbar/commands' - -const getTitle = (state: FigureModalSource) => { - switch (state) { - case FigureModalSource.FILE_UPLOAD: - return 'Upload from computer' - case FigureModalSource.FILE_TREE: - return 'Insert from project files' - case FigureModalSource.FROM_URL: - return 'Insert from URL' - case FigureModalSource.OTHER_PROJECT: - return 'Insert from another project' - case FigureModalSource.EDIT_FIGURE: - return 'Edit figure' - default: - return 'Insert image' - } -} +import { useTranslation } from 'react-i18next' export const FigureModal = memo(function FigureModal() { return ( @@ -45,6 +29,28 @@ export const FigureModal = memo(function FigureModal() { }) const FigureModalContent = () => { + const { t } = useTranslation() + + const getTitle = useCallback( + (state: FigureModalSource) => { + switch (state) { + case FigureModalSource.FILE_UPLOAD: + return t('upload_from_computer') + case FigureModalSource.FILE_TREE: + return t('insert_from_project_files') + case FigureModalSource.FROM_URL: + return t('insert_from_url') + case FigureModalSource.OTHER_PROJECT: + return t('insert_from_another_project') + case FigureModalSource.EDIT_FIGURE: + return t('edit_figure') + default: + return t('insert_image') + } + }, + [t] + ) + const { source, dispatch, @@ -232,9 +238,9 @@ const FigureModalContent = () => { {helpShown - ? 'Help' + ? t('help') : sourcePickerShown - ? 'Replace figure' + ? t('replace_figure') : getTitle(source)}{' '} , HTMLInputElement>, @@ -54,6 +55,7 @@ export const FileNameInput = ({ targetFolder, ...props }: FileNameInputProps) => { + const { t } = useTranslation() const [overlap, setOverlap] = useState(false) const [rootFolder] = useScopeValue('rootFolder') const { value } = props @@ -83,7 +85,7 @@ export const FileNameInput = ({ {overlap && ( - A file with that name already exists. That file will be overwritten. + {t('a_file_with_that_name_already_exists_and_will_be_overriden')} )} diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/file-relocator.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/file-relocator.tsx index 89185caf74..762ea5e4a3 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/file-relocator.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/file-relocator.tsx @@ -3,6 +3,7 @@ import { FileNameInput } from './file-name-input' import { File } from '../../utils/file' import { Select } from '../../../../shared/components/select' import { useCurrentProjectFolders } from '../../hooks/useCurrentProjectFolders' +import { useTranslation } from 'react-i18next' export const FileRelocator = ({ name, @@ -23,6 +24,7 @@ export const FileRelocator = ({ setFolder: (folder: File) => void setNameDirty: (nameDirty: boolean) => void }) => { + const { t } = useTranslation() const [folders, rootFile] = useCurrentProjectFolders() const nameChanged = useCallback( @@ -48,7 +50,7 @@ export const FileRelocator = ({ return ( <> { if (item?.path === '' && item?.name === 'rootFolder') { - return 'No folder' + return t('no_folder') } if (item) { return `${item.path}${item.name}` } - return 'No folder' + return t('no_folder') }} itemToSubtitle={item => item?.path ?? ''} itemToKey={item => item.id} - defaultText="Select folder from project" - label="Folder location" + defaultText={t('select_folder_from_project')} + label={t('folder_location')} optionalLabel onSelectedItemChanged={selectedFolderChanged} /> diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-edit-figure-source.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-edit-figure-source.tsx index 9cce0220b2..0acf03a518 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-edit-figure-source.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-edit-figure-source.tsx @@ -4,8 +4,10 @@ import { useFigureModalContext, useFigureModalExistingFigureContext, } from '../figure-modal-context' +import { useTranslation } from 'react-i18next' export const FigureModalEditFigureSource: FC = () => { + const { t } = useTranslation() const { dispatch } = useFigureModalContext() const { name } = useFigureModalExistingFigureContext() @@ -19,7 +21,7 @@ export const FigureModalEditFigureSource: FC = () => { return ( { dispatch({ sourcePickerShown: true }) diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-other-project-source.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-other-project-source.tsx index 85d25f37ca..ecf196af4f 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-other-project-source.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-other-project-source.tsx @@ -19,6 +19,7 @@ import { File, isImageEntity } from '../../../utils/file' import { postJSON } from '../../../../../infrastructure/fetch-json' import { useProjectContext } from '../../../../../shared/context/project-context' import { FileRelocator } from '../file-relocator' +import { useTranslation } from 'react-i18next' function suggestName(path: string) { const parts = path.split('/') @@ -26,6 +27,7 @@ function suggestName(path: string) { } export const FigureModalOtherProjectSource: FC = () => { + const { t } = useTranslation() const { dispatch } = useFigureModalContext() const { _id: projectId } = useProjectContext() const { loading: projectsLoading, data: projects, error } = useUserProjects() @@ -124,8 +126,8 @@ export const FigureModalOtherProjectSource: FC = () => { items={projects ?? []} itemToString={project => (project ? project.name : '')} itemToKey={item => item._id} - defaultText="Select a project" - label="Project" + defaultText={t('select_a_project')} + label={t('project_figure_modal')} disabled={projectsLoading} onSelectedItemChanged={item => { const suggestion = nameDirty ? name : '' @@ -161,8 +163,8 @@ export const FigureModalOtherProjectSource: FC = () => { > {usingOutputFiles - ? 'select from project files' - : 'select from output files'} + ? t('select_from_project_files') + : t('select_from_output_files')}
@@ -187,8 +189,8 @@ const SelectFile = ({ disabled, files, onSelectedItemChange, - defaultText = 'Select a file', - label = 'Image file', + defaultText, + label, loading = false, }: { disabled: boolean @@ -198,6 +200,9 @@ const SelectFile = ({ loading?: boolean onSelectedItemChange?: (item: T | null | undefined) => any }) => { + const { t } = useTranslation() + defaultText = defaultText ?? t('select_a_file') + label = label ?? t('image_file') const imageFiles = useMemo(() => files?.filter(isImageEntity), [files]) const empty = loading || !imageFiles || imageFiles.length === 0 return ( @@ -207,7 +212,7 @@ const SelectFile = ({ itemToString={file => (file ? file.path.replace(/^\//, '') : '')} itemToKey={file => file.path} defaultText={ - imageFiles?.length === 0 ? 'No image files found' : defaultText + imageFiles?.length === 0 ? t('no_image_files_found') : defaultText } label={label} disabled={disabled || empty} @@ -241,6 +246,7 @@ const SelectFromProjectOutputFiles: FC<{ projectId?: string onSelectedItemChange?: (item: OutputEntity | null | undefined) => any }> = ({ projectId, onSelectedItemChange }) => { + const { t } = useTranslation() const { loading, data: entities, error } = useProjectOutputFiles(projectId) const { dispatch } = useFigureModalContext() useEffect(() => { @@ -250,8 +256,8 @@ const SelectFromProjectOutputFiles: FC<{ }, [error, dispatch]) return ( { + const { t } = useTranslation() const [rootFolder] = useScopeValue('rootFolder') const files = useMemo( () => filterFiles(rootFolder)?.filter(isImageFile), @@ -19,7 +21,9 @@ export const FigureModalCurrentProjectSource: FC = () => { itemToSubtitle={item => item?.path ?? ''} itemToKey={item => item.id} defaultText={ - noFiles ? 'No image files found' : 'Select image from project files' + noFiles + ? t('no_image_files_found') + : t('select_image_from_project_files') } label="Image file" onSelectedItemChanged={item => { diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-upload-source.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-upload-source.tsx index a7f42f9505..ab4c709e69 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-upload-source.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-upload-source.tsx @@ -13,6 +13,7 @@ import Icon from '../../../../../shared/components/icon' import classNames from 'classnames' import { Button } from 'react-bootstrap' import { FileRelocator } from '../file-relocator' +import { useTranslation } from 'react-i18next' const maxFileSize = window.ExposedSettings.maxUploadSize @@ -26,6 +27,7 @@ export enum FileUploadStatus { /* eslint-enable no-unused-vars */ export const FigureModalUploadFileSource: FC = () => { + const { t } = useTranslation() const { dispatch } = useFigureModalContext() const { _id: projectId } = useProjectContext() const [, rootFolder] = useCurrentProjectFolders() @@ -217,9 +219,11 @@ export const FigureModalUploadFileSource: FC = () => { strings: { // Text to show on the droppable area. // `%{browseFiles}` is replaced with a link that opens the system file selection dialog. - dropPasteFiles: `Drag here, paste an image, or %{browseFiles}`, + dropPasteFiles: `${t( + 'drag_here_paste_an_image_or' + )} %{browseFiles}`, // Used as the label for the link that opens the system file selection dialog. - browseFiles: 'select from your computer', + browseFiles: t('select_from_your_computer'), }, }} /> diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-url-source.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-url-source.tsx index e7fea93d5b..d722ce9f89 100644 --- a/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-url-source.tsx +++ b/services/web/frontend/js/features/source-editor/components/figure-modal/file-sources/figure-modal-url-source.tsx @@ -5,6 +5,7 @@ import { useProjectContext } from '../../../../../shared/context/project-context import { File } from '../../../utils/file' import { useCurrentProjectFolders } from '../../../hooks/useCurrentProjectFolders' import { FileRelocator } from '../file-relocator' +import { useTranslation } from 'react-i18next' function generateLinkedFileFetcher( projectId: string, @@ -30,6 +31,7 @@ function generateLinkedFileFetcher( } export const FigureModalUrlSource: FC = () => { + const { t } = useTranslation() const [url, setUrl] = useState('') const [nameDirty, setNameDirty] = useState(false) const [name, setName] = useState('') @@ -61,12 +63,12 @@ export const FigureModalUrlSource: FC = () => { return ( <> - + { setUrl(e.target.value) diff --git a/services/web/frontend/js/shared/components/select.tsx b/services/web/frontend/js/shared/components/select.tsx index a70448cffd..e5af26d054 100644 --- a/services/web/frontend/js/shared/components/select.tsx +++ b/services/web/frontend/js/shared/components/select.tsx @@ -3,6 +3,7 @@ import classNames from 'classnames' import { useSelect } from 'downshift' import Icon from './icon' +import { useTranslation } from 'react-i18next' type SelectProps = { items: T[] @@ -29,6 +30,7 @@ export const Select = ({ optionalLabel = false, loading = false, }: SelectProps) => { + const { t } = useTranslation() const { isOpen, selectedItem, @@ -54,7 +56,7 @@ export const Select = ({ {label}{' '} {optionalLabel && ( - (Optional) + ({t('optional')}) )}{' '} {loading && } diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 670b6ff03f..6311eac9c0 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -1,4 +1,7 @@ { + "1_2_width": "½ width", + "1_4_width": "¼ width", + "3_4_width": "¾ width", "About": "About", "Account": "Account", "Account Settings": "Account Settings", @@ -8,6 +11,8 @@ "Subscription": "Subscription", "Terms": "Terms", "Universities": "Universities", + "a_custom_size_has_been_used_in_the_latex_code": "A custom size has been used in the LaTeX code.", + "a_file_with_that_name_already_exists_and_will_be_overriden": "A file with that name already exists. That file will be overwritten.", "a_more_comprehensive_list_of_keyboard_shortcuts": "A more comprehensive list of keyboard shortcuts can be found in <0>this __appName__ project template", "about": "About", "about_to_archive_projects": "You are about to archive the following projects:", @@ -99,6 +104,7 @@ "archived_projects": "Archived Projects", "archiving_projects_wont_affect_collaborators": "Archiving projects won’t affect your collaborators.", "are_you_affiliated_with_an_institution": "Are you affiliated with an institution?", + "are_you_getting_an_undefined_control_sequence_error": "Are you getting an Undefined Control Sequence error? If you are, make sure you’ve loaded the graphicx package—<0>\\usepackage{graphicx}—in the preamble (first section of code) in your document. <1>Learn more", "are_you_still_at": "Are you still at <0>__institutionName__?", "are_you_sure": "Are you sure?", "as_a_member_of_sso_required": "As a member of __institutionName__, you must log in to __appName__ through your institution.", @@ -116,6 +122,7 @@ "autocompile_disabled_reason": "Due to high server load, background recompilation has been temporarily disabled. Please recompile by clicking the button above.", "autocomplete": "Autocomplete", "autocomplete_references": "Reference Autocomplete (inside a \\cite{} block)", + "back": "Back", "back_to_account_settings": "Back to account settings", "back_to_editor": "Back to the editor", "back_to_log_in": "Back to log in", @@ -200,6 +207,7 @@ "change_to_annual_billing_and_save": "Get <0>__percentage__ off with annual billing. If you switch now you’ll save <1>__yearlySaving__ per year.", "change_to_group_plan": "Change to a group plan", "change_to_this_plan": "Change to this plan", + "changing_the_position_of_your_figure": "Changing the position of your figure", "chat": "Chat", "chat_error": "Could not load chat messages, please try again.", "check_your_email": "Check your email", @@ -307,10 +315,12 @@ "customize": "Customize", "customize_your_group_subscription": "Customize your group subscription", "customize_your_plan": "Customize your plan", + "customizing_figures": "Customizing figures", "da": "Danish", "date": "Date", "date_and_owner": "Date and owner", "de": "German", + "dealing_with_errors": "Dealing with errors", "december": "December", "dedicated_account_manager": "Dedicated account manager", "dedicated_account_manager_info": "Our Account Management Team will be able to assist with requests, questions and to help you spread the word about Overleaf with promotional materials, training resources and webinars.", @@ -322,6 +332,7 @@ "delete_acct_no_existing_pw": "Please use the password reset form to set a password before deleting your account", "delete_and_leave": "Delete / Leave", "delete_and_leave_projects": "Delete and Leave Projects", + "delete_figure": "Delete figure", "delete_folder": "Delete Folder", "delete_projects": "Delete Projects", "delete_tag": "Delete Tag", @@ -361,6 +372,7 @@ "download_zip_file": "Download .zip File", "drag_a_zip_file": "drag a .zip file", "drag_here": "drag here", + "drag_here_paste_an_image_or": "Drag here, paste an image, or ", "drop_files_here_to_upload": "Drop files here to upload", "dropbox_already_linked_error": "Your Dropbox account cannot be linked as it is already linked with another Overleaf account.", "dropbox_already_linked_error_with_email": "Your Dropbox account cannot be linked as it is already linked with another Overleaf account using email address __otherUsersEmail__.", @@ -395,10 +407,12 @@ "edit_dictionary": "Edit Dictionary", "edit_dictionary_empty": "Your custom dictionary is empty.", "edit_dictionary_remove": "Remove from dictionary", + "edit_figure": "Edit figure", "edit_in_source_to_see_your_entire_latex_code": "Edit in <0>Source to see your entire LaTeX code, or choose <0>Rich Text for something more visual.", "edit_in_the_left_pane_click_recompile": "Edit in the left pane. Click <0>Recompile to see the PDF output on the right.", "edit_tag": "Edit Tag", "editing": "Editing", + "editing_captions": "Editing captions", "editor_and_pdf": "Editor <0> PDF", "editor_disconected_click_to_reconnect": "Editor disconnected, click anywhere to reconnect.", "editor_only_hide_pdf": "Editor only <0>(hide PDF)", @@ -424,6 +438,7 @@ "empty_zip_file": "Zip doesn’t contain any file", "en": "English", "end_of_document": "End of document", + "enter_image_url": "Enter image URL", "enter_institution_email_to_log_in": "Enter your institutional email to log in through your institution.", "enter_your_email_address": "Enter your email address", "enter_your_email_address_below_and_we_will_send_you_a_link_to_reset_your_password": "Enter your email address below, and we will send you a link to reset your password", @@ -481,6 +496,7 @@ "file_has_been_deleted": "__filename__ has been deleted", "file_name": "File Name", "file_name_in_this_project": "File Name In This Project", + "file_name_in_this_project_figure_modal": "File name in this project", "file_outline": "File outline", "file_restored": "Your file (__filename__) has been recovered.", "file_restored_back_to_editor": "You can go back to the editor and work on it again.", @@ -496,6 +512,7 @@ "first_name": "First Name", "first_x_days_free_after_that_y_per_month": "First <0>__trialLen__ days free, after that <0>__price__ per month", "fold_line": "Fold line", + "folder_location": "Folder location", "folders": "Folders", "following_paths_conflict": "The following files and folders conflict with the same path", "font_family": "Font Family", @@ -530,6 +547,7 @@ "full_doc_history_info": "Travel back in time to see any version and who made changes. No matter what happens, we’ve got your back.", "full_doc_history_info_v2": "You can see all the edits in your project and who made every change. Add labels to quickly access specific versions.", "full_document_history": "Full document <0>history", + "full_width": "Full width", "galileo_feedback_button": "Give feedback", "galileo_feedback_detail": "Tell us more", "galileo_feedback_intro": "We are working on improving Galileo, your feedback is very welcome. ", @@ -695,6 +713,9 @@ "ignore_and_continue_institution_linking": "You can also ignore this and continue to __appName__ with your __email__ account.", "ignore_validation_errors": "Don’t check syntax", "ill_take_it": "I’ll take it!", + "image_file": "Image file", + "image_url": "Image URL", + "image_width": "Image width", "import_from_github": "Import from GitHub", "import_to_sharelatex": "Import to __appName__", "imported_from_another_project_at_date": "Imported from <0>Another project/__sourceEntityPathHTML__, at __formattedDate__ __relativeDate__", @@ -708,10 +729,17 @@ "in_order_to_have_a_secure_account_make_sure_your_password": "To help keep your account secure, make sure your new password:", "in_order_to_match_institutional_metadata_2": "In order to match your institutional metadata, we’ve linked your account using <0>__email__.", "in_order_to_match_institutional_metadata_associated": "In order to match your institutional metadata, your account is associated with the email __email__.", + "include_caption": "Include caption", + "include_label": "Include label", "increased_compile_timeout": "Increased compile timeout", "indvidual_plans": "Individual Plans", "info": "Info", "inr_discount_offer": "Good news! You can now use Rupees ₹ to pay for an Overleaf subscription, giving you a <0>70% discount on our premium features.", + "insert_figure": "Insert figure", + "insert_from_another_project": "Insert from another project", + "insert_from_project_files": "Insert from project files", + "insert_from_url": "Insert from URL", + "insert_image": "Insert image", "institution": "Institution", "institution_account": "Institution Account", "institution_account_tried_to_add_affiliated_with_another_institution": "This email is already associated with your account but affiliated with another institution.", @@ -771,6 +799,7 @@ "keybindings": "Keybindings", "knowledge_base": "knowledge base", "ko": "Korean", + "labels_help_you_to_easily_reference_your_figures": "Labels help you to easily reference your figures throughout your document. To reference a figure within the text, reference the label using the <0>\\ref{...} command. This makes it easy to reference figures without needing to manually remember the figure numbering. <1>Learn more", "labs_program_already_participating": "You are enrolled in Labs", "labs_program_badge_description": "While using __appName__, you will see Labs features marked with this badge:", "labs_program_benefits": "__appName__ is always looking for new ways to help users work more quickly and effectively. By joining Overleaf Labs, you can participate in experiments that explore innovative ideas in the space of collaborative writing and publishing.", @@ -787,6 +816,7 @@ "latex_guides": "LaTeX guides", "latex_help_guide": "LaTeX help guide", "latex_in_thirty_minutes": "LaTeX in 30 minutes", + "latex_places_figures_according_to_a_special_algorithm": "LaTeX places figures according to a special algorithm. You can use something called ‘placement parameters’ to influence the positioning of the figure. <0>Find out how", "latex_templates": "LaTeX Templates", "layout": "Layout", "layout_processing": "Layout processing", @@ -964,7 +994,9 @@ "no_complicated_latex_install": "No complicated LaTeX installation", "no_existing_password": "Please use the password reset form to set your password", "no_featured_templates": "No featured templates", + "no_folder": "No folder", "no_history_available": "This project doesn’t have any history yet. Please make some changes to the project and try again.", + "no_image_files_found": "No image files found", "no_members": "No members", "no_messages": "No messages", "no_new_commits_in_github": "No new commits in GitHub since last merge.", @@ -1030,6 +1062,7 @@ "other_output_files": "Download other output files", "other_sessions": "Other Sessions", "our_values": "Our values", + "output_file": "Output file", "over": "over", "over_x_templates_easy_getting_started": "There are thousands of __templates__ in our template gallery, so it’s really easy to get started, whether you’re writing a journal article, thesis, CV or something else.", "overall_theme": "Overall theme", @@ -1136,6 +1169,7 @@ "professional": "Professional", "project": "project", "project_approaching_file_limit": "This project is approaching the file limit", + "project_figure_modal": "Project", "project_flagged_too_many_compiles": "This project has been flagged for compiling too often. The limit will be lifted shortly.", "project_has_too_many_files": "This project has reached the 2000 file limit", "project_last_published_at": "Your project was last published at", @@ -1235,6 +1269,11 @@ "rename_project": "Rename Project", "renaming": "Renaming", "reopen": "Re-open", + "replace_figure": "Replace figure", + "replace_from_another_project": "Replace from another project", + "replace_from_computer": "Replace from computer", + "replace_from_project_files": "Replace from project files", + "replace_from_url": "Replace from URL", "reply": "Reply", "repository_name": "Repository Name", "republish": "Republish", @@ -1316,9 +1355,13 @@ "select_all": "Select all", "select_all_projects": "Select all projects", "select_an_output_file": "Select an Output File", + "select_folder_from_project": "Select folder from project", "select_from_output_files": "select from output files", + "select_from_project_files": "select from project files", "select_from_source_files": "select from source files", + "select_from_your_computer": "select from your computer", "select_github_repository": "Select a GitHub repository to import into __appName__.", + "select_image_from_project_files": "Select image from project files", "select_project": "Select __project__", "select_projects": "Select Projects", "select_tag": "Select tag __tagName__", @@ -1494,9 +1537,11 @@ "the_required_parameters_were_not_supplied": "The link to open this content on Overleaf was missing some required parameters. If this keeps happening for links on a particular site, please report this to them.", "the_supplied_parameters_were_invalid": "The link to open this content on Overleaf included some invalid parameters. If this keeps happening for links on a particular site, please report this to them.", "the_supplied_uri_is_invalid": "The link to open this content on Overleaf included an invalid URI. If this keeps happening for links on a particular site, please report this to them.", + "the_width_you_choose_here_is_based_on_the_width_of_the_text_in_your_document": "The width you choose here is based on the width of the text in your document. Alternatively, you can customize the image size directly in the LaTeX code.", "theme": "Theme", "then_x_price_per_month": "Then __price__ per month", "then_x_price_per_year": "Then __price__ per year", + "there_are_lots_of_options_to_edit_and_customize_your_figures": "There are lots of options to edit and customize your figures, such as wrapping text around the figure, rotating the image, or including multiple images in a single figure. You’ll need to edit the LaTeX code to do this. <0>Find out how", "there_was_an_error_opening_your_content": "There was an error creating your project", "thesis": "Thesis", "this_action_cannot_be_undone": "This action cannot be undone.", @@ -1507,6 +1552,7 @@ "this_project_is_public": "This project is public and can be edited by anyone with the URL.", "this_project_is_public_read_only": "This project is public and can be viewed but not edited by anyone with the URL", "this_project_will_appear_in_your_dropbox_folder_at": "This project will appear in your Dropbox folder at ", + "this_tool_helps_you_insert_figures": "This tool helps you insert figures into your project without needing to write the LaTeX code. The following information explains more about the options in the tool and how to further customize your figures.", "thousands_templates": "Thousands of templates", "thousands_templates_info": "Produce beautiful documents starting from our gallery of LaTeX templates for journals, conferences, theses, reports, CVs and much more.", "three_free_collab": "Three free collaborators", @@ -1589,8 +1635,10 @@ "unconfirmed": "Unconfirmed", "undelete": "Undelete", "undeleting": "Undeleting", + "understanding_labels": "Understanding labels", "unfold_line": "Unfold line", "university": "University", + "unknown": "Unknown", "unlimited": "Unlimited", "unlimited_collaborators_in_each_project": "Unlimited collaborators in each project", "unlimited_collabs": "Unlimited collaborators", @@ -1629,6 +1677,7 @@ "upgrade_to_track_changes": "Upgrade to Track Changes", "upload": "Upload", "upload_failed": "Upload failed", + "upload_from_computer": "Upload from computer", "upload_project": "Upload Project", "upload_zipped_project": "Upload Zipped Project", "url_to_fetch_the_file_from": "URL to fetch the file from", @@ -1636,6 +1685,7 @@ "usage_metrics_info": "Metrics that show how many users are accessing the licence, how many projects are being created and worked on, and how much collaboration is happening in Overleaf.", "use_a_different_password": "Please use a different password", "use_your_own_machine": "Use your own machine, with your own setup", + "used_when_referring_to_the_figure_elsewhere_in_the_document": "Used when referring to the figure elsewhere in the document", "user_already_added": "User already added", "user_deletion_error": "Sorry, something went wrong deleting your account. Please try again in a minute.", "user_deletion_password_reset_tip": "If you cannot remember your password, or if you are using Single-Sign-On with another provider to sign in (such as Twitter or Google), please <0>reset your password and try again.", @@ -1670,6 +1720,7 @@ "wed_love_you_to_stay": "We’d love you to stay", "welcome_to_sl": "Welcome to __appName__!", "welcome_to_your_first_project": "Welcome to your first __appName__ project!", + "when_you_tick_the_include_caption_box": "When you tick the box “Include caption” the image will be inserted into your document with a placeholder caption. To edit it, you simply select the placeholder text and type to replace it with your own.", "wide": "Wide", "will_need_to_log_out_from_and_in_with": "You will need to log out from your __email1__ account and then log in with __email2__.", "with_premium_subscription_you_also_get": "With an Overleaf Premium subscription you also get",