@seafile/sdoc-editor 0.4.6 → 0.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/basic-sdk/assets/css/layout.css +12 -2
  2. package/dist/basic-sdk/constants/index.js +3 -1
  3. package/dist/basic-sdk/editor/sdoc-editor.js +7 -2
  4. package/dist/basic-sdk/extension/constants/menus-config.js +6 -0
  5. package/dist/basic-sdk/extension/plugins/code-block/render-elem.js +4 -0
  6. package/dist/basic-sdk/extension/plugins/image/hover-menu/index.js +6 -0
  7. package/dist/basic-sdk/extension/plugins/image/plugin.js +8 -2
  8. package/dist/basic-sdk/extension/plugins/image/render-elem.js +5 -1
  9. package/dist/basic-sdk/extension/plugins/index.js +3 -2
  10. package/dist/basic-sdk/extension/plugins/search-replace/constant.js +2 -0
  11. package/dist/basic-sdk/extension/plugins/search-replace/helper.js +331 -0
  12. package/dist/basic-sdk/extension/plugins/search-replace/index.js +10 -0
  13. package/dist/basic-sdk/extension/plugins/search-replace/menu/index.css +14 -0
  14. package/dist/basic-sdk/extension/plugins/search-replace/menu/index.js +78 -0
  15. package/dist/basic-sdk/extension/plugins/search-replace/plugin.js +21 -0
  16. package/dist/basic-sdk/extension/plugins/search-replace/popover/index.css +82 -0
  17. package/dist/basic-sdk/extension/plugins/search-replace/popover/index.js +211 -0
  18. package/dist/basic-sdk/extension/plugins/search-replace/popover/replace-all-confirm-modal.js +36 -0
  19. package/dist/basic-sdk/extension/toolbar/header-toolbar/index.js +7 -1
  20. package/dist/basic-sdk/utils/debounce.js +14 -0
  21. package/dist/components/doc-info/index.js +15 -11
  22. package/package.json +1 -1
  23. package/public/locales/cs/sdoc-editor.json +15 -3
  24. package/public/locales/de/sdoc-editor.json +15 -3
  25. package/public/locales/en/sdoc-editor.json +15 -3
  26. package/public/locales/es/sdoc-editor.json +15 -3
  27. package/public/locales/fr/sdoc-editor.json +15 -3
  28. package/public/locales/it/sdoc-editor.json +15 -3
  29. package/public/locales/ru/sdoc-editor.json +15 -3
  30. package/public/locales/zh_CN/sdoc-editor.json +15 -3
