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

Merge pull request #8694 from weseek/support/143958-comment-localize

support: Localize comment components
Yuki Takei 2 лет назад
Родитель
Сommit
048450b2e5

+ 8 - 2
apps/app/public/static/locales/en_US/translation.json

@@ -330,8 +330,13 @@
   "page_comment": {
   "page_comment": {
     "comments": "Commments",
     "comments": "Commments",
     "comment": "Commment",
     "comment": "Commment",
+    "preview": "Preview",
+    "write": "Write",
+    "add_a_comment": "Add a comment",
     "display_the_page_when_posting_this_comment": "Display the page when posting this comment",
     "display_the_page_when_posting_this_comment": "Display the page when posting this comment",
-    "no_user_found": "No user found"
+    "no_user_found": "No user found",
+    "reply": "Reply",
+    "delete_comment": "Delete comment?"
   },
   },
   "page_api_error": {
   "page_api_error": {
     "notfound_or_forbidden": "Original page is not found or forbidden.",
     "notfound_or_forbidden": "Original page is not found or forbidden.",
@@ -531,7 +536,8 @@
   },
   },
   "slack_notification": {
   "slack_notification": {
     "popover_title": "Slack Notification",
     "popover_title": "Slack Notification",
-    "popover_desc": "Input channel name. You can notify multiple channels by entering a comma-separated list."
+    "popover_desc": "Input channel name. You can notify multiple channels by entering a comma-separated list.",
+    "input_channels": "Input channels"
   },
   },
   "search_result": {
   "search_result": {
     "title": "Search",
     "title": "Search",

+ 8 - 2
apps/app/public/static/locales/ja_JP/translation.json

@@ -363,8 +363,13 @@
   "page_comment": {
   "page_comment": {
     "comments": "コメント",
     "comments": "コメント",
     "comment": "コメント",
     "comment": "コメント",
+    "preview": "プレビュー",
+    "write": "入力",
+    "add_a_comment": "コメントを追加",
     "display_the_page_when_posting_this_comment": "投稿時のページを表示する",
     "display_the_page_when_posting_this_comment": "投稿時のページを表示する",
-    "no_user_found": "ユーザー名が見つかりません"
+    "no_user_found": "ユーザー名が見つかりません",
+    "reply": "返信",
+    "delete_comment": "コメントを削除しますか?"
   },
   },
   "page_api_error": {
   "page_api_error": {
     "notfound_or_forbidden": "元のページが見つからないか、アクセス権がありません。",
     "notfound_or_forbidden": "元のページが見つからないか、アクセス権がありません。",
@@ -564,7 +569,8 @@
   },
   },
   "slack_notification": {
   "slack_notification": {
     "popover_title": "Slack 通知",
     "popover_title": "Slack 通知",
-    "popover_desc": "チャンネル名を入れてください。カンマ区切りのリストを入力することで複数のチャンネルに通知することができます。"
+    "popover_desc": "チャンネル名を入れてください。カンマ区切りのリストを入力することで複数のチャンネルに通知することができます。",
+    "input_channels": "チャンネル名"
   },
   },
   "search_result": {
   "search_result": {
     "title": "検索",
     "title": "検索",

+ 8 - 2
apps/app/public/static/locales/zh_CN/translation.json

@@ -320,8 +320,13 @@
   "page_comment": {
   "page_comment": {
     "comments": "评论",
     "comments": "评论",
     "comment": "评论",
     "comment": "评论",
+    "preview": "预览",
+    "write": "输入",
+    "add_a_comment": "Add a comment",
     "display_the_page_when_posting_this_comment": "Display the page when posting this comment",
     "display_the_page_when_posting_this_comment": "Display the page when posting this comment",
-    "no_user_found": "未找到用户名"
+    "no_user_found": "未找到用户名",
+    "reply": "Reply",
+    "delete_comment": "Delete comment?"
   },
   },
   "page_api_error": {
   "page_api_error": {
     "notfound_or_forbidden": "未找到或禁止原始页。",
     "notfound_or_forbidden": "未找到或禁止原始页。",
@@ -518,7 +523,8 @@
   },
   },
   "slack_notification": {
   "slack_notification": {
     "popover_title": "Slack Notification",
     "popover_title": "Slack Notification",
-    "popover_desc": "Input channel name. You can notify multiple channels by entering a comma-separated list."
+    "popover_desc": "Input channel name. You can notify multiple channels by entering a comma-separated list.",
+    "input_channels": "Input channels"
   },
   },
   "share_links": {
   "share_links": {
     "Shere this page link to public": "Shere this page link to public",
     "Shere this page link to public": "Shere this page link to public",

+ 4 - 1
apps/app/src/components/PageComment.tsx

@@ -5,6 +5,7 @@ import React, {
 
 
 import { isPopulated, getIdForRef, type IRevisionHasId } from '@growi/core';
 import { isPopulated, getIdForRef, type IRevisionHasId } from '@growi/core';
 import { UserPicture } from '@growi/ui/dist/components';
 import { UserPicture } from '@growi/ui/dist/components';
+import { useTranslation } from 'next-i18next';
 
 
 import { apiPost } from '~/client/util/apiv1-client';
 import { apiPost } from '~/client/util/apiv1-client';
 import { toastError } from '~/client/util/toastr';
 import { toastError } from '~/client/util/toastr';
@@ -50,6 +51,8 @@ export const PageComment: FC<PageCommentProps> = memo((props: PageCommentProps):
   const [errorMessageOnDelete, setErrorMessageOnDelete] = useState<string>('');
   const [errorMessageOnDelete, setErrorMessageOnDelete] = useState<string>('');
   const { trigger: mutatePageInfo } = useSWRMUTxPageInfo(pageId);
   const { trigger: mutatePageInfo } = useSWRMUTxPageInfo(pageId);
 
 
+  const { t } = useTranslation('');
+
   const commentsFromOldest = useMemo(() => (comments != null ? [...comments].reverse() : null), [comments]);
   const commentsFromOldest = useMemo(() => (comments != null ? [...comments].reverse() : null), [comments]);
   const commentsExceptReply: ICommentHasIdList | undefined = useMemo(
   const commentsExceptReply: ICommentHasIdList | undefined = useMemo(
     () => commentsFromOldest?.filter(comment => comment.replyTo == null), [commentsFromOldest],
     () => commentsFromOldest?.filter(comment => comment.replyTo == null), [commentsFromOldest],
@@ -178,7 +181,7 @@ export const PageComment: FC<PageCommentProps> = memo((props: PageCommentProps):
                           onClick={() => onReplyButtonClickHandler(comment._id)}
                           onClick={() => onReplyButtonClickHandler(comment._id)}
                         >
                         >
                           <UserPicture user={currentUser} noLink noTooltip additionalClassName="me-2" />
                           <UserPicture user={currentUser} noLink noTooltip additionalClassName="me-2" />
-                          <span className="material-symbols-outlined me-1 fs-5 pb-1">reply</span><small>Reply...</small>
+                          <span className="material-symbols-outlined me-1 fs-5 pb-1">reply</span><small>{t('page_comment.reply')}...</small>
                         </button>
                         </button>
                       </NotAvailableForReadOnlyUser>
                       </NotAvailableForReadOnlyUser>
                     </NotAvailableForGuest>
                     </NotAvailableForGuest>

+ 2 - 2
apps/app/src/components/PageComment/CommentEditor.tsx

@@ -239,7 +239,7 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
             >
             >
               <UserPicture user={currentUser} noLink noTooltip additionalClassName="me-3" />
               <UserPicture user={currentUser} noLink noTooltip additionalClassName="me-3" />
               <span className="material-symbols-outlined me-1 fs-5">add_comment</span>
               <span className="material-symbols-outlined me-1 fs-5">add_comment</span>
-              <small>Add Comment in markdown...</small>
+              <small>{t('page_comment.add_a_comment')}...</small>
             </button>
             </button>
           </NotAvailableForReadOnlyUser>
           </NotAvailableForReadOnlyUser>
         </NotAvailableForGuest>
         </NotAvailableForGuest>
@@ -304,7 +304,7 @@ export const CommentEditor = (props: CommentEditorProps): JSX.Element => {
           <div className="d-flex justify-content-between align-items-center mb-2">
           <div className="d-flex justify-content-between align-items-center mb-2">
             <div className="d-flex">
             <div className="d-flex">
               <UserPicture user={currentUser} noLink noTooltip />
               <UserPicture user={currentUser} noLink noTooltip />
-              <p className="ms-2 mb-0">Add a comment</p>
+              <p className="ms-2 mb-0">{t('page_comment.add_a_comment')}</p>
             </div>
             </div>
             <SwitchingButtonGroup showPreview={showPreview} onSelected={handleSelect} />
             <SwitchingButtonGroup showPreview={showPreview} onSelected={handleSelect} />
           </div>
           </div>

+ 9 - 5
apps/app/src/components/PageComment/DeleteCommentModal.tsx

@@ -3,11 +3,13 @@ import React from 'react';
 import { isPopulated } from '@growi/core';
 import { isPopulated } from '@growi/core';
 import { UserPicture } from '@growi/ui/dist/components';
 import { UserPicture } from '@growi/ui/dist/components';
 import { format } from 'date-fns';
 import { format } from 'date-fns';
+import { t } from 'i18next';
+import { useTranslation } from 'next-i18next';
 import {
 import {
   Button, Modal, ModalHeader, ModalBody, ModalFooter,
   Button, Modal, ModalHeader, ModalBody, ModalFooter,
 } from 'reactstrap';
 } from 'reactstrap';
 
 
-import { ICommentHasId } from '../../interfaces/comment';
+import type { ICommentHasId } from '../../interfaces/comment';
 import { Username } from '../User/Username';
 import { Username } from '../User/Username';
 
 
 import styles from './DeleteCommentModal.module.scss';
 import styles from './DeleteCommentModal.module.scss';
@@ -26,6 +28,8 @@ export const DeleteCommentModal = (props: DeleteCommentModalProps): JSX.Element
     isShown, comment, errorMessage, cancelToDelete, confirmToDelete,
     isShown, comment, errorMessage, cancelToDelete, confirmToDelete,
   } = props;
   } = props;
 
 
+  const { t } = useTranslation();
+
   const headerContent = () => {
   const headerContent = () => {
     if (comment == null || isShown === false) {
     if (comment == null || isShown === false) {
       return <></>;
       return <></>;
@@ -33,7 +37,7 @@ export const DeleteCommentModal = (props: DeleteCommentModalProps): JSX.Element
     return (
     return (
       <span>
       <span>
         <span className="material-symbols-outlined">delete_forever</span>
         <span className="material-symbols-outlined">delete_forever</span>
-        Delete comment?
+        {t('page_comment.delete_comment')}
       </span>
       </span>
     );
     );
   };
   };
@@ -58,7 +62,7 @@ export const DeleteCommentModal = (props: DeleteCommentModalProps): JSX.Element
 
 
     return (
     return (
       <>
       <>
-        <UserPicture user={creator} size="xs" /> <strong><Username user={creator}></Username></strong> wrote on {commentDate}:
+        <UserPicture user={creator} size="xs" /> <strong className="me-2"><Username user={creator}></Username></strong>{commentDate}:
         <p className="card custom-card comment-body mt-2 p-2">{commentBodyElement}</p>
         <p className="card custom-card comment-body mt-2 p-2">{commentBodyElement}</p>
       </>
       </>
     );
     );
@@ -71,10 +75,10 @@ export const DeleteCommentModal = (props: DeleteCommentModalProps): JSX.Element
     return (
     return (
       <>
       <>
         <span className="text-danger">{errorMessage}</span>&nbsp;
         <span className="text-danger">{errorMessage}</span>&nbsp;
-        <Button onClick={cancelToDelete}>Cancel</Button>
+        <Button onClick={cancelToDelete}>{t('Cancel')}</Button>
         <Button color="danger" onClick={confirmToDelete}>
         <Button color="danger" onClick={confirmToDelete}>
           <span className="material-symbols-outlined">delete_forever</span>
           <span className="material-symbols-outlined">delete_forever</span>
-          Delete
+          {t('Delete')}
         </Button>
         </Button>
       </>
       </>
     );
     );

+ 1 - 1
apps/app/src/components/PageComment/SwitchingButtonGroup.module.scss

@@ -9,7 +9,7 @@
     height: 38px;
     height: 38px;
 
 
     @include bs.media-breakpoint-up(sm) {
     @include bs.media-breakpoint-up(sm) {
-      width: 90px;
+      width: auto;
       height: 30px;
       height: 30px;
     }
     }
   }
   }

+ 2 - 2
apps/app/src/components/PageComment/SwitchingButtonGroup.tsx

@@ -57,7 +57,7 @@ export const SwitchingButtonGroup = (props: Props): JSX.Element => {
         onClick={() => onSelected?.(true)}
         onClick={() => onSelected?.(true)}
       >
       >
         <span className="material-symbols-outlined me-0">play_arrow</span>
         <span className="material-symbols-outlined me-0">play_arrow</span>
-        <span className="d-none d-sm-inline">{t('Preview')}</span>
+        <span className="d-none d-sm-inline">{t('page_comment.preview')}</span>
       </SwitchingButton>
       </SwitchingButton>
       <SwitchingButton
       <SwitchingButton
         active={!showPreview}
         active={!showPreview}
@@ -65,7 +65,7 @@ export const SwitchingButtonGroup = (props: Props): JSX.Element => {
         onClick={() => onSelected?.(false)}
         onClick={() => onSelected?.(false)}
       >
       >
         <span className="material-symbols-outlined me-1">edit_square</span>
         <span className="material-symbols-outlined me-1">edit_square</span>
-        <span className="d-none d-sm-inline">{t('Write')}</span>
+        <span className="d-none d-sm-inline">{t('page_comment.write')}</span>
       </SwitchingButton>
       </SwitchingButton>
     </div>
     </div>
   );
   );

+ 1 - 1
apps/app/src/components/SlackNotification.tsx

@@ -59,7 +59,7 @@ export const SlackNotification: FC<SlackNotificationProps> = ({
         id={idForSlackPopover}
         id={idForSlackPopover}
         type="text"
         type="text"
         value={slackChannels}
         value={slackChannels}
-        placeholder="Input channels"
+        placeholder={`${t('slack_notification.input_channels')}`}
         onChange={updateSlackChannelsHandler}
         onChange={updateSlackChannelsHandler}
       />
       />
       <UncontrolledPopover trigger="focus" placement="top" target={idForSlackPopover}>
       <UncontrolledPopover trigger="focus" placement="top" target={idForSlackPopover}>