diff --git a/editors/demo/src/locale/en.js b/editors/demo/src/locale/en.js index 6bf441a41a59ed59bef73bc7d2fbb8cccf9c29ac..daf907ed46592bb258d69d86ed17dcc99c4dfe29 100644 --- a/editors/demo/src/locale/en.js +++ b/editors/demo/src/locale/en.js @@ -58,6 +58,23 @@ const en = { 'Short Boxes': 'Short Boxes', Text: 'Text', 'Custom Block': 'Custom Block', + Expand: 'Expand', + 'Show more tools': 'Show more tools', + more: 'more', + Previous: 'Previous', + Next: 'Next', + Close: 'Close', + Reject: 'Reject', + 'remove tag': 'remove tag', + 'Full screen': 'Full screen', + 'Exit full screen': 'Exit full screen', + 'Match Case': 'Match Case', + Editing: 'Editing', + Suggesting: 'Suggesting', + Viewing: 'Viewing', + Chapters: 'Chapters', + 'Show Changes': 'Show Changes', + Accept: 'Accept', }, }, }, diff --git a/editors/demo/src/locale/es.js b/editors/demo/src/locale/es.js index 09103dc4e939dd574090f2bbbb4c3af3ef60fd2b..d7e0a735b0a4762725b740b142395ed7ebf7afe2 100644 --- a/editors/demo/src/locale/es.js +++ b/editors/demo/src/locale/es.js @@ -58,6 +58,23 @@ const es = { 'Short Boxes': 'Cajas cortas', Text: 'Texto', 'Custom Block': 'Bloque personalizado', + Expand: 'Expandir', + 'Show more tools': 'Mostrar más herramientas', + more: 'más', + Previous: 'Previo', + Next: 'Próximo', + Close: 'Cerca', + Reject: 'Rechazar', + 'remove tag': 'Remover etiqueta', + 'Full screen': 'Pantalla completa', + 'Exit full screen': 'Salir de pantalla completa', + 'Match Case': 'Caso de partido', + Editing: 'Edición', + Suggesting: 'Sugerencia', + Viewing: 'Visita', + Chapters: 'CapÃtulos', + 'Show Changes': 'Mostrar cambios', + Accept: 'Aceptar', }, }, }, diff --git a/wax-prosemirror-core/index.js b/wax-prosemirror-core/index.js index ba7f464dff6cdb110c5e96fce41cba97877b970d..f6f7a4641af02902f6e26a69aa53d73baeff8075 100644 --- a/wax-prosemirror-core/index.js +++ b/wax-prosemirror-core/index.js @@ -18,6 +18,7 @@ export { default as EditoriaSchema } from './src/utilities/schema/EditoriaSchema export { default as Middleware } from './src/utilities/lib/Middleware'; export { default as ToolGroup } from './src/utilities/lib/ToolGroup'; export { default as Tools } from './src/utilities/lib/Tools'; +export { default as Translation } from './src/helpers/Translation'; /* Base Services */ export { default as LayoutService } from './src/config/defaultServices/LayoutService/LayoutService'; diff --git a/wax-prosemirror-core/src/components/icons/icons.js b/wax-prosemirror-core/src/components/icons/icons.js index 9a8cc58049144061b930a81c45e297fdb03e7002..bcd0309390d5c1128ff1842af6062c50d28b69d4 100644 --- a/wax-prosemirror-core/src/components/icons/icons.js +++ b/wax-prosemirror-core/src/components/icons/icons.js @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ /** * SVG source for icons: https://material.io/resources/icons */ @@ -5,6 +6,8 @@ import React from 'react'; import styled from 'styled-components'; import { th } from '@pubsweet/ui-toolkit'; +import { isEmpty } from 'lodash'; +import { useTranslation } from 'react-i18next'; const Svg = styled.svg.attrs(() => ({ version: '1.1', @@ -17,6 +20,18 @@ const Svg = styled.svg.attrs(() => ({ width: 24px; `; +const Translation = ({ label }) => { + const { t, i18n } = useTranslation(); + + return ( + <> + {!isEmpty(i18n) && i18n.exists(`Wax.Various.${label}`) + ? t(`Wax.Various.${label}`) + : label} + </> + ); +}; + export default { commentBubble: ({ className }) => ( <Svg className={className} viewBox="0 0 24 24"> @@ -104,7 +119,9 @@ export default { ), more: ({ className }) => ( <Svg className={className} viewBox="0 0 24 24"> - <title> Expand </title> + <title> + <Translation label="more" /> + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" /> </Svg> @@ -247,80 +264,112 @@ export default { ), navigatePrevious: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title>Previous</title> + <title> + <Translation label="Previous" /> + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" /> </Svg> ), navigateNext: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title>Next</title> + <title> + <Translation label="Next" /> + </title> <path d="M0 0h24v24H0V0z" fill="none" /> <path d="M10.02 6L8.61 7.41 13.19 12l-4.58 4.59L10.02 18l6-6-6-6z" /> </Svg> ), close: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Close </title> + <title> + {' '} + <Translation label="Close" />{' '} + </title> <path d="M0 0h24v24H0V0z" fill="none" /> <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" /> </Svg> ), reject: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Reject </title> + <title> + <Translation label="Reject" />{' '} + </title> <path d="M0 0h24v24H0V0z" fill="none" /> <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" /> </Svg> ), removeTag: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> remove tag </title> + <title> + {' '} + <Translation label="remove tag" />{' '} + </title> <path d="M0 0h24v24H0V0z" fill="none" /> <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" /> </Svg> ), fullScreen: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Full screen </title> + <title> + {' '} + <Translation label="Full screen" />{' '} + </title> <path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" /> </Svg> ), fullScreenExit: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Exit full screen </title> + <title> + {' '} + <Translation label="Exit full screen" />{' '} + </title> <path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" /> </Svg> ), matchCase: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Match Case </title> + <title> + {' '} + <Translation label="Match Case" />{' '} + </title> <path d="M2.5,4v3h5v12h3V7h5V4H2.5z M21.5,9h-9v3h3v7h3v-7h3V9z" /> </Svg> ), editing: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Editing </title> + <title> + {' '} + <Translation label="Editing" />{' '} + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" /> </Svg> ), suggesting: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Suggesting </title> + <title> + <Translation label="Suggesting" />{' '} + </title> <path d="M22,24H2v-4h20V24z M13.06,5.19l3.75,3.75L7.75,18H4v-3.75L13.06,5.19z M17.88,7.87l-3.75-3.75 l1.83-1.83c0.39-0.39,1.02-0.39,1.41,0l2.34,2.34c0.39,0.39,0.39,1.02,0,1.41L17.88,7.87z" /> </Svg> ), viewing: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Viewing </title> + <title> + {' '} + <Translation label="Viewing" />{' '} + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" /> </Svg> ), toggleOn: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Viewing </title> + <title> + {' '} + <Translation label="Viewing" />{' '} + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M17 7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h10c2.76 0 5-2.24 5-5s-2.24-5-5-5zm0 8c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z" /> </Svg> @@ -342,42 +391,59 @@ export default { ), chapterList: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Chapters </title> + <title> + {' '} + <Translation label="Chapters" />{' '} + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z" /> </Svg> ), showTrack: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Show Changes </title> + <title> + <Translation label="Show Changes" />{' '} + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M 18 2.016 L 18 0 L 0 0 L 0 2.016 Z M 18 6.984 L 18 5.016 L 0 5.016 L 0 6.984 Z M 7.5 12 L 7.5 9.984 L 0 9.984 L 0 12 Z M 16.871 11.691 L 17.633 10.93 C 17.711 10.852 17.75 10.754 17.75 10.637 C 17.75 10.52 17.711 10.422 17.633 10.344 L 17.633 10.344 L 16.656 9.367 C 16.578 9.289 16.48 9.25 16.363 9.25 C 16.246 9.25 16.148 9.289 16.07 9.367 L 16.07 9.367 L 15.309 10.129 Z M 11.813 16.75 L 16.422 12.141 L 14.859 10.578 L 10.25 15.188 L 10.25 16.75 Z" /> </Svg> ), acceptTrack: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Accept </title> + <title> + {' '} + <Translation label="Accept" />{' '} + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M 18 2.016 L 18 0 L 0 0 L 0 2.016 Z M 18 6.984 L 18 5.016 L 0 5.016 L 0 6.984 Z M 7.5 12 L 7.5 9.984 L 0 9.984 L 0 12 Z M 12.563 17.078 L 18.188 11.406 L 16.781 10 L 12.563 14.219 L 10.406 12.109 L 9 13.516 Z" /> </Svg> ), rejectTrack: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Reject </title> + <title> + {' '} + <Translation label="Reject" />{' '} + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M 18 2.016 L 18 0 L 0 0 L 0 2.016 Z M 18 6.984 L 18 5.016 L 0 5.016 L 0 6.984 Z M 7.5 12 L 7.5 9.984 L 0 9.984 L 0 12 Z M 16.609 17.516 L 18.016 16.109 L 15.438 13.484 L 18.016 10.906 L 16.609 9.5 L 14.031 12.078 L 11.406 9.5 L 10 10.906 L 12.625 13.484 L 10 16.109 L 11.406 17.516 L 14.031 14.891 Z" /> </Svg> ), acceptRejectTrack: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Accept </title> + <title> + {' '} + <Translation label="Accept" />{' '} + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M 14.531 7.078 L 20.156 1.406 L 18.75 0 L 14.531 4.219 L 12.375 2.109 L 10.969 3.516 Z M 9 5.063 L 9 3.047 L 0 3.047 L 0 5.063 Z M 17.578 16.078 L 18.984 14.672 L 16.406 12.047 L 18.984 9.469 L 17.578 8.063 L 15 10.641 L 12.375 8.063 L 10.969 9.469 L 13.594 12.047 L 10.969 14.672 L 12.375 16.078 L 15 13.453 Z M 9 13.078 L 9 11.063 L 0 11.063 L 0 13.078 Z" /> </Svg> ), checkTrack: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Accept </title> + <title> + {' '} + <Translation label="Accept" />{' '} + </title> <path d="M0 0h24v24H0z" fill="none" /> <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" /> </Svg> @@ -493,7 +559,10 @@ export default { ), expand: ({ className }) => ( <Svg className={className} fill="none" viewBox="0 0 24 24"> - <title> Expand</title> + <title> + {' '} + <Translation label="Expand" /> + </title> <path d="M7 10l5 5 5-5z" />{' '} </Svg> ), diff --git a/wax-prosemirror-core/src/components/ui/Dropdown.js b/wax-prosemirror-core/src/components/ui/Dropdown.js index 3085205fc08110fae72cb558ebf69314a2420d14..5263ca2dd3fb8681dcae3b197facf54c87ebff67 100644 --- a/wax-prosemirror-core/src/components/ui/Dropdown.js +++ b/wax-prosemirror-core/src/components/ui/Dropdown.js @@ -1,7 +1,8 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; - +import { isEmpty } from 'lodash'; +import { useTranslation } from 'react-i18next'; import { grid, override } from '@pubsweet/ui-toolkit'; import MenuButton from './MenuButton'; @@ -22,10 +23,9 @@ const DropWrapper = styled.div` const Dropdown = props => { const { className, disabled, dropComponent, iconName, label, title } = props; - const [isOpen, setIsOpen] = useState(false); - // const dropElementRef = useRef(null); + const { t, i18n } = useTranslation(); return ( <Wrapper className={className}> @@ -33,12 +33,20 @@ const Dropdown = props => { active={isOpen} disabled={disabled} iconName={iconName} - label={label} + label={ + !isEmpty(i18n) && i18n.exists(`Wax.Various.${label}`) + ? t(`Wax.Various.${label}`) + : label + } onMouseDown={event => { event.preventDefault(); setIsOpen(!isOpen); }} - title={title} + title={ + !isEmpty(i18n) && i18n.exists(`Wax.Various.${title}`) + ? t(`Wax.Various.${title}`) + : title + } /> {isOpen && <DropWrapper>{dropComponent}</DropWrapper>} diff --git a/wax-prosemirror-core/src/helpers/Translation.js b/wax-prosemirror-core/src/helpers/Translation.js new file mode 100644 index 0000000000000000000000000000000000000000..bd4a85014d549bc2b1d8da7fd4f1fdb7b9e656db --- /dev/null +++ b/wax-prosemirror-core/src/helpers/Translation.js @@ -0,0 +1,12 @@ +/* eslint-disable react/prop-types */ +import React from 'react'; +import { isEmpty } from 'lodash'; +import { useTranslation } from 'react-i18next'; + +const Translation = ({ label, defaultTr }) => { + console.log('asdads', defaultTr); + const { t, i18n } = useTranslation(); + return <>{!isEmpty(i18n) && i18n.exists(label) ? t(label) : defaultTr}</>; +}; + +export default Translation; diff --git a/wax-prosemirror-services/src/FindAndReplaceService/components/FindComponent.js b/wax-prosemirror-services/src/FindAndReplaceService/components/FindComponent.js index eb468b51393bcbdb6d85d238088b7018660e6e7a..265ab32503f325ba33888459f66f3f680af77a08 100644 --- a/wax-prosemirror-services/src/FindAndReplaceService/components/FindComponent.js +++ b/wax-prosemirror-services/src/FindAndReplaceService/components/FindComponent.js @@ -1,7 +1,8 @@ /* eslint react/prop-types: 0 */ import React, { useState, useRef, useContext, useEffect } from 'react'; -import { each, eachRight } from 'lodash'; +import { each, eachRight, isEmpty } from 'lodash'; +import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import { grid } from '@pubsweet/ui-toolkit'; import { WaxContext, useDebounce, Icon } from 'wax-prosemirror-core'; @@ -233,6 +234,18 @@ const FindComponent = ({ searchRef.current.focus(); }; + const Translation = ({ label }) => { + const { t, i18n } = useTranslation(); + + return ( + <> + {!isEmpty(i18n) && i18n.exists(`Wax.Various.${label}`) + ? t(`Wax.Various.${label}`) + : label} + </> + ); + }; + return ( <Wrapper> <SingleRow> @@ -249,7 +262,10 @@ const FindComponent = ({ <ControlsWrapper> <IconWrapper onClick={matchCase} role="button" tabIndex="0"> <Svg active={matchCaseSearch} fill="none" viewBox="0 0 24 24"> - <title> Match Case </title> + <title> + {' '} + <Translation label="Match Case" />{' '} + </title> <path d="M2.5,4v3h5v12h3V7h5V4H2.5z M21.5,9h-9v3h3v7h3v-7h3V9z" /> </Svg> </IconWrapper>