@@ -0,0 +1,82 @@
1
+ .sdoc-search-replace-popover-container {
2
+ position: absolute;
3
+ width: 400px;
4
+ height: 280px;
5
+ z-index: 103;
6
+ background: #fff;
7
+ border: 1px solid #ebebeb;
8
+ }
9
+
10
+ .sdoc-search-replace-popover-container .sdoc-search-replace-popover-title {
11
+ display: flex;
12
+ justify-content: space-between;
13
+ padding: 10px 15px;
14
+ border-bottom: 1px solid #ebebeb;
15
+ pointer-events: none;
16
+ user-select: none;
17
+ }
18
+
19
+ .sdoc-search-replace-popover-container .sdoc-search-replace-popover-title .sdoc-search-replace-title-text {
20
+ font-weight: 600;
21
+ color: #333;
22
+ }
23
+
24
+ .sdoc-search-replace-popover-container .sdoc-search-replace-popover-title .sdoc-search-replace-title-close {
25
+ cursor: pointer;
26
+ pointer-events: all;
27
+ }
28
+
29
+ .sdoc-search-replace-popover-container .sdoc-search-replace-popover-body {
30
+ padding: 10px 15px;
31
+ pointer-events: visibleFill;
32
+ pointer-events: none;
33
+ }
34
+
35
+ .sdoc-search-replace-popover-body label,
36
+ .sdoc-search-replace-popover-body input,
37
+ .sdoc-search-replace-popover-body button {
38
+ pointer-events: auto;
39
+ }
40
+
41
+ .sdoc-search-replace-popover-body label {
42
+ user-select: none;
43
+ }
44
+
45
+ .sdoc-search-replace-popover-body .sdoc-replace-ipt-label {
46
+ margin-top: 10px;
47
+ }
48
+
49
+ .sdoc-search-replace-popover-body .sdoc-search-replace-popover-btn-group {
50
+ margin-top: 20px;
51
+ display: flex;
52
+ justify-content: space-between;
53
+ }
54
+
55
+ .sdoc-replace-all-confirm-modal {
56
+ position: absolute;
57
+ top: 0;
58
+ left: 0;
59
+ z-index: 104;
60
+ width: 100%;
61
+ height: 100%;
62
+ background: rgba(0, 0, 0, 0.5);
63
+ }
64
+
65
+ .sdoc-replace-ipt-container {
66
+ display: flex;
67
+ position: relative;
68
+ }
69
+
70
+ .sdoc-replace-ipt-container input {
71
+ padding-right: 85px;
72
+ }
73
+
74
+ .sdoc-replace-ipt-container .sdoc-replace-ipt-tip {
75
+ position: absolute;
76
+ right: 15px;
77
+ top: 0;
78
+ height: 100%;
79
+ display: flex;
80
+ justify-content: center;
81
+ align-items: center;
82
+ }
@@ -0,0 +1,211 @@
1
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { createPortal } from 'react-dom';
3
+ import { useTranslation } from 'react-i18next';
4
+ import isHotkey from 'is-hotkey';
5
+ import { Input, Label } from 'reactstrap';
6
+ import debounce from '../../../../utils/debounce';
7
+ import { handleReplaceKeyword, getHighlightInfos, drawHighlights } from '../helper';
8
+ import ReplaceAllConfirmModal from './replace-all-confirm-modal';
9
+ import EventBus from '../../../../utils/event-bus';
10
+ import { INTERNAL_EVENT } from '../../../../constants';
11
+ import './index.css';
12
+ const SearchReplacePopover = _ref => {
13
+ let {
14
+ editor,
15
+ closePopover
16
+ } = _ref;
17
+ const [searchContent, setSearchContent] = useState('');
18
+ const [replacementContent, setReplacementContent] = useState('');
19
+ const [highlightInfos, setHighlightInfos] = useState([]);
20
+ const [isMoving, setIsMoving] = useState(false);
21
+ const [popoverPosition, setPopoverPosition] = useState({
22
+ x: 0,
23
+ y: 100
24
+ });
25
+ const [currentSelectIndex, setCurrentSelectIndex] = useState(0);
26
+ const [isOpenReplaceAllModal, setIsOpenReplaceAllModal] = useState(false);
27
+ const pageInnerSizeRef = useRef({
28
+ x: window.innerWidth,
29
+ y: window.innerHeight
30
+ });
31
+ const shouldScrollIntoView = useRef(false);
32
+ const popoverContainerRef = useRef(null);
33
+ const searchInputRef = useRef(null);
34
+ const {
35
+ t
36
+ } = useTranslation();
37
+ const searchInputSuffixContent = useMemo(() => {
38
+ if (!!searchContent.length && !highlightInfos.length) return t('Search_not_found');
39
+ if (highlightInfos.length) return "".concat(currentSelectIndex + 1, " / ").concat(highlightInfos.length);
40
+ }, [currentSelectIndex, highlightInfos.length, searchContent.length, t]);
41
+ useEffect(() => {
42
+ setPopoverPosition({
43
+ x: pageInnerSizeRef.current.x - 420,
44
+ y: 95
45
+ });
46
+ }, []);
47
+ const handleDrawHighlight = useCallback((editor, keyword) => {
48
+ const newHighlightInfos = getHighlightInfos(editor, keyword);
49
+ setHighlightInfos(newHighlightInfos);
50
+ let newSelectIndex = currentSelectIndex;
51
+ if (!shouldScrollIntoView.current && newHighlightInfos.length !== highlightInfos.length) {
52
+ newSelectIndex = 0;
53
+ }
54
+ if (newSelectIndex >= newHighlightInfos.length) {
55
+ newSelectIndex = newHighlightInfos.length - 1;
56
+ }
57
+ if (newSelectIndex < 0 && newHighlightInfos.length) {
58
+ newSelectIndex = 0;
59
+ }
60
+ setCurrentSelectIndex(newSelectIndex);
61
+ }, [currentSelectIndex, highlightInfos.length, shouldScrollIntoView]);
62
+ const handleDrawHighlightLister = useCallback(() => {
63
+ handleDrawHighlight(editor, searchContent);
64
+ pageInnerSizeRef.current = {
65
+ x: window.innerWidth,
66
+ y: window.innerHeight
67
+ };
68
+ }, [editor, handleDrawHighlight, searchContent]);
69
+ useEffect(() => {
70
+ const highlightInfos = getHighlightInfos(editor, searchContent);
71
+ drawHighlights(editor, highlightInfos, currentSelectIndex, shouldScrollIntoView.current);
72
+ shouldScrollIntoView.current = false;
73
+ }, [currentSelectIndex, editor, searchContent, highlightInfos, shouldScrollIntoView]);
74
+ useEffect(() => {
75
+ const eventBus = EventBus.getInstance();
76
+ const unSubscribe = eventBus.subscribe(INTERNAL_EVENT.UPDATE_SEARCH_REPLACE_HIGHLIGHT, handleDrawHighlightLister);
77
+ return () => {
78
+ unSubscribe();
79
+ };
80
+ }, [editor, handleDrawHighlight, handleDrawHighlightLister, highlightInfos.length, searchContent]);
81
+ const handleSearchInputChange = useCallback(e => {
82
+ const keyword = e.target.value;
83
+ setSearchContent(keyword);
84
+ handleDrawHighlight(editor, keyword);
85
+ setCurrentSelectIndex(0);
86
+ }, [editor, handleDrawHighlight]);
87
+ const handleLast = useCallback(() => {
88
+ const currentIndex = currentSelectIndex === 0 ? highlightInfos.length - 1 : currentSelectIndex - 1;
89
+ setCurrentSelectIndex(currentIndex);
90
+ shouldScrollIntoView.current = true;
91
+ }, [currentSelectIndex, highlightInfos.length]);
92
+ const handleNext = useCallback(() => {
93
+ const currentIndex = currentSelectIndex === highlightInfos.length - 1 ? 0 : currentSelectIndex + 1;
94
+ setCurrentSelectIndex(currentIndex);
95
+ shouldScrollIntoView.current = true;
96
+ }, [currentSelectIndex, highlightInfos.length]);
97
+ const handleOpenReplaceAllModal = useCallback(() => {
98
+ setIsOpenReplaceAllModal(true);
99
+ }, []);
100
+ const handleCloseReplaceAllModal = useCallback(() => {
101
+ setIsOpenReplaceAllModal(false);
102
+ }, []);
103
+ const handleReplace = useCallback(() => {
104
+ handleReplaceKeyword(editor, [highlightInfos[currentSelectIndex]], replacementContent);
105
+ shouldScrollIntoView.current = true;
106
+ }, [currentSelectIndex, editor, highlightInfos, replacementContent]);
107
+ const handleReplaceAll = useCallback(() => {
108
+ handleReplaceKeyword(editor, highlightInfos, replacementContent);
109
+ handleCloseReplaceAllModal();
110
+ }, [editor, handleCloseReplaceAllModal, highlightInfos, replacementContent]);
111
+ const handleStartMove = useCallback(e => {
112
+ if (!e.target.className.includes('sdoc-search-replace-popover-container')) return;
113
+ setIsMoving(true);
114
+ }, []);
115
+ const handleMouseMove = useCallback(e => {
116
+ if (!isMoving) return;
117
+ const {
118
+ width,
119
+ height
120
+ } = popoverContainerRef.current.getBoundingClientRect();
121
+ const {
122
+ movementX,
123
+ movementY
124
+ } = e;
125
+ let x = popoverPosition.x + movementX;
126
+ let y = popoverPosition.y + movementY;
127
+ if (x <= 0) x = 0;
128
+ if (y < 0) y = 0;
129
+ if (x + width >= pageInnerSizeRef.current.x) x = pageInnerSizeRef.current.x - width;
130
+ if (y + height >= pageInnerSizeRef.current.y) y = pageInnerSizeRef.current.y - height;
131
+ setPopoverPosition({
132
+ x,
133
+ y
134
+ });
135
+ }, [isMoving, popoverPosition.x, popoverPosition.y]);
136
+ const handleFinishMove = useCallback(() => {
137
+ setIsMoving(false);
138
+ }, []);
139
+ const handleInputKeyDown = e => {
140
+ if (!highlightInfos.length) return;
141
+ if (isHotkey('enter', e)) handleNext();
142
+ if (isHotkey('enter+shift', e)) handleLast();
143
+ };
144
+ return createPortal( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
145
+ className: "sdoc-search-replace-popover-container",
146
+ onMouseDown: handleStartMove,
147
+ onMouseMove: handleMouseMove,
148
+ onMouseUp: handleFinishMove,
149
+ onMouseLeave: handleFinishMove,
150
+ ref: popoverContainerRef,
151
+ style: {
152
+ left: popoverPosition.x,
153
+ top: popoverPosition.y
154
+ }
155
+ }, /*#__PURE__*/React.createElement("div", {
156
+ className: "sdoc-search-replace-popover-title"
157
+ }, /*#__PURE__*/React.createElement("span", {
158
+ className: "sdoc-search-replace-title-text"
159
+ }, t('Search_and_replace')), /*#__PURE__*/React.createElement("i", {
160
+ onClick: closePopover,
161
+ className: "sdocfont sdoc-sm-close sdoc-search-replace-title-close"
162
+ })), /*#__PURE__*/React.createElement("div", {
163
+ className: "sdoc-search-replace-popover-body"
164
+ }, /*#__PURE__*/React.createElement(Label, {
165
+ for: "sdoc-search-replace-search-ipt"
166
+ }, t('Search')), /*#__PURE__*/React.createElement("div", {
167
+ className: "sdoc-replace-ipt-container"
168
+ }, /*#__PURE__*/React.createElement(Input, {
169
+ ref: searchInputRef,
170
+ autoFocus: true,
171
+ onKeyUp: handleInputKeyDown,
172
+ onChange: debounce(handleSearchInputChange, 300),
173
+ id: "sdoc-search-replace-search-ipt",
174
+ placeholder: t('Type_search_content')
175
+ }), searchInputSuffixContent && /*#__PURE__*/React.createElement("div", {
176
+ className: "sdoc-replace-ipt-tip"
177
+ }, searchInputSuffixContent)), /*#__PURE__*/React.createElement(Label, {
178
+ className: "sdoc-replace-ipt-label",
179
+ for: "sdoc-search-replace-replace-ipt"
180
+ }, t('Replace_as')), /*#__PURE__*/React.createElement(Input, {
181
+ onChange: e => setReplacementContent(e.target.value),
182
+ id: "sdoc-search-replace-replace-ipt",
183
+ placeholder: t('Type_replace_content')
184
+ }), /*#__PURE__*/React.createElement("div", {
185
+ className: "sdoc-search-replace-popover-btn-group"
186
+ }, /*#__PURE__*/React.createElement("button", {
187
+ disabled: !highlightInfos.length,
188
+ onClick: handleLast,
189
+ className: "btn btn-secondary"
190
+ }, t('Previous')), /*#__PURE__*/React.createElement("button", {
191
+ disabled: !highlightInfos.length,
192
+ onClick: handleNext,
193
+ className: "btn btn-secondary"
194
+ }, t('Next')), /*#__PURE__*/React.createElement("button", {
195
+ disabled: !highlightInfos.length,
196
+ onClick: handleReplace,
197
+ className: "btn btn-primary"
198
+ }, t('Replace')), /*#__PURE__*/React.createElement("button", {
199
+ disabled: !highlightInfos.length,
200
+ onClick: handleOpenReplaceAllModal,
201
+ className: "btn btn-primary"
202
+ }, t('Replace_all'))))), /*#__PURE__*/React.createElement(ReplaceAllConfirmModal, {
203
+ isOpen: isOpenReplaceAllModal,
204
+ handleConfirm: handleReplaceAll,
205
+ handleCancel: handleCloseReplaceAllModal,
206
+ number: highlightInfos.length,
207
+ originalWord: searchContent,
208
+ replacedWord: replacementContent
209
+ })), document.body);
210
+ };
211
+ export default SearchReplacePopover;
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
4
+ const ReplaceAllConfirmModal = _ref => {
5
+ let {
6
+ isOpen,
7
+ handleConfirm,
8
+ handleCancel,
9
+ number,
10
+ originalWord,
11
+ replacedWord
12
+ } = _ref;
13
+ const {
14
+ t
15
+ } = useTranslation();
16
+ const modalContent = replacedWord === '' ? t('Are_you_sure_to_clear_all_number_xxx_in_this_document', {
17
+ number,
18
+ originalWord
19
+ }) : t('Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy', {
20
+ number,
21
+ originalWord,
22
+ replacedWord
23
+ });
24
+ return /*#__PURE__*/React.createElement(Modal, {
25
+ isOpen: isOpen
26
+ }, /*#__PURE__*/React.createElement(ModalHeader, {
27
+ toggle: handleCancel
28
+ }, t('Tip')), /*#__PURE__*/React.createElement(ModalBody, null, "".concat(modalContent)), /*#__PURE__*/React.createElement(ModalFooter, null, /*#__PURE__*/React.createElement("button", {
29
+ onClick: handleCancel,
30
+ className: "btn btn-secondary"
31
+ }, t('Cancel')), /*#__PURE__*/React.createElement("button", {
32
+ onClick: handleConfirm,
33
+ className: "btn btn-primary"
34
+ }, t('Confirm'))));
35
+ };
36
+ export default ReplaceAllConfirmModal;
@@ -14,6 +14,7 @@ import Font from '../../plugins/font/menu';
14
14
  import InsertToolbar from './insert-toolbar';
