Просмотр исходного кода

Merge pull request #26244 from overleaf/td-limit-browser-translate-ide

Prevent browser translation of stuff that shouldn't be translated in IDE page

GitOrigin-RevId: 96a75b51c3c8efc4cbcec7eb17d9e331a03e2c96
Tim Down 1 год назад
Родитель
Сommit
ab140f578d
41 измененных файлов с 94 добавлено и 29 удалено
  1. 3 3
      services/web/app/views/_metadata.pug
  2. 1 1
      services/web/frontend/js/features/chat/components/message-content.tsx
  3. 1 1
      services/web/frontend/js/features/chat/components/message.tsx
  4. 3 1
      services/web/frontend/js/features/dictionary/components/dictionary-modal-content.tsx
  5. 5 3
      services/web/frontend/js/features/editor-left-menu/components/left-menu-button.tsx
  6. 1 0
      services/web/frontend/js/features/editor-left-menu/components/settings/settings-compiler.tsx
  7. 1 0
      services/web/frontend/js/features/editor-left-menu/components/settings/settings-document.tsx
  8. 1 0
      services/web/frontend/js/features/editor-left-menu/components/settings/settings-editor-theme.tsx
  9. 1 0
      services/web/frontend/js/features/editor-left-menu/components/settings/settings-font-family.tsx
  10. 1 0
      services/web/frontend/js/features/editor-left-menu/components/settings/settings-image-name.tsx
  11. 3 0
      services/web/frontend/js/features/editor-left-menu/components/settings/settings-menu-select.tsx
  12. 1 0
      services/web/frontend/js/features/editor-left-menu/components/settings/settings-pdf-viewer.tsx
  13. 1 0
      services/web/frontend/js/features/editor-navigation-toolbar/components/online-users-widget.tsx
  14. 1 0
      services/web/frontend/js/features/file-tree/components/file-tree-doc.tsx
  15. 1 0
      services/web/frontend/js/features/file-tree/components/file-tree-folder.tsx
  16. 2 0
      services/web/frontend/js/features/history/components/change-list/changes.tsx
  17. 15 6
      services/web/frontend/js/features/history/components/change-list/tag-tooltip.tsx
  18. 9 1
      services/web/frontend/js/features/history/components/change-list/user-name-with-colored-badge.tsx
  19. 1 0
      services/web/frontend/js/features/history/components/file-tree/history-file-tree-doc.tsx
  20. 1 0
      services/web/frontend/js/features/history/components/file-tree/history-file-tree-folder.tsx
  21. 1 1
      services/web/frontend/js/features/ide-redesign/components/breadcrumbs.tsx
  22. 1 0
      services/web/frontend/js/features/ide-redesign/components/settings/appearance-settings/editor-theme-setting.tsx
  23. 1 0
      services/web/frontend/js/features/ide-redesign/components/settings/appearance-settings/font-family-setting.tsx
  24. 1 0
      services/web/frontend/js/features/ide-redesign/components/settings/compiler-settings/compiler-setting.tsx
  25. 1 0
      services/web/frontend/js/features/ide-redesign/components/settings/compiler-settings/image-name-setting.tsx
  26. 1 0
      services/web/frontend/js/features/ide-redesign/components/settings/compiler-settings/root-document-setting.tsx
  27. 3 0
      services/web/frontend/js/features/ide-redesign/components/settings/dropdown-setting.tsx
  28. 1 0
      services/web/frontend/js/features/ide-redesign/components/settings/editor-settings/pdf-viewer-setting.tsx
  29. 3 1
      services/web/frontend/js/features/ide-redesign/components/toolbar/project-title.tsx
  30. 1 0
      services/web/frontend/js/features/outline/components/outline-item.tsx
  31. 1 1
      services/web/frontend/js/features/pdf-preview/components/pdf-log-entry-raw-content.tsx
  32. 6 2
      services/web/frontend/js/features/preview/components/preview-log-entry-header.tsx
  33. 1 1
      services/web/frontend/js/features/review-panel-new/components/review-panel-entry-user.tsx
  34. 3 0
      services/web/frontend/js/features/review-panel-new/components/review-panel-expandable-content.tsx
  35. 1 0
      services/web/frontend/js/features/review-panel-new/components/review-panel-message.tsx
  36. 5 1
      services/web/frontend/js/features/review-panel-new/components/review-panel-resolved-thread.tsx
  37. 1 1
      services/web/frontend/js/features/source-editor/extensions/toolbar/toolbar-panel.ts
  38. 1 0
      services/web/frontend/js/shared/components/collapsible-file-header.tsx
  39. 5 3
      services/web/test/acceptance/src/ProjectInviteTests.mjs
  40. 1 1
      services/web/test/acceptance/src/helpers/expectErrorResponse.mjs
  41. 2 1
      services/web/test/smoke/src/steps/100_loadProjectDashboard.js

