소스 검색

Merge pull request #13061 from overleaf/mj-cm6-translations

[web] Make translations accessible to CM6

GitOrigin-RevId: ef617638419597548e6e0545bac3ac94216177de
Mathias Jakobsen 3 년 전
부모
커밋
5fd4504f51

+ 1 - 0
services/web/frontend/extracted-translations.json

@@ -769,6 +769,7 @@
   "select_tag": "",
   "select_user": "",
   "selected": "",
+  "selection_deleted": "",
   "send": "",
   "send_first_message": "",
   "sending": "",

+ 1 - 1
services/web/frontend/js/features/source-editor/extensions/visual-line-selection.ts

@@ -141,7 +141,7 @@ function deleteBy(target: CommandTarget, by: (start: number) => number) {
       userEvent: event,
       effects:
         event == 'delete.selection'
-          ? EditorView.announce.of(state.phrase('Selection deleted'))
+          ? EditorView.announce.of(state.phrase('selection_deleted'))
           : undefined,
     })
   )

+ 1 - 1
services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/end-document.ts

@@ -5,7 +5,7 @@ export class EndDocumentWidget extends WidgetType {
   toDOM(view: EditorView): HTMLElement {
     const element = document.createElement('div')
     element.classList.add('ol-cm-end-document-widget')
-    element.textContent = view.state.phrase('End of document')
+    element.textContent = view.state.phrase('end_of_document')
     element.addEventListener('mouseup', event => {
       event.preventDefault()
       view.dispatch(placeSelectionInsideBlock(view, event as MouseEvent))

+ 3 - 3
services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/preamble.ts

@@ -26,7 +26,7 @@ export class PreambleWidget extends WidgetType {
     helpLink.target = '_blank'
     const icon = document.createElement('i')
     icon.classList.add('fa', 'fa-question-circle')
-    icon.title = view.state.phrase('Learn more')
+    icon.title = view.state.phrase('learn_more')
     helpLink.appendChild(icon)
     const textNode = document.createElement('span')
     textNode.classList.add('ol-cm-preamble-text')
@@ -72,8 +72,8 @@ export class PreambleWidget extends WidgetType {
 
   getToggleText(view: EditorView) {
     if (this.expanded) {
-      return view.state.phrase(`Hide document preamble`)
+      return view.state.phrase(`hide_document_preamble`)
     }
-    return view.state.phrase(`Show document preamble`)
+    return view.state.phrase(`show_document_preamble`)
   }
 }

+ 44 - 9
services/web/frontend/js/features/source-editor/hooks/use-phrases.ts

@@ -2,16 +2,51 @@ import { useTranslation } from 'react-i18next'
 import { useMemo } from 'react'
 
 export const usePhrases = (): Record<string, string> => {
-  const { t } = useTranslation()
+  const { t, i18n } = useTranslation()
 
-  return useMemo(() => {
-    return {
+  const codemirrorBuiltinsOverrides = useMemo(
+    () => ({
       'Fold line': t('fold_line'),
       'Unfold line': t('unfold_line'),
-      'Learn more': t('learn_more'),
-      'Hide document preamble': t('hide_document_preamble'),
-      'Show document preamble': t('show_document_preamble'),
-      'End of document': t('end_of_document'),
-    }
-  }, [t])
+    }),
+    [t]
+  )
+
+  const translationProxy = useMemo(
+    () => ({
+      getOwnPropertyDescriptor(target: Record<string, string>, prop: string) {
+        // If we've added an override
+        if (Object.prototype.hasOwnProperty.call(target, prop)) {
+          return Object.getOwnPropertyDescriptor(target, prop)
+        }
+        // If the translation exists, report a property:
+        //   non-enumerable: it won't show up in enumerating the keys of the target
+        //   configurable: we have to report it as configurable since it doesn't
+        //                 exist in the base object
+        //   writable: an override can be added
+        if (i18n.exists(prop)) {
+          return { enumerable: false, configurable: true, writable: true }
+        }
+        return Object.getOwnPropertyDescriptor(target, prop)
+      },
+      get(target: Record<string, string>, prop: string) {
+        // If we've specifically added an override
+        if (Object.prototype.hasOwnProperty.call(target, prop)) {
+          return target[prop]
+        }
+        if (i18n.exists(prop)) {
+          return t(prop)
+        }
+        return target[prop]
+      },
+    }),
+    [t, i18n]
+  )
+
+  const phrases = useMemo(
+    () => new Proxy(codemirrorBuiltinsOverrides, translationProxy),
+    [translationProxy, codemirrorBuiltinsOverrides]
+  )
+
+  return phrases
 }

+ 1 - 1
services/web/i18next-scanner.config.js

@@ -12,7 +12,7 @@ module.exports = {
   options: {
     sort: true,
     func: {
-      list: ['t'],
+      list: ['t', 'phrase'],
       extensions: ['.js', '.jsx'],
     },
     trans: {

+ 1 - 0
services/web/locales/en.json

@@ -1319,6 +1319,7 @@
   "select_tag": "Select tag __tagName__",
   "select_user": "Select user",
   "selected": "Selected",
+  "selection_deleted": "Selection deleted",
   "send": "Send",
   "send_first_message": "Send your first message to your collaborators",
   "send_test_email": "Send a test email",