15
15
  import ActiveTableMenu from '../../plugins/table/menu/active-table-menu';
16
16
  import CalloutMenu from '../../plugins/callout/menu';
17
+ import SearchReplaceMenu from '../../plugins/search-replace/menu';
17
18
  const HeaderToolbar = _ref => {
18
19
  let {
19
20
  editor,
@@ -63,7 +64,12 @@ const HeaderToolbar = _ref => {
63
64
  })), /*#__PURE__*/React.createElement(ActiveTableMenu, {
64
65
  editor: editor,
65
66
  readonly: readonly
66
- }));
67
+ }), /*#__PURE__*/React.createElement(MenuGroup, {
68
+ className: "menu-group sdoc-editor-toolbar-right-menu"
69
+ }, /*#__PURE__*/React.createElement(SearchReplaceMenu, {
70
+ editor: editor,
71
+ readonly: readonly
72
+ })));
67
73
  };
68
74
  HeaderToolbar.defaultProps = {
69
75
  readonly: false
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @param {Function} fn
3
+ * @param {Number} delay
4
+ */
5
+ const debounce = (fn, delay) => {
6
+ let timeout = null;
7
+ return function () {
8
+ clearTimeout(timeout);
9
+ timeout = setTimeout(() => {
10
+ fn.apply(this, arguments);
11
+ }, delay);
12
+ };
13
+ };
14
+ export default debounce;
@@ -17,12 +17,23 @@ const DocInfo = _ref => {
17
17
  isEditMode,
18
18
  isPublished = false
19
19
  } = _ref;
20
+ const isSdocRevision = context.getSetting('isSdocRevision');
21
+ const docName = context.getSetting('docName');
22
+ const {
23
+ isShowInternalLink,
24
+ isStarIconShown,
25
+ isFreezed
26
+ } = context.getSettings();
20
27
  const onInternalLinkClick = useCallback(() => {
21
28
  const eventBus = EventBus.getInstance();
22
- eventBus.dispatch(EXTERNAL_EVENT.INTERNAL_LINK_CLICK, {
23
- internalLink: window.location.href
24
- });
25
- }, []);
29
+ if (isSdocRevision) {
30
+ eventBus.dispatch(EXTERNAL_EVENT.INTERNAL_LINK_CLICK, {
31
+ internalLink: window.location.href
32
+ });
33
+ return;
34
+ }
35
+ eventBus.dispatch(EXTERNAL_EVENT.INTERNAL_LINK_CLICK);
36
+ }, [isSdocRevision]);
26
37
  const toggleStar = useCallback(() => {
27
38
  const eventBus = EventBus.getInstance();
28
39
  eventBus.dispatch(EXTERNAL_EVENT.TOGGLE_STAR);
@@ -31,13 +42,6 @@ const DocInfo = _ref => {
31
42
  const originFileURL = context.getSetting('originFileURL');
32
43
  window.open(originFileURL, '_blank');
33
44
  }, []);
34
- const isSdocRevision = context.getSetting('isSdocRevision');
35
- const docName = context.getSetting('docName');
36
- const {
37
- isShowInternalLink,
38
- isStarIconShown,
39
- isFreezed
40
- } = context.getSettings();
41
45
  const docInfo = /*#__PURE__*/React.createElement(React.Fragment, null, isDraft && /*#__PURE__*/React.createElement(DraftDropdown, null), isStarIconShown && /*#__PURE__*/React.createElement("button", {
42
46
  className: "doc-icon sdocfont ".concat(isStarred ? 'sdoc-starred' : 'sdoc-unstarred', " border-0 p-0 bg-transparent"),
43
47
  title: isStarred ? t('Starred') : t('Unstarred'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.4.6",
3
+ "version": "0.4.8",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -424,9 +424,21 @@
424
424
  "Row_number": "Row number",
425
425
  "Column_number": "Column number",
426
426
  "The_maximum_row_number_is_{number}": "The maximum row number is {number}",
427
- "Freeze_Document": "Freeze document",
428
- "Unfreeze": "Unfreeze",
429
427
  "Other_modification": "Other's modification",
430
428
  "My_modification": "My modification",
431
- "Document_history": "Document history"
429
+ "Document_history": "Document history",
430
+ "Freeze_Document": "Freeze Document",
431
+ "Unfreeze": "Unfreeze",
432
+ "Search_and_replace": "Search and replace",
433
+ "Search": "Hledat",
434
+ "Type_search_content": "Type search content",
435
+ "Replace_as": "Replace as",
436
+ "Type_replace_content": "Type replace content",
437
+ "Previous": "Předchozí",
438
+ "Next": "Další",
439
+ "Replace": "Nahradit",
440
+ "Replace_all": "Replace all",
441
+ "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "Are you sure to replace all {{number}} '{{originalWord}}' in this document with '{{replacedWord}}'?",
442
+ "Are_you_sure_to_clear_all_number_xxx_in_this_document": "Are you sure to clear all {{number}} '{{originalWord}}' in this document?",
443
+ "Search_not_found": "Not found"
432
444
  }
@@ -424,9 +424,21 @@
424
424
  "Row_number": "Row number",
425
425
  "Column_number": "Column number",
426
426
  "The_maximum_row_number_is_{number}": "The maximum row number is {number}",
427
- "Freeze_Document": "Freeze document",
428
- "Unfreeze": "Unfreeze",
429
427
  "Other_modification": "Other's modification",
430
428
  "My_modification": "My modification",
431
- "Document_history": "Document history"
429
+ "Document_history": "Document history",
430
+ "Freeze_Document": "Freeze Document",
431
+ "Unfreeze": "Unfreeze",
432
+ "Search_and_replace": "Search and replace",
433
+ "Search": "Suchen",
434
+ "Type_search_content": "Type search content",
435
+ "Replace_as": "Replace as",
436
+ "Type_replace_content": "Type replace content",
437
+ "Previous": "Vorherige",
438
+ "Next": "Nächste Seite",
439
+ "Replace": "Ersetzen",
440
+ "Replace_all": "Replace all",
441
+ "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "Are you sure to replace all {{number}} '{{originalWord}}' in this document with '{{replacedWord}}'?",
442
+ "Are_you_sure_to_clear_all_number_xxx_in_this_document": "Are you sure to clear all {{number}} '{{originalWord}}' in this document?",
443
+ "Search_not_found": "Not found"
432
444
  }
@@ -424,9 +424,21 @@
424
424
  "Row_number": "Row number",
425
425
  "Column_number": "Column number",
426
426
  "The_maximum_row_number_is_{number}": "The maximum row number is {number}",
427
- "Freeze_Document": "Freeze document",
428
- "Unfreeze": "Unfreeze",
429
427
  "Other_modification": "Other's modification",
430
428
  "My_modification": "My modification",
431
- "Document_history": "Document history"
429
+ "Document_history": "Document history",
430
+ "Freeze_Document": "Freeze Document",
431
+ "Unfreeze": "Unfreeze",
432
+ "Search_and_replace": "Search and replace",
433
+ "Search": "Search",
434
+ "Type_search_content": "Type search content",
435
+ "Replace_as": "Replace as",
436
+ "Type_replace_content": "Type replace content",
437
+ "Previous": "Previous",
438
+ "Next": "Next",
439
+ "Replace": "Replace",
440
+ "Replace_all": "Replace all",
441
+ "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "Are you sure to replace all {{number}} '{{originalWord}}' in this document with '{{replacedWord}}'?",
442
+ "Are_you_sure_to_clear_all_number_xxx_in_this_document": "Are you sure to clear all {{number}} '{{originalWord}}' in this document?",
443
+ "Search_not_found": "Not found"
432
444
  }
@@ -424,9 +424,21 @@
424
424
  "Row_number": "Row number",
425
425
  "Column_number": "Column number",
426
426
  "The_maximum_row_number_is_{number}": "The maximum row number is {number}",
427
- "Freeze_Document": "Freeze document",
428
- "Unfreeze": "Unfreeze",
429
427
  "Other_modification": "Other's modification",
430
428
  "My_modification": "My modification",
431
- "Document_history": "Document history"
429
+ "Document_history": "Document history",
430
+ "Freeze_Document": "Freeze Document",
431
+ "Unfreeze": "Unfreeze",
432
+ "Search_and_replace": "Search and replace",
433
+ "Search": "Buscar",
434
+ "Type_search_content": "Type search content",
435
+ "Replace_as": "Replace as",
436
+ "Type_replace_content": "Type replace content",
437
+ "Previous": "Anterior",
438
+ "Next": "Siguiente",
439
+ "Replace": "Reemplazar",
440
+ "Replace_all": "Replace all",
441
+ "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "Are you sure to replace all {{number}} '{{originalWord}}' in this document with '{{replacedWord}}'?",
442
+ "Are_you_sure_to_clear_all_number_xxx_in_this_document": "Are you sure to clear all {{number}} '{{originalWord}}' in this document?",
443
+ "Search_not_found": "Not found"
432
444
  }
@@ -424,9 +424,21 @@
424
424
  "Row_number": "Row number",
425
425
  "Column_number": "Column number",
426
426
  "The_maximum_row_number_is_{number}": "The maximum row number is {number}",
427
- "Freeze_Document": "Freeze document",
428
- "Unfreeze": "Unfreeze",
429
427
  "Other_modification": "Other's modification",
430
428
  "My_modification": "My modification",
431
- "Document_history": "Document history"
429
+ "Document_history": "Document history",
430
+ "Freeze_Document": "Freeze Document",
431
+ "Unfreeze": "Unfreeze",
432
+ "Search_and_replace": "Search and replace",
433
+ "Search": "Chercher",
434
+ "Type_search_content": "Type search content",
435
+ "Replace_as": "Replace as",
436
+ "Type_replace_content": "Type replace content",
437
+ "Previous": "Précédent",
438
+ "Next": "Suivant",
439
+ "Replace": "Remplacer",
440
+ "Replace_all": "Replace all",
441
+ "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "Are you sure to replace all {{number}} '{{originalWord}}' in this document with '{{replacedWord}}'?",
442
+ "Are_you_sure_to_clear_all_number_xxx_in_this_document": "Are you sure to clear all {{number}} '{{originalWord}}' in this document?",
443
+ "Search_not_found": "Not found"
432
444
  }
