Add localization support for chat message components with enhanced Translation component (#4560)
* Initial plan * Add localization support for chat message components Co-authored-by: gabek <414923+gabek@users.noreply.github.com> * Update chat message localization to use string interpolation Co-authored-by: gabek <414923+gabek@users.noreply.github.com> * Restore original styling while preserving string interpolation Co-authored-by: gabek <414923+gabek@users.noreply.github.com> * Separate styling from variables in translation templates Co-authored-by: gabek <414923+gabek@users.noreply.github.com> * Revert to concatenation approach for chat message localization Co-authored-by: gabek <414923+gabek@users.noreply.github.com> * Add id property to Translation component and restore missing CSS classes and IDs Co-authored-by: gabek <414923+gabek@users.noreply.github.com> * Javascript formatting autofixes --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: gabek <414923+gabek@users.noreply.github.com> Co-authored-by: Gabe Kangas <gabek@real-ity.com> Co-authored-by: Owncast <owncast@owncast.online>
This commit is contained in:
co-authored by
gabek
copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Gabe Kangas
Owncast
parent
fa1b07e987
commit
275339bdf0
@@ -1,6 +1,8 @@
|
||||
import { FC } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { ModerationBadge } from '../ChatUserBadge/ModerationBadge';
|
||||
import { Translation } from '../../ui/Translation/Translation';
|
||||
import { Localization } from '../../../types/localization';
|
||||
|
||||
import styles from './ChatJoinMessage.module.scss';
|
||||
|
||||
@@ -29,13 +31,19 @@ export const ChatJoinMessage: FC<ChatJoinMessageProps> = ({
|
||||
<span className={styles.icon}>
|
||||
<UsergroupAddOutlined />
|
||||
</span>
|
||||
<span className={styles.user}>{displayName}</span>
|
||||
{isAuthorModerator && (
|
||||
<span className={styles.moderatorBadge}>
|
||||
<ModerationBadge userColor={userColor} />
|
||||
</span>
|
||||
)}
|
||||
<span className={styles.joinMessage}>joined the chat.</span>
|
||||
<span className={styles.joinMessage}>
|
||||
<span className={styles.user}>{displayName}</span>
|
||||
<span> </span>
|
||||
<Translation
|
||||
translationKey={Localization.Frontend.Chat.userJoined}
|
||||
defaultText="joined the chat."
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { Translation } from '../../ui/Translation/Translation';
|
||||
import { Localization } from '../../../types/localization';
|
||||
import styles from './ChatModeratorNotification.module.scss';
|
||||
import Icon from '../../../assets/images/moderator.svg';
|
||||
|
||||
export const ChatModeratorNotification = () => (
|
||||
<div className={styles.chatModerationNotification}>
|
||||
<Icon className={styles.icon} />
|
||||
You are now a moderator.
|
||||
<Translation
|
||||
translationKey={Localization.Frontend.Chat.moderatorNotification}
|
||||
defaultText="You are now a moderator."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// export const ChatSocialMessage: FC<ChatSocialMessageProps> = ({ message }) => {
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import { FC } from 'react';
|
||||
import { NameChangeEvent } from '../../../interfaces/socket-events';
|
||||
import { Translation } from '../../ui/Translation/Translation';
|
||||
import { Localization } from '../../../types/localization';
|
||||
import styles from './ChatNameChangeMessage.module.scss';
|
||||
|
||||
export interface ChatNameChangeMessageProps {
|
||||
@@ -27,10 +27,14 @@ export const ChatNameChangeMessage: FC<ChatNameChangeMessageProps> = ({ message
|
||||
</div>
|
||||
<div className={styles.nameChangeText}>
|
||||
<span style={{ color }}>{oldName}</span>
|
||||
<span className={styles.plain} id="owncast-name-change-is-now-known-text">
|
||||
{' '}
|
||||
is now known as{' '}
|
||||
</span>
|
||||
<span> </span>
|
||||
<Translation
|
||||
translationKey={Localization.Frontend.Chat.nameChangeText}
|
||||
className={styles.plain}
|
||||
id="owncast-name-change-is-now-known-text"
|
||||
defaultText="is now known as"
|
||||
/>
|
||||
<span> </span>
|
||||
<span style={{ color }}>{displayName}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { FC } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { ModerationBadge } from '../ChatUserBadge/ModerationBadge';
|
||||
import { Translation } from '../../ui/Translation/Translation';
|
||||
import { Localization } from '../../../types/localization';
|
||||
|
||||
import styles from './ChatPartMessage.module.scss';
|
||||
|
||||
@@ -29,13 +31,19 @@ export const ChatPartMessage: FC<ChatPartMessageProps> = ({
|
||||
<span className={styles.icon}>
|
||||
<UsergroupDeleteOutlined />
|
||||
</span>
|
||||
<span className={styles.user}>{displayName}</span>
|
||||
{isAuthorModerator && (
|
||||
<span className={styles.moderatorBadge}>
|
||||
<ModerationBadge userColor={userColor} />
|
||||
</span>
|
||||
)}
|
||||
<span className={styles.partMessage}>left the chat.</span>
|
||||
<span className={styles.partMessage}>
|
||||
<span className={styles.user}>{displayName}</span>
|
||||
<span> </span>
|
||||
<Translation
|
||||
translationKey={Localization.Frontend.Chat.userLeft}
|
||||
defaultText="left the chat."
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface TranslationProps {
|
||||
translationKey: LocalizationKey;
|
||||
vars?: Record<string, any>;
|
||||
className?: string;
|
||||
id?: string;
|
||||
defaultText?: string;
|
||||
count?: number;
|
||||
}
|
||||
@@ -15,6 +16,7 @@ export const Translation: FC<TranslationProps> = ({
|
||||
translationKey,
|
||||
vars,
|
||||
className,
|
||||
id,
|
||||
defaultText,
|
||||
count,
|
||||
}) => {
|
||||
@@ -55,7 +57,9 @@ export const Translation: FC<TranslationProps> = ({
|
||||
}
|
||||
}
|
||||
|
||||
return <span className={className} dangerouslySetInnerHTML={{ __html: translatedText }} />;
|
||||
return (
|
||||
<span className={className} id={id} dangerouslySetInnerHTML={{ __html: translatedText }} />
|
||||
);
|
||||
};
|
||||
|
||||
export default Translation;
|
||||
|
||||
@@ -118,6 +118,12 @@
|
||||
"contribute": "Contribute",
|
||||
"source": "Source"
|
||||
},
|
||||
"Chat": {
|
||||
"userJoined": "joined the chat.",
|
||||
"userLeft": "left the chat.",
|
||||
"nameChangeText": "is now known as",
|
||||
"moderatorNotification": "You are now a moderator."
|
||||
,
|
||||
"FollowModal": {
|
||||
"description": "By following this stream you'll get notified on the Fediverse when it goes live. Now is a great time to",
|
||||
"learnFediverse": "learn about the Fediverse",
|
||||
|
||||
@@ -100,6 +100,14 @@ export const Localization = {
|
||||
source: 'Frontend.Footer.source',
|
||||
},
|
||||
|
||||
// Chat message components
|
||||
Chat: {
|
||||
userJoined: 'Frontend.Chat.userJoined',
|
||||
userLeft: 'Frontend.Chat.userLeft',
|
||||
nameChangeText: 'Frontend.Chat.nameChangeText',
|
||||
moderatorNotification: 'Frontend.Chat.moderatorNotification',
|
||||
},
|
||||
|
||||
// Follow modal component
|
||||
FollowModal: {
|
||||
description: 'Frontend.FollowModal.description',
|
||||
|
||||
Reference in New Issue
Block a user