From c5acf004832210fc7fa9f59a3af2af9a00453f95 Mon Sep 17 00:00:00 2001 From: "Dedy F. Setyawan" Date: Fri, 23 Jan 2026 15:42:51 +0700 Subject: [PATCH] feat(web): localize reaction tooltip --- .../MemoReactionListView/ReactionView.tsx | 4 +++- web/src/components/MemoReactionListView/hooks.ts | 15 ++++++++++++--- web/src/locales/en.json | 5 +++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/web/src/components/MemoReactionListView/ReactionView.tsx b/web/src/components/MemoReactionListView/ReactionView.tsx index a8803f0be..5297a21c0 100644 --- a/web/src/components/MemoReactionListView/ReactionView.tsx +++ b/web/src/components/MemoReactionListView/ReactionView.tsx @@ -4,6 +4,7 @@ import { cn } from "@/lib/utils"; import { State } from "@/types/proto/api/v1/common_pb"; import type { Memo } from "@/types/proto/api/v1/memo_service_pb"; import type { User } from "@/types/proto/api/v1/user_service_pb"; +import { useTranslate } from "@/utils/i18n"; import { formatReactionTooltip, useReactionActions } from "./hooks"; interface Props { @@ -14,6 +15,7 @@ interface Props { const ReactionView = (props: Props) => { const { memo, reactionType, users } = props; + const t = useTranslate(); const currentUser = useCurrentUser(); const hasReaction = users.some((user) => currentUser && user.username === currentUser.username); const readonly = memo.state === State.ARCHIVED; @@ -48,7 +50,7 @@ const ReactionView = (props: Props) => { -

{formatReactionTooltip(users, reactionType)}

+

{formatReactionTooltip(users, reactionType, t)}

diff --git a/web/src/components/MemoReactionListView/hooks.ts b/web/src/components/MemoReactionListView/hooks.ts index 6e83b8b33..47b5592b6 100644 --- a/web/src/components/MemoReactionListView/hooks.ts +++ b/web/src/components/MemoReactionListView/hooks.ts @@ -6,8 +6,10 @@ import { memoKeys } from "@/hooks/useMemoQueries"; import { useUsersByNames } from "@/hooks/useUserQueries"; import type { Memo, Reaction } from "@/types/proto/api/v1/memo_service_pb"; import type { User } from "@/types/proto/api/v1/user_service_pb"; +import { useTranslate } from "@/utils/i18n"; export type ReactionGroup = Map; +export type TranslateFunction = ReturnType; export const useReactionGroups = (reactions: Reaction[]): ReactionGroup => { const creatorNames = useMemo(() => reactions.map((r) => r.creator), [reactions]); @@ -70,11 +72,18 @@ export const useReactionActions = ({ memo, onComplete }: UseReactionActionsOptio return { hasReacted, handleReactionClick }; }; -export const formatReactionTooltip = (users: User[], reactionType: string): string => { +export const formatReactionTooltip = (users: User[], reactionType: string, t: TranslateFunction): string => { if (users.length === 0) return ""; const formatUserName = (user: User) => user.displayName || user.username; + const separator = t("common.list-separator"); if (users.length < 5) { - return `${users.map(formatUserName).join(", ")} reacted with ${reactionType.toLowerCase()}`; + const userList = users.map(formatUserName).join(separator); + return t("reaction.reacted-with", { userList: userList, reactionType: reactionType.toLowerCase() }); } - return `${users.slice(0, 4).map(formatUserName).join(", ")} and ${users.length - 4} more reacted with ${reactionType.toLowerCase()}`; + const userList = users.slice(0, 4).map(formatUserName).join(separator); + return t("reaction.more-reacted-with", { + userList: userList, + count: users.length - 4, + reactionType: reactionType.toLowerCase(), + }); }; diff --git a/web/src/locales/en.json b/web/src/locales/en.json index d4598eea1..28e727b69 100644 --- a/web/src/locales/en.json +++ b/web/src/locales/en.json @@ -53,6 +53,7 @@ "inbox": "Inbox", "input": "Input", "language": "Language", + "list-separator": ", ", "last-updated-at": "Last updated at", "layout": "Layout", "learn-more": "Learn more", @@ -212,6 +213,10 @@ "no-memos-found": "No memos found", "search-placeholder": "Search content" }, + "reaction": { + "reacted-with": "{{userList}} reacted with {{reactionType}}", + "more-reacted-with": "{{userList}} and {{count}} more reacted with {{reactionType}}" + }, "resource": { "clear": "Clear", "copy-link": "Copy Link",