@@ -424,9 +424,21 @@
424
424
  "Row_number": "Row number",
425
425
  "Column_number": "Column number",
426
426
  "The_maximum_row_number_is_{number}": "The maximum row number is {number}",
427
- "Freeze_Document": "Freeze document",
428
- "Unfreeze": "Unfreeze",
429
427
  "Other_modification": "Other's modification",
430
428
  "My_modification": "My modification",
431
- "Document_history": "Document history"
429
+ "Document_history": "Document history",
430
+ "Freeze_Document": "Freeze Document",
431
+ "Unfreeze": "Unfreeze",
432
+ "Search_and_replace": "Search and replace",
433
+ "Search": "Search",
434
+ "Type_search_content": "Type search content",
435
+ "Replace_as": "Replace as",
436
+ "Type_replace_content": "Type replace content",
437
+ "Previous": "Precedente",
438
+ "Next": "Successivo",
439
+ "Replace": "Sostituire",
440
+ "Replace_all": "Replace all",
441
+ "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "Are you sure to replace all {{number}} '{{originalWord}}' in this document with '{{replacedWord}}'?",
442
+ "Are_you_sure_to_clear_all_number_xxx_in_this_document": "Are you sure to clear all {{number}} '{{originalWord}}' in this document?",
443
+ "Search_not_found": "Not found"
432
444
  }