+ 3 - 3
services/web/app/views/_metadata.pug

@@ -1,10 +1,10 @@
 //- Title
 if metadata && metadata.title
-	title= metadata.title + ' - ' + settings.appName + ', ' + translate('online_latex_editor')
+	title(translate='no')= metadata.title + ' - ' + settings.appName + ', ' + translate('online_latex_editor')
 	meta(name='twitter:title' content=metadata.title)
 	meta(name='og:title' content=metadata.title)
 else if typeof title == 'undefined'
-	title= settings.appName + ', ' + translate('online_latex_editor')
+	title(translate='no')= settings.appName + ', ' + translate('online_latex_editor')
 	meta(
 		name='twitter:title'
 		content=settings.appName + ', ' + translate('online_latex_editor')
@@ -14,7 +14,7 @@ else if typeof title == 'undefined'
 		content=settings.appName + ', ' + translate('online_latex_editor')
 	)
 else
-	title= translate(title) + ' - ' + settings.appName + ', ' + translate('online_latex_editor')
+	title(translate='no')= translate(title) + ' - ' + settings.appName + ', ' + translate('online_latex_editor')
 	//- to do - not translate?
 	meta(name='twitter:title' content=translate(title))
 	meta(name='og:title' content=translate(title))

+ 1 - 1
services/web/frontend/js/features/chat/components/message-content.tsx

@@ -34,7 +34,7 @@ const MessageContent: FC<{ content: string }> = ({ content }) => {
   }, [content, mounted])
 
   return (
-    <p ref={root}>
+    <p ref={root} translate="no">
       <Linkify>{content}</Linkify>
     </p>
   )

+ 1 - 1
services/web/frontend/js/features/chat/components/message.tsx