@@ -424,9 +424,21 @@
424
424
  "Row_number": "Номер строки",
425
425
  "Column_number": "Номер столбца",
426
426
  "The_maximum_row_number_is_{number}": "Максимальное количество строк - {number}",
427
- "Freeze_Document": "Freeze document",
428
- "Unfreeze": "Разморозить",
429
427
  "Other_modification": "Другая модификация",
430
428
  "My_modification": "Моя модификация",
431
- "Document_history": "История документа"
429
+ "Document_history": "История документа",
430
+ "Freeze_Document": "Заморозить документ",
431
+ "Unfreeze": "Разморозить",
432
+ "Search_and_replace": "Search and replace",
433
+ "Search": "Поиск",
434
+ "Type_search_content": "Type search content",
435
+ "Replace_as": "Replace as",
436
+ "Type_replace_content": "Type replace content",
437
+ "Previous": "Предыдущий",
438
+ "Next": "Следующий",
439
+ "Replace": "Заменить",
440
+ "Replace_all": "Replace all",
441
+ "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "Are you sure to replace all {{number}} '{{originalWord}}' in this document with '{{replacedWord}}'?",
442
+ "Are_you_sure_to_clear_all_number_xxx_in_this_document": "Are you sure to clear all {{number}} '{{originalWord}}' in this document?",
443
+ "Search_not_found": "Not found"
432
444
  }
@@ -424,9 +424,21 @@
424
424
  "Row_number": "行数",
425
425
  "Column_number": "列数",
426
426
  "The_maximum_row_number_is_{number}": "最大行数为 {number}",
427
- "Freeze_Document": "冻结文档",
428
- "Unfreeze": "取消冻结",
429
427
  "Other_modification": "他人更改",
430
428
  "My_modification": "我的更改",
431
- "Document_history": "文档历史"
429
+ "Document_history": "文档历史",
430
+ "Freeze_Document": "冻结文档",
431
+ "Unfreeze": "取消冻结",
432
+ "Search_and_replace": "查找和替换",
433
+ "Search": "搜索",
434
+ "Type_search_content": "输入查找内容",
435
+ "Replace_as": "替换为",
436
+ "Type_replace_content": "输入替换内容",
437
+ "Previous": "上一个",
438
+ "Next": "下一页",
439
+ "Replace": "替换",
440
+ "Replace_all": "下一个",
441
+ "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "确定要将此文档内的 {{number}} 处 \"{{originalWord}} \" 替换为 \"{{replacedWord}} \" 吗?",
442
+ "Are_you_sure_to_clear_all_number_xxx_in_this_document": "确定将此文档内的 {{number}} 处 \"{{originalWord}}\" 全部清除吗?",
443
+ "Search_not_found": "未找到"
432
444
  }