@@ -29,7 +29,7 @@ function Message({ message, fromSelf }: MessageProps) {
   return (
     <div className="message-wrapper">
       {!fromSelf && (
-        <div className="name">
+        <div className="name" translate="no">
           <span>{message.user.first_name || message.user.email}</span>
         </div>
       )}

+ 3 - 1
services/web/frontend/js/features/dictionary/components/dictionary-modal-content.tsx

@@ -68,7 +68,9 @@ export default function DictionaryModalContent({
           <ul className="list-unstyled dictionary-entries-list">
             {[...learnedWords].sort(wordsSortFunction).map(learnedWord => (
               <li key={learnedWord} className="dictionary-entry">
-                <span className="dictionary-entry-name">{learnedWord}</span>
+                <span className="dictionary-entry-name" translate="no">
+                  {learnedWord}
+                </span>
                 <OLTooltip
                   id={`tooltip-remove-learned-word-${learnedWord}`}
                   description={t('edit_dictionary_remove')}

+ 5 - 3
services/web/frontend/js/features/editor-left-menu/components/left-menu-button.tsx

@@ -9,6 +9,7 @@ type Props = {
   disabledAccesibilityText?: string
   type?: 'button' | 'link'
   href?: string
+  translate?: React.HTMLAttributes<HTMLElement>['translate']
 }
 
 function LeftMenuButtonIcon({
@@ -34,12 +35,13 @@ export default function LeftMenuButton({
   disabledAccesibilityText,
   type = 'button',
   href,
+  translate,
 }: PropsWithChildren<Props>) {
   if (disabled) {
     return (
       <div className="left-menu-button link-disabled">
         <LeftMenuButtonIcon svgIcon={svgIcon} icon={icon} />
-        <span>{children}</span>
+        <span translate={translate}>{children}</span>
         {disabledAccesibilityText ? (
           <span className="sr-only">{disabledAccesibilityText}</span>
         ) : null}
@@ -51,7 +53,7 @@ export default function LeftMenuButton({
     return (
       <button onClick={onClick} className="left-menu-button">
         <LeftMenuButtonIcon svgIcon={svgIcon} icon={icon} />
-        <span>{children}</span>
+        <span translate={translate}>{children}</span>
       </button>
     )
   } else {
@@ -63,7 +65,7 @@ export default function LeftMenuButton({
         className="left-menu-button"
       >
         <LeftMenuButtonIcon svgIcon={svgIcon} icon={icon} />
-        <span>{children}</span>
+        <span translate={translate}>{children}</span>
       </a>
     )
   }

+ 1 - 0
services/web/frontend/js/features/editor-left-menu/components/settings/settings-compiler.tsx

@@ -34,6 +34,7 @@ export default function SettingsCompiler() {
       ]}
       label={t('compiler')}
       name="compiler"
+      translateOptions="no"
     />
   )
 }

+ 1 - 0
services/web/frontend/js/features/editor-left-menu/components/settings/settings-document.tsx

@@ -43,6 +43,7 @@ export default function SettingsDocument() {
       options={validDocsOptions}
       label={t('main_document')}
       name="rootDocId"
+      translateOptions="no"
     />
   )
 }

+ 1 - 0
services/web/frontend/js/features/editor-left-menu/components/settings/settings-editor-theme.tsx

@@ -40,6 +40,7 @@ export default function SettingsEditorTheme() {
       options={options}
       label={t('editor_theme')}
       name="editorTheme"
+      translateOptions="no"
     />
   )
 }

+ 1 - 0
services/web/frontend/js/features/editor-left-menu/components/settings/settings-font-family.tsx

@@ -29,6 +29,7 @@ export default function SettingsFontFamily() {
         ]}
         label={t('font_family')}
         name="fontFamily"
+        translateOptions="no"
       />
       <BetaBadge
         phase="release"

+ 1 - 0
services/web/frontend/js/features/editor-left-menu/components/settings/settings-image-name.tsx

@@ -37,6 +37,7 @@ export default function SettingsImageName() {
       options={options}
       label={t('tex_live_version')}
       name="imageName"
+      translateOptions="no"
     />
   )
 }

+ 3 - 0
services/web/frontend/js/features/editor-left-menu/components/settings/settings-menu-select.tsx

@@ -28,6 +28,7 @@ type SettingsMenuSelectProps<T extends PossibleValue = string> = {
   onChange: (val: T) => void
   value?: T
   disabled?: boolean
+  translateOptions?: 'yes' | 'no'
 }
 
 export default function SettingsMenuSelect<T extends PossibleValue = string>({
@@ -39,6 +40,7 @@ export default function SettingsMenuSelect<T extends PossibleValue = string>({
   onChange,
   value,
   disabled = false,
+  translateOptions,
 }: SettingsMenuSelectProps<T>) {
   const handleChange: ChangeEventHandler<HTMLSelectElement> = useCallback(
     event => {
@@ -95,6 +97,7 @@ export default function SettingsMenuSelect<T extends PossibleValue = string>({
           value={value?.toString()}
           disabled={disabled}
           ref={selectRef}
+          translate={translateOptions}
         >
           {options.map(option => (
             <option

+ 1 - 0
services/web/frontend/js/features/editor-left-menu/components/settings/settings-pdf-viewer.tsx

@@ -23,6 +23,7 @@ export default function SettingsPdfViewer() {
       ]}
       label={t('pdf_viewer')}
       name="pdfViewer"
+      translateOptions="no"
     />
   )
 }

+ 1 - 0
services/web/frontend/js/features/editor-navigation-toolbar/components/online-users-widget.tsx

@@ -60,6 +60,7 @@ function OnlineUsersWidget({
             id="online-user"
             description={user.name}
             overlayProps={{ placement: 'bottom', trigger: ['hover', 'focus'] }}
+            tooltipProps={{ translate: 'no' }}
           >
             <span>
               {/* OverlayTrigger won't fire unless UserIcon is wrapped in a span */}

+ 1 - 0
services/web/frontend/js/features/file-tree/components/file-tree-doc.tsx

@@ -28,6 +28,7 @@ function FileTreeDoc({
       {...selectableEntityProps}
       aria-label={name}
       tabIndex={0}
+      translate="no"
     >
       <FileTreeItemInner
         id={id}

+ 1 - 0
services/web/frontend/js/features/file-tree/components/file-tree-folder.tsx

@@ -67,6 +67,7 @@ function FileTreeFolder({
         className={classNames(selectableEntityProps.className, {
           'dnd-droppable-hover': isOverRoot || isOverList,
         })}
+        translate="no"
       >
         <FileTreeItemInner
           id={id}

+ 2 - 0
services/web/frontend/js/features/history/components/change-list/changes.tsx

@@ -23,6 +23,7 @@ function Changes({ pathnames, projectOps }: ChangesProps) {
           <div
             className="history-version-change-doc"
             data-testid="history-version-change-doc"
+            translate="no"
           >
             {pathname}
           </div>
@@ -41,6 +42,7 @@ function Changes({ pathnames, projectOps }: ChangesProps) {
           <div
             className="history-version-change-doc"
             data-testid="history-version-change-doc"
+            translate="no"
           >
             {getProjectOpDoc(op)}
           </div>

+ 15 - 6
services/web/frontend/js/features/history/components/change-list/tag-tooltip.tsx

@@ -87,6 +87,7 @@ const ChangeTag = forwardRef<HTMLElement, TagProps>(
           className="history-version-badge"
           data-testid="history-version-badge"
           {...props}
+          translate={isPseudoCurrentStateLabel ? 'yes' : 'no'}
         >
           {isPseudoCurrentStateLabel
             ? t('history_label_project_current_state')
@@ -147,24 +148,32 @@ function TagTooltip({ label, currentUserId, showTooltip }: LabelBadgesProps) {
 
   const isPseudoCurrentStateLabel = isPseudoLabel(label)
   const currentLabelData = allLabels?.find(({ id }) => id === label.id)
-  const labelOwnerName =
-    currentLabelData && !isPseudoLabel(currentLabelData)
-      ? currentLabelData.user_display_name
-      : t('anonymous')
+  const isAnonymous = !currentLabelData || isPseudoLabel(currentLabelData)
+  const labelOwnerName = isAnonymous
+    ? t('anonymous')
+    : currentLabelData.user_display_name
+  const labelOwnerNameComponent = isAnonymous ? (
+    labelOwnerName
+  ) : (
+    <span translate="no">{labelOwnerName}</span>
+  )
 
   return !isPseudoCurrentStateLabel ? (
     <OLTooltip
       description={
         <div className="history-version-label-tooltip">
           <div className="history-version-label-tooltip-row">
-            <b className="history-version-label-tooltip-row-comment">
+            <b
+              className="history-version-label-tooltip-row-comment"
+              translate="no"
+            >
               <OLTagIcon />
               &nbsp;
               {label.comment}
             </b>
           </div>
           <div className="history-version-label-tooltip-row">
-            {t('history_label_created_by')} {labelOwnerName}
+            {t('history_label_created_by')} {labelOwnerNameComponent}
           </div>
           <div className="history-version-label-tooltip-row">
             <time>

+ 9 - 1
services/web/frontend/js/features/history/components/change-list/user-name-with-colored-badge.tsx

@@ -14,6 +14,7 @@ function UserNameWithColoredBadge({
   currentUserId,
 }: UserNameWithColoredBadgeProps) {
   const { t } = useTranslation()
+  let allowBrowserTranslate = true
 
   let userName: string
   if (!user) {
@@ -22,8 +23,10 @@ function UserNameWithColoredBadge({
     userName = t('you')
   } else if ('displayName' in user) {
     userName = user.displayName
+    allowBrowserTranslate = false
   } else {
     userName = formatUserName(user)
+    allowBrowserTranslate = false
   }
 
   return (
@@ -32,7 +35,12 @@ function UserNameWithColoredBadge({
         className="history-version-user-badge-color"
         style={{ backgroundColor: getBackgroundColorForUserId(user?.id) }}
       />
-      <span className="history-version-user-badge-text">{userName}</span>
+      <span
+        className="history-version-user-badge-text"
+        translate={allowBrowserTranslate ? 'yes' : 'no'}
+      >
+        {userName}
+      </span>
     </>
   )
 }

+ 1 - 0
services/web/frontend/js/features/history/components/file-tree/history-file-tree-doc.tsx

@@ -42,6 +42,7 @@ function HistoryFileTreeDoc({
       aria-selected={selected}
       aria-label={name}
       tabIndex={0}
+      translate="no"
     >
       <HistoryFileTreeItem
         name={name}

+ 1 - 0
services/web/frontend/js/features/history/components/file-tree/history-file-tree-folder.tsx

@@ -79,6 +79,7 @@ function HistoryFileTreeFolder({
             setExpanded(!expanded)
           }
         }}
+        translate="no"
       >
         <HistoryFileTreeItem name={name} icons={icons} />
       </li>

+ 1 - 1
services/web/frontend/js/features/ide-redesign/components/breadcrumbs.tsx

@@ -83,7 +83,7 @@ export default function Breadcrumbs() {
   const numOutlineItems = outlineHierarchy.length
 
   return (
-    <div className="ol-cm-breadcrumbs">
+    <div className="ol-cm-breadcrumbs" translate="no">
       {folderHierarchy.map(folder => (
         <Fragment key={folder._id}>
           <div>{folder.name}</div>

+ 1 - 0
services/web/frontend/js/features/ide-redesign/components/settings/appearance-settings/editor-theme-setting.tsx

@@ -41,6 +41,7 @@ export default function EditorThemeSetting() {
       options={options}
       onChange={setEditorTheme}
       value={editorTheme}
+      translateOptions="no"
     />
   )
 }

+ 1 - 0
services/web/frontend/js/features/ide-redesign/components/settings/appearance-settings/font-family-setting.tsx

@@ -27,6 +27,7 @@ export default function FontFamilySetting() {
       onChange={setFontFamily}
       value={fontFamily}
       width="wide"
+      translateOptions="no"
     />
   )
 }

+ 1 - 0
services/web/frontend/js/features/ide-redesign/components/settings/compiler-settings/compiler-setting.tsx

@@ -38,6 +38,7 @@ export default function CompilerSetting() {
       options={OPTIONS}
       onChange={setCompiler}
       value={compiler}
+      translateOptions="no"
     />
   )
 }

+ 1 - 0
services/web/frontend/js/features/ide-redesign/components/settings/compiler-settings/image-name-setting.tsx

@@ -38,6 +38,7 @@ export default function ImageNameSetting() {
       options={options}
       onChange={setImageName}
       value={imageName}
+      translateOptions="no"
     />
   )
 }

+ 1 - 0
services/web/frontend/js/features/ide-redesign/components/settings/compiler-settings/root-document-setting.tsx

@@ -44,6 +44,7 @@ export default function RootDocumentSetting() {
       options={validDocsOptions}
       onChange={setRootDocId}
       value={rootDocId}
+      translateOptions="no"
     />
   )
 }

+ 3 - 0
services/web/frontend/js/features/ide-redesign/components/settings/dropdown-setting.tsx

@@ -31,6 +31,7 @@ type SettingsMenuSelectProps<T extends PossibleValue = string> = {
   disabled?: boolean
   width?: 'default' | 'wide'
   loading?: boolean
+  translateOptions?: 'yes' | 'no'
 }
 
 export default function DropdownSetting<T extends PossibleValue = string>({
@@ -44,6 +45,7 @@ export default function DropdownSetting<T extends PossibleValue = string>({
   disabled = false,
   width = 'default',
   loading = false,
+  translateOptions,
 }: SettingsMenuSelectProps<T>) {
   const handleChange: ChangeEventHandler<HTMLSelectElement> = useCallback(
     event => {
@@ -78,6 +80,7 @@ export default function DropdownSetting<T extends PossibleValue = string>({
           onChange={handleChange}
           value={value?.toString()}
           disabled={disabled}
+          translate={translateOptions}
         >
           {options.map(option => (
             <option

+ 1 - 0
services/web/frontend/js/features/ide-redesign/components/settings/editor-settings/pdf-viewer-setting.tsx

@@ -22,6 +22,7 @@ export default function PDFViewerSetting() {
       ]}
       onChange={setPdfViewer}
       value={pdfViewer}
+      translateOptions="no"
     />
   )
 }

+ 3 - 1
services/web/frontend/js/features/ide-redesign/components/toolbar/project-title.tsx

@@ -58,7 +58,9 @@ export const ToolbarProjectTitle = () => {
         id="project-title-options"
         className="ide-redesign-toolbar-project-dropdown-toggle ide-redesign-toolbar-dropdown-toggle-subdued fw-bold ide-redesign-toolbar-button-subdued"
       >
-        <span className="ide-redesign-toolbar-project-name">{name}</span>
+        <span className="ide-redesign-toolbar-project-name" translate="no">
+          {name}
+        </span>
         <MaterialIcon
           type="keyboard_arrow_down"
           accessibilityLabel={t('project_title_options')}

+ 1 - 0
services/web/frontend/js/features/outline/components/outline-item.tsx

@@ -62,6 +62,7 @@ const OutlineItem = memo(function OutlineItem({
       role="treeitem"
       aria-current={isHighlighted}
       aria-label={outlineItem.title}
+      translate="no"
     >
       <div className="outline-item-row">
         {!!outlineItem.children && (

+ 1 - 1
services/web/frontend/js/features/pdf-preview/components/pdf-log-entry-raw-content.tsx

@@ -39,7 +39,7 @@ export default function PdfLogEntryRawContent({
           height: expanded || !needsExpander ? 'auto' : collapsedSize,
         }}
       >
-        <pre className="log-entry-content-raw" ref={elementRef}>
+        <pre className="log-entry-content-raw" ref={elementRef} translate="no">
           {rawContent.trim()}
         </pre>
       </div>

+ 6 - 2
services/web/frontend/js/features/preview/components/preview-log-entry-header.tsx

@@ -86,7 +86,11 @@ function PreviewLogEntryHeader({
       onClick={onSourceLocationClick}
     >
       <MaterialIcon type="link" />
-      <span ref={logLocationSpanRef} className="log-entry-header-link-location">
+      <span
+        ref={logLocationSpanRef}
+        className="log-entry-header-link-location"
+        translate="no"
+      >
         {`\u202A${locationLinkText}\u202C`}
       </span>
     </OLButton>
@@ -105,7 +109,7 @@ function PreviewLogEntryHeader({
           id={locationLinkText}
           description={locationLinkText}
           overlayProps={{ placement: 'left' }}
-          tooltipProps={{ className: 'log-location-tooltip' }}
+          tooltipProps={{ className: 'log-location-tooltip', translate: 'no' }}
         >
           {locationLink}
         </OLTooltip>

+ 1 - 1
services/web/frontend/js/features/review-panel-new/components/review-panel-entry-user.tsx

@@ -12,7 +12,7 @@ const ReviewPanelEntryUser = ({
   const userName = buildName(user)
 
   return (
-    <div className="review-panel-entry-user">
+    <div className="review-panel-entry-user" translate="no">
       <span
         className="review-panel-entry-user-color-badge"
         style={{

+ 3 - 0
services/web/frontend/js/features/review-panel-new/components/review-panel-expandable-content.tsx

@@ -11,6 +11,7 @@ export const ExpandableContent = memo<{
   newLineCharsLimit?: number
   checkNewLines?: boolean
   inline?: boolean
+  translate?: 'yes' | 'no'
 }>(function ExpandableContent({
   content,
   className,
@@ -18,6 +19,7 @@ export const ExpandableContent = memo<{
   newLineCharsLimit = 3,
   checkNewLines = true,
   inline = false,
+  translate,
 }) {
   const { t } = useTranslation()
   const contentRef = useRef<HTMLDivElement>(null)
@@ -50,6 +52,7 @@ export const ExpandableContent = memo<{
       <div
         ref={contentRef}
         className={classNames('review-panel-expandable-content', className)}
+        translate={translate}
       >
         {isExpanded ? content : content.slice(0, limit)}
         {isOverflowing && !isExpanded && '...'}

+ 1 - 0
services/web/frontend/js/features/review-panel-new/components/review-panel-message.tsx

@@ -135,6 +135,7 @@ export const ReviewPanelMessage: FC<{
           contentLimit={100}
           checkNewLines
           content={message.content}
+          translate="no"
         />
       )}
 

+ 5 - 1
services/web/frontend/js/features/review-panel-new/components/review-panel-resolved-thread.tsx

@@ -73,7 +73,10 @@ export const ReviewPanelResolvedThread: FC<{
             i18nKey="from_filename"
             components={[
               // eslint-disable-next-line react/jsx-key
-              <span className="review-panel-resolved-comment-filename" />,
+              <span
+                className="review-panel-resolved-comment-filename"
+                translate="no"
+              />,
             ]}
             values={{ filename: docName }}
             shouldUnescape
@@ -121,6 +124,7 @@ export const ReviewPanelResolvedThread: FC<{
           className="review-panel-resolved-comment-quoted-text-quote"
           content={comment?.op.c}
           checkNewLines
+          translate="no"
         />
       </div>
 

+ 1 - 1
services/web/frontend/js/features/source-editor/extensions/toolbar/toolbar-panel.ts

@@ -238,7 +238,7 @@ const toolbarTheme = EditorView.theme({
       color: 'inherit',
     },
     '& .ol-cm-toolbar-menu': {
-      width: '120px',
+      minWidth: '120px',
       display: 'flex',
       flexDirection: 'column',
       boxSizing: 'border-box',

+ 1 - 0
services/web/frontend/js/shared/components/collapsible-file-header.tsx

@@ -11,6 +11,7 @@ export const CollapsibleFileHeader: FC<{
     type="button"
     className="collapsible-file-header"
     onClick={toggleCollapsed}
+    translate="no"
   >
     <MaterialIcon
       type={collapsed ? 'keyboard_arrow_right' : 'keyboard_arrow_down'}

+ 5 - 3
services/web/test/acceptance/src/ProjectInviteTests.mjs

@@ -200,7 +200,7 @@ const expectInvitePage = (user, link, callback) => {
   tryFollowInviteLink(user, link, (err, response, body) => {
     expect(err).not.to.exist
     expect(response.statusCode).to.equal(200)
-    expect(body).to.match(/<title>Project Invite - .*<\/title>/)
+    expect(body).to.match(/<title[^>]*>Project Invite - .*<\/title>/)
     callback()
   })
 }
@@ -210,7 +210,7 @@ const expectInvalidInvitePage = (user, link, callback) => {
   tryFollowInviteLink(user, link, (err, response, body) => {
     expect(err).not.to.exist
     expect(response.statusCode).to.equal(404)
-    expect(body).to.match(/<title>Invalid Invite - .*<\/title>/)
+    expect(body).to.match(/<title[^>]*>Invalid Invite - .*<\/title>/)
     callback()
   })
 }
@@ -237,7 +237,9 @@ const expectLoginPage = (user, callback) => {
   tryFollowLoginLink(user, '/login', (err, response, body) => {
     expect(err).not.to.exist
     expect(response.statusCode).to.equal(200)
-    expect(body).to.match(/<title>(Login|Log in to Overleaf) - .*<\/title>/)
+    expect(body).to.match(
+      /<title[^>]*>(Login|Log in to Overleaf) - .*<\/title>/
+    )
     callback()
   })
 }

+ 1 - 1
services/web/test/acceptance/src/helpers/expectErrorResponse.mjs

@@ -12,7 +12,7 @@ export default {
   restricted: {
     html(response, body) {
       expect(response.statusCode).to.equal(403)
-      expect(body).to.match(/<head><title>Restricted/)
+      expect(body).to.match(/<head><title translate="no">Restricted/)
     },
     json(response, body) {
       expect(response.statusCode).to.equal(403)

+ 2 - 1
services/web/test/smoke/src/steps/100_loadProjectDashboard.js

@@ -1,4 +1,5 @@
-const TITLE_REGEX = /<title>Your projects - .*, Online LaTeX Editor<\/title>/
+const TITLE_REGEX =
+  /<title[^>]*>Your projects - .*, Online LaTeX Editor<\/title>/
 
 async function run({ request, assertHasStatusCode }) {
   const response = await request('/project')