mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-07-21 23:38:30 +00:00
feat: translations support
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { translateString } from '../utils/helpers/';
|
||||
|
||||
interface MediaListHeaderProps {
|
||||
title?: string;
|
||||
@ -9,7 +10,7 @@ interface MediaListHeaderProps {
|
||||
}
|
||||
|
||||
export const MediaListHeader: React.FC<MediaListHeaderProps> = (props) => {
|
||||
const viewAllText = props.viewAllText || 'VIEW ALL';
|
||||
const viewAllText = props.viewAllText || translateString('VIEW ALL');
|
||||
return (
|
||||
<div className={(props.className ? props.className + ' ' : '') + 'media-list-header'} style={props.style}>
|
||||
<h2>{props.title}</h2>
|
||||
|
@ -7,20 +7,22 @@ import { PageStore, MediaPageStore } from '../../utils/stores/';
|
||||
import { PageActions, MediaPageActions } from '../../utils/actions/';
|
||||
import { LinksContext, MemberContext, SiteContext } from '../../utils/contexts/';
|
||||
import { PopupMain, UserThumbnail } from '../_shared';
|
||||
import { replaceString } from '../../utils/helpers/';
|
||||
|
||||
import './videojs-markers.js';
|
||||
import './videojs.markers.css';
|
||||
import {enableMarkers, addMarker} from './videojs-markers_config.js'
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
import './Comments.scss';
|
||||
|
||||
const commentsText = {
|
||||
single: 'comment',
|
||||
uppercaseSingle: 'COMMENT',
|
||||
ucfirstSingle: 'Comment',
|
||||
ucfirstPlural: 'Comments',
|
||||
submitCommentText: 'SUBMIT',
|
||||
disabledCommentsMsg: 'Comments are disabled',
|
||||
single: translateString('comment'),
|
||||
uppercaseSingle: translateString('COMMENT'),
|
||||
ucfirstSingle: translateString('Comment'),
|
||||
ucfirstPlural: translateString('Comments'),
|
||||
submitCommentText: translateString('SUBMIT'),
|
||||
disabledCommentsMsg: translateString('Comments are disabled'),
|
||||
};
|
||||
|
||||
function CommentForm(props) {
|
||||
@ -149,7 +151,7 @@ function CommentForm(props) {
|
||||
inputRef={textareaRef}
|
||||
className="form-textarea"
|
||||
rows="1"
|
||||
placeholder={'Add a ' + commentsText.single + '...'}
|
||||
placeholder={translateString('Add a ') + commentsText.single + '...'}
|
||||
value={value}
|
||||
onChange={onChangeWithMention}
|
||||
onFocus={onFocus}
|
||||
@ -164,7 +166,7 @@ function CommentForm(props) {
|
||||
ref={textareaRef}
|
||||
className="form-textarea"
|
||||
rows="1"
|
||||
placeholder={'Add a ' + commentsText.single + '...'}
|
||||
placeholder={translateString('Add a ') + commentsText.single + '...'}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onFocus={onFocus}
|
||||
@ -189,9 +191,9 @@ function CommentForm(props) {
|
||||
href={loginUrl}
|
||||
rel="noffolow"
|
||||
className="form-textarea-wrap"
|
||||
title={'Add a ' + commentsText.single + '...'}
|
||||
title={translateString('Add a ') + commentsText.single + '...'}
|
||||
>
|
||||
<span className="form-textarea">{'Add a ' + commentsText.single + '...'}</span>
|
||||
<span className="form-textarea">{translateString('Add a ') + commentsText.single + '...'}</span>
|
||||
</a>
|
||||
<div className="form-buttons">
|
||||
<a href={loginUrl} rel="noffolow" className="disabled">
|
||||
@ -237,7 +239,7 @@ function CommentActions(props) {
|
||||
{MemberContext._currentValue.can.deleteComment ? (
|
||||
<div className="comment-action remove-comment">
|
||||
<PopupTrigger contentRef={popupContentRef}>
|
||||
<button>DELETE {commentsText.uppercaseSingle}</button>
|
||||
<button>{translateString('DELETE')} {commentsText.uppercaseSingle}</button>
|
||||
</PopupTrigger>
|
||||
|
||||
<PopupContent contentRef={popupContentRef}>
|
||||
@ -310,7 +312,7 @@ function Comment(props) {
|
||||
{props.author_name}
|
||||
</a>
|
||||
</div>
|
||||
<div className="comment-date">{format(new Date(props.publish_date))}</div>
|
||||
<div className="comment-date">{replaceString(format(new Date(props.publish_date)))}</div>
|
||||
</div>
|
||||
<div ref={commentTextRef} className={'comment-text' + (viewMoreContent ? ' show-all' : '')}>
|
||||
<div
|
||||
@ -411,7 +413,7 @@ const CommentsListHeader = ({ commentsLength }) => {
|
||||
? commentsLength + ' ' + commentsText.ucfirstPlural
|
||||
: commentsLength + ' ' + commentsText.ucfirstSingle
|
||||
: MediaPageStore.get('media-data').enable_comments
|
||||
? 'No ' + commentsText.single + ' yet'
|
||||
? translateString('No') + commentsText.single + translateString('yet')
|
||||
: ''}
|
||||
</h2>
|
||||
) : null}
|
||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { format } from 'timeago.js';
|
||||
import { formatViewsNumber, imageExtension } from '../../../../utils/helpers/';
|
||||
import { VideoPlayerByPageLink } from '../../../video-player/VideoPlayerByPageLink';
|
||||
import { translateString } from '../../../../utils/helpers/';
|
||||
|
||||
export function ItemDescription(props) {
|
||||
return '' === props.description ? null : (
|
||||
@ -73,8 +74,8 @@ export function MediaItemEditLink(props) {
|
||||
}
|
||||
|
||||
return !link ? null : (
|
||||
<a href={link} title="Edit media" className="item-edit-link">
|
||||
EDIT MEDIA
|
||||
<a href={link} title={translateString("Edit media")} className="item-edit-link">
|
||||
{translateString("EDIT MEDIA")}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
@ -135,7 +136,7 @@ export function MediaItemAuthorLink(props) {
|
||||
|
||||
export function MediaItemMetaViews(props) {
|
||||
return (
|
||||
<span className="item-views">{formatViewsNumber(props.views) + ' ' + (1 >= props.views ? 'view' : 'views')}</span>
|
||||
<span className="item-views">{formatViewsNumber(props.views) + ' ' + (1 >= props.views ? translateString('view') : translateString('views'))}</span>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import { PendingItemsList } from '../../item-list/PendingItemsList.jsx';
|
||||
import { renderManageItems } from './includes/functions';
|
||||
import initManageItemsList from './includes/initManageItemsList';
|
||||
import { ManageItemsListHandler } from './includes/ManageItemsListHandler';
|
||||
import { translateString } from '../../../utils/helpers/';
|
||||
|
||||
import './ManageItemList.scss';
|
||||
|
||||
@ -102,7 +103,7 @@ function useManageItemListSync(props) {
|
||||
|
||||
return 1 > listHandler.totalPages() || listHandler.loadedAllItems() ? null : (
|
||||
<button className="load-more" onClick={onClickLoadMore}>
|
||||
SHOW MORE
|
||||
{translateString("SHOW MORE")}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import React, { useState } from 'react';
|
||||
import { usePopup } from '../../utils/hooks/';
|
||||
import { CircleIconButton, MaterialIcon, NavigationContentApp, PopupMain } from '../_shared/';
|
||||
import { PlaylistsSelection } from '../playlists-selection/PlaylistsSelection';
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
function mediaSavePopupPages(onTriggerPopupClose) {
|
||||
return {
|
||||
@ -39,7 +40,7 @@ export function MediaSaveButton(props) {
|
||||
<CircleIconButton type="span">
|
||||
<MaterialIcon type="playlist_add" />
|
||||
</CircleIconButton>
|
||||
<span>SAVE</span>
|
||||
<span>{translateString("SAVE")}</span>
|
||||
</button>
|
||||
</PopupTrigger>
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { usePopup } from '../../utils/hooks/';
|
||||
import { CircleIconButton, MaterialIcon, NavigationContentApp, PopupMain } from '../_shared/';
|
||||
import { MediaShareEmbed } from './MediaShareEmbed';
|
||||
import { MediaShareOptions } from './MediaShareOptions';
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
function mediaSharePopupPages() {
|
||||
return {
|
||||
@ -54,7 +55,7 @@ export function MediaShareButton(props) {
|
||||
<CircleIconButton type="span">
|
||||
<MaterialIcon type="share" />
|
||||
</CircleIconButton>
|
||||
<span>SHARE</span>
|
||||
<span>{translateString("SHARE")}</span>
|
||||
</button>
|
||||
</PopupTrigger>
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { SiteContext } from '../../utils/contexts/';
|
||||
import { MediaPageStore } from '../../utils/stores/';
|
||||
import { formatInnerLink } from '../../utils/helpers/';
|
||||
import { CircleIconButton, MaterialIcon, NavigationContentApp, NavigationMenuList, PopupMain } from '../_shared/';
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
function downloadOptionsList() {
|
||||
const media_data = MediaPageStore.get('media-data');
|
||||
@ -71,7 +72,7 @@ export function VideoMediaDownloadLink(props) {
|
||||
<CircleIconButton type="span">
|
||||
<MaterialIcon type="arrow_downward" />
|
||||
</CircleIconButton>
|
||||
<span>DOWNLOAD</span>
|
||||
<span>{translateString("DOWNLOAD")}</span>
|
||||
</button>
|
||||
</PopupTrigger>
|
||||
|
||||
|
@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
|
||||
import { PageActions } from '../../utils/actions/';
|
||||
import { PageStore, MediaPageStore } from '../../utils/stores/';
|
||||
import { ItemList } from '../item-list/ItemList';
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
function autoPlayMedia() {
|
||||
const dt = MediaPageStore.get('media-data');
|
||||
@ -38,10 +39,10 @@ export function AutoPlay(props) {
|
||||
return !media ? null : (
|
||||
<div className="auto-play">
|
||||
<div className="auto-play-header">
|
||||
<div className="next-label">Up next</div>
|
||||
<div className="next-label">{translateString("Up next")}</div>
|
||||
<div className="auto-play-option">
|
||||
<label className="checkbox-label right-selectbox" tabIndex={0} onKeyPress={onKeyPress}>
|
||||
AUTOPLAY
|
||||
{translateString("AUTOPLAY")}
|
||||
<span className="checkbox-switcher-wrap">
|
||||
<span className="checkbox-switcher">
|
||||
<input
|
||||
|
@ -6,6 +6,8 @@ import { PageActions, MediaPageActions } from '../../utils/actions/';
|
||||
import { formatInnerLink, publishedOnDate } from '../../utils/helpers/';
|
||||
import { PopupMain } from '../_shared/';
|
||||
import CommentsList from '../comments/Comments';
|
||||
import { replaceString } from '../../utils/helpers/';
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
function metafield(arr) {
|
||||
let i;
|
||||
@ -48,7 +50,7 @@ function MediaAuthorBanner(props) {
|
||||
</a>
|
||||
</span>
|
||||
{PageStore.get('config-media-item').displayPublishDate && props.published ? (
|
||||
<span className="author-banner-date">Published on {publishedOnDate(new Date(props.published))}</span>
|
||||
<span className="author-banner-date">{translateString("Published on")} {replaceString(publishedOnDate(new Date(props.published)))}</span>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
@ -76,8 +78,8 @@ function EditMediaButton(props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<a href={link} rel="nofollow" title="Edit media" className="edit-media">
|
||||
EDIT MEDIA
|
||||
<a href={link} rel="nofollow" title={translateString("Edit media")} className="edit-media">
|
||||
{translateString("EDIT MEDIA")}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
@ -90,8 +92,8 @@ function EditSubtitleButton(props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<a href={link} rel="nofollow" title="Edit subtitle" className="edit-subtitle">
|
||||
EDIT SUBTITLE
|
||||
<a href={link} rel="nofollow" title={translateString("Edit subtitle")} className="edit-subtitle">
|
||||
{translateString("EDIT SUBTITLE")}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
@ -195,12 +197,12 @@ export default function ViewerInfoContent(props) {
|
||||
</button>
|
||||
) : null}
|
||||
{tagsContent.length ? (
|
||||
<MediaMetaField value={tagsContent} title={1 < tagsContent.length ? 'Tags' : 'Tag'} id="tags" />
|
||||
<MediaMetaField value={tagsContent} title={1 < tagsContent.length ? translateString('Tags') : translateString('Tag')} id="tags" />
|
||||
) : null}
|
||||
{categoriesContent.length ? (
|
||||
<MediaMetaField
|
||||
value={categoriesContent}
|
||||
title={1 < categoriesContent.length ? 'Categories' : 'Category'}
|
||||
title={1 < categoriesContent.length ? translateString('Categories') : translateString('Category')}
|
||||
id="categories"
|
||||
/>
|
||||
) : null}
|
||||
@ -215,7 +217,7 @@ export default function ViewerInfoContent(props) {
|
||||
) : null}
|
||||
|
||||
<PopupTrigger contentRef={popupContentRef}>
|
||||
<button className="remove-media">DELETE MEDIA</button>
|
||||
<button className="remove-media">{translateString("DELETE MEDIA")}</button>
|
||||
</PopupTrigger>
|
||||
|
||||
<PopupContent contentRef={popupContentRef}>
|
||||
|
@ -4,6 +4,7 @@ import { PageStore, MediaPageStore } from '../../utils/stores/';
|
||||
import { MemberContext, PlaylistsContext } from '../../utils/contexts/';
|
||||
import { MediaLikeIcon, MediaDislikeIcon, OtherMediaDownloadLink, VideoMediaDownloadLink, MediaSaveButton, MediaShareButton, MediaMoreOptionsIcon } from '../media-actions/';
|
||||
import ViewerInfoTitleBanner from './ViewerInfoTitleBanner';
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
export default class ViewerInfoVideoTitleBanner extends ViewerInfoTitleBanner {
|
||||
render() {
|
||||
@ -56,7 +57,7 @@ export default class ViewerInfoVideoTitleBanner extends ViewerInfoTitleBanner {
|
||||
|
||||
{displayViews ? (
|
||||
<div className="media-views">
|
||||
{formatViewsNumber(this.props.views, true)} {1 >= this.props.views ? 'view' : 'views'}
|
||||
{formatViewsNumber(this.props.views, true)} {1 >= this.props.views ? translateString('view') : translateString('views')}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { PageStore } from '../../../utils/stores/';
|
||||
import { HeaderConsumer, MemberConsumer, LinksConsumer } from '../../../utils/contexts/';
|
||||
import { CircleIconButton, MaterialIcon, NavigationContentApp, NavigationMenuList, PopupTop, PopupMain, UserThumbnail } from '../../_shared';
|
||||
import { HeaderThemeSwitcher } from './HeaderThemeSwitcher';
|
||||
import { translateString } from '../../../utils/helpers/';
|
||||
|
||||
function headerPopupPages(user, popupNavItems, hasHeaderThemeSwitcher) {
|
||||
const pages = {
|
||||
@ -95,9 +96,9 @@ function LoginButton({ user, link, hasHeaderThemeSwitcher }) {
|
||||
className={
|
||||
'button-link sign-in' + (hasHeaderThemeSwitcher ? ' hidden-only-in-small' : ' hidden-only-in-extra-small')
|
||||
}
|
||||
title="Sign in"
|
||||
title={translateString('Sign in')}
|
||||
>
|
||||
Sign in
|
||||
{translateString('Sign in')}
|
||||
</a>
|
||||
</div>
|
||||
) : null;
|
||||
@ -112,9 +113,9 @@ function RegisterButton({ user, link, hasHeaderThemeSwitcher }) {
|
||||
'button-link register-link' +
|
||||
(hasHeaderThemeSwitcher ? ' hidden-only-in-small' : ' hidden-only-in-extra-small')
|
||||
}
|
||||
title="Register"
|
||||
title={translateString('Register')}
|
||||
>
|
||||
Register
|
||||
{translateString('Register')}
|
||||
</a>
|
||||
</div>
|
||||
) : null;
|
||||
|
@ -4,6 +4,7 @@ import { LinksContext } from '../../../utils/contexts/';
|
||||
import { PageStore, SearchFieldStore } from '../../../utils/stores/';
|
||||
import { SearchFieldActions } from '../../../utils/actions/';
|
||||
import { MaterialIcon, PopupMain } from '../../_shared';
|
||||
import { translateString } from '../../../utils/helpers/';
|
||||
|
||||
import './SearchField.scss';
|
||||
|
||||
@ -296,7 +297,7 @@ export function SearchField(props) {
|
||||
<input
|
||||
ref={searchInputRef}
|
||||
type="text"
|
||||
placeholder="Search"
|
||||
placeholder={translateString("Search")}
|
||||
aria-label="Search"
|
||||
name="q"
|
||||
value={queryVal}
|
||||
|
@ -4,6 +4,7 @@ import { useUser } from '../../../utils/hooks/';
|
||||
import { PageStore } from '../../../utils/stores/';
|
||||
import { LinksContext, SidebarContext } from '../../../utils/contexts/';
|
||||
import { NavigationMenuList } from '../../_shared';
|
||||
import { translateString } from '../../../utils/helpers/';
|
||||
|
||||
export function SidebarNavigationMenu() {
|
||||
const { userCan, isAnonymous, pages: userPages } = useUser();
|
||||
@ -40,7 +41,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.home,
|
||||
icon: 'home',
|
||||
text: 'Home',
|
||||
text: translateString('Home'),
|
||||
className: 'nav-item-home',
|
||||
});
|
||||
}
|
||||
@ -49,7 +50,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.featured,
|
||||
icon: 'star',
|
||||
text: PageStore.get('config-enabled').pages.featured.title,
|
||||
text: translateString('Featured'),
|
||||
className: 'nav-item-featured',
|
||||
});
|
||||
}
|
||||
@ -61,7 +62,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.recommended,
|
||||
icon: 'done_outline',
|
||||
text: PageStore.get('config-enabled').pages.recommended.title,
|
||||
text: translateString("Recommended"),
|
||||
className: 'nav-item-recommended',
|
||||
});
|
||||
}
|
||||
@ -70,7 +71,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.latest,
|
||||
icon: 'new_releases',
|
||||
text: PageStore.get('config-enabled').pages.latest.title,
|
||||
text: translateString("Latest"),
|
||||
className: 'nav-item-latest',
|
||||
});
|
||||
}
|
||||
@ -83,7 +84,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.archive.tags,
|
||||
icon: 'local_offer',
|
||||
text: PageStore.get('config-enabled').taxonomies.tags.title,
|
||||
text: translateString("Tags"),
|
||||
className: 'nav-item-tags',
|
||||
});
|
||||
}
|
||||
@ -96,7 +97,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.archive.categories,
|
||||
icon: 'list_alt',
|
||||
text: PageStore.get('config-enabled').taxonomies.categories.title,
|
||||
text: translateString("Categories"),
|
||||
className: 'nav-item-categories',
|
||||
});
|
||||
}
|
||||
@ -105,7 +106,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.members,
|
||||
icon: 'people',
|
||||
text: PageStore.get('config-enabled').pages.members.title,
|
||||
text: translateString("Members"),
|
||||
className: 'nav-item-members',
|
||||
});
|
||||
}
|
||||
@ -132,7 +133,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.user.addMedia,
|
||||
icon: 'video_call',
|
||||
text: 'Upload media',
|
||||
text: translateString("Upload"),
|
||||
className: 'nav-item-upload-media',
|
||||
});
|
||||
|
||||
@ -140,7 +141,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: userPages.media,
|
||||
icon: 'video_library',
|
||||
text: 'My media',
|
||||
text: translateString("My media"),
|
||||
className: 'nav-item-my-media',
|
||||
});
|
||||
}
|
||||
@ -150,7 +151,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: userPages.playlists,
|
||||
icon: 'playlist_play',
|
||||
text: 'My playlists',
|
||||
text: translateString("My playlists"),
|
||||
className: 'nav-item-my-playlists',
|
||||
});
|
||||
}
|
||||
@ -166,7 +167,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.user.history,
|
||||
icon: 'history',
|
||||
text: PageStore.get('config-enabled').pages.history.title,
|
||||
text: translateString("History"),
|
||||
className: 'nav-item-history',
|
||||
});
|
||||
}
|
||||
@ -179,7 +180,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.user.liked,
|
||||
icon: 'thumb_up',
|
||||
text: PageStore.get('config-enabled').pages.liked.title,
|
||||
text: translateString("Liked media"),
|
||||
className: 'nav-item-liked',
|
||||
});
|
||||
}
|
||||
@ -188,7 +189,35 @@ export function SidebarNavigationMenu() {
|
||||
}
|
||||
|
||||
function CustomMenuSection() {
|
||||
const items = PageStore.get('config-contents').sidebar.navMenu.items;
|
||||
const items = [];
|
||||
|
||||
items.push({
|
||||
link: '/about',
|
||||
icon: 'contact_support',
|
||||
text: translateString("About"),
|
||||
className: 'nav-item-about',
|
||||
});
|
||||
|
||||
items.push({
|
||||
link: '/tos',
|
||||
icon: 'description',
|
||||
text: translateString("Terms"),
|
||||
className: 'nav-item-terms',
|
||||
});
|
||||
|
||||
items.push({
|
||||
link: '/contact',
|
||||
icon: 'alternate_email',
|
||||
text: translateString("Contact"),
|
||||
className: 'nav-item-contact',
|
||||
});
|
||||
|
||||
items.push({
|
||||
link: '/setlanguage',
|
||||
icon: 'language',
|
||||
text: translateString("Language"),
|
||||
className: 'nav-item-language',
|
||||
});
|
||||
|
||||
return items.length ? <NavigationMenuList key="custom" items={formatItems(items)} /> : null;
|
||||
}
|
||||
@ -200,7 +229,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.manage.media,
|
||||
icon: 'miscellaneous_services',
|
||||
text: 'Manage media',
|
||||
text: translateString("Manage media"),
|
||||
className: 'nav-item-manage-media',
|
||||
});
|
||||
}
|
||||
@ -209,7 +238,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.manage.users,
|
||||
icon: 'miscellaneous_services',
|
||||
text: 'Manage users',
|
||||
text: translateString("Manage users"),
|
||||
className: 'nav-item-manage-users',
|
||||
});
|
||||
}
|
||||
@ -218,7 +247,7 @@ export function SidebarNavigationMenu() {
|
||||
items.push({
|
||||
link: links.manage.comments,
|
||||
icon: 'miscellaneous_services',
|
||||
text: 'Manage comments',
|
||||
text: translateString("Manage comments"),
|
||||
className: 'nav-item-manage-comments',
|
||||
});
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import { PageStore, ProfilePageStore } from '../../utils/stores/';
|
||||
import { PageActions, ProfilePageActions } from '../../utils/actions/';
|
||||
import { CircleIconButton, PopupMain } from '../_shared';
|
||||
import ItemsInlineSlider from '../item-list/includes/itemLists/ItemsInlineSlider';
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
class ProfileSearchBar extends React.PureComponent {
|
||||
constructor(props) {
|
||||
@ -315,13 +316,13 @@ class NavMenuInlineTabs extends React.PureComponent {
|
||||
<InlineTab
|
||||
id="about"
|
||||
isActive={'about' === this.props.type}
|
||||
label={'About' + (this.userIsAuthor ? ' Me' : '')}
|
||||
label={translateString('About')}
|
||||
link={LinksContext._currentValue.profile.about}
|
||||
/>
|
||||
<InlineTab
|
||||
id="media"
|
||||
isActive={'media' === this.props.type}
|
||||
label={(this.userIsAuthor ? 'My ' : '') + 'Media'}
|
||||
label={translateString('Media')}
|
||||
link={LinksContext._currentValue.profile.media}
|
||||
/>
|
||||
|
||||
@ -329,7 +330,7 @@ class NavMenuInlineTabs extends React.PureComponent {
|
||||
<InlineTab
|
||||
id="playlists"
|
||||
isActive={'playlists' === this.props.type}
|
||||
label={(this.userIsAuthor ? 'My ' : '') + 'Playlists'}
|
||||
label={translateString('Playlists')}
|
||||
link={LinksContext._currentValue.profile.playlists}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -3,13 +3,14 @@ import { ApiUrlConsumer } from '../utils/contexts/';
|
||||
import { MediaListWrapper } from '../components/MediaListWrapper';
|
||||
import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListAsync.jsx';
|
||||
import { Page } from './Page';
|
||||
import { translateString } from '../utils/helpers/';
|
||||
|
||||
interface CategoriesPageProps {
|
||||
id?: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export const CategoriesPage: React.FC<CategoriesPageProps> = ({ id = 'categories', title = 'Categories' }) => (
|
||||
export const CategoriesPage: React.FC<CategoriesPageProps> = ({ id = 'categories', title = translateString('Categories') }) => (
|
||||
<Page id={id}>
|
||||
<ApiUrlConsumer>
|
||||
{(apiUrl) => (
|
||||
|
@ -4,6 +4,7 @@ import { PageStore } from '../utils/stores/';
|
||||
import { MediaListWrapper } from '../components/MediaListWrapper';
|
||||
import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListAsync.jsx';
|
||||
import { Page } from './Page';
|
||||
import { translateString } from '../utils/helpers/';
|
||||
|
||||
interface FeaturedMediaPageProps {
|
||||
id?: string;
|
||||
@ -12,7 +13,7 @@ interface FeaturedMediaPageProps {
|
||||
|
||||
export const FeaturedMediaPage: React.FC<FeaturedMediaPageProps> = ({
|
||||
id = 'featured-media',
|
||||
title = PageStore.get('config-enabled').pages.featured.title,
|
||||
title = translateString('Featured'),
|
||||
}) => (
|
||||
<Page id={id}>
|
||||
<ApiUrlConsumer>
|
||||
|
@ -7,6 +7,7 @@ import { MediaListWrapper } from '../components/MediaListWrapper';
|
||||
import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListAsync.jsx';
|
||||
import { ProfileHistoryPage } from './ProfileHistoryPage';
|
||||
import { Page } from './Page';
|
||||
import { translateString } from '../utils/helpers/';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@ -21,7 +22,7 @@ interface AnonymousHistoryPageProps {
|
||||
|
||||
export const AnonymousHistoryPage: React.FC<AnonymousHistoryPageProps> = ({
|
||||
id = 'history-media',
|
||||
title = PageStore.get('config-enabled').pages.history.title,
|
||||
title = translateString('History'),
|
||||
}) => {
|
||||
const [resultsCount, setResultsCount] = useState<number | null>(null);
|
||||
|
||||
|
@ -6,6 +6,7 @@ import { MediaMultiListWrapper } from '../components/MediaMultiListWrapper';
|
||||
import { ItemListAsync } from '../components/item-list/ItemListAsync.jsx';
|
||||
import { InlineSliderItemListAsync } from '../components/item-list/InlineSliderItemListAsync.jsx';
|
||||
import { Page } from './Page';
|
||||
import { translateString } from '../utils/helpers/';
|
||||
|
||||
const EmptyMedia: React.FC = ({}) => {
|
||||
return (
|
||||
@ -35,9 +36,12 @@ interface HomePageProps {
|
||||
|
||||
export const HomePage: React.FC<HomePageProps> = ({
|
||||
id = 'home',
|
||||
featured_title = PageStore.get('config-options').pages.home.sections.featured.title,
|
||||
recommended_title = PageStore.get('config-options').pages.home.sections.recommended.title,
|
||||
latest_title = PageStore.get('config-options').pages.home.sections.latest.title,
|
||||
//featured_title = PageStore.get('config-options').pages.home.sections.featured.title,
|
||||
//recommended_title = PageStore.get('config-options').pages.home.sections.recommended.title,
|
||||
//latest_title = PageStore.get('config-options').pages.home.sections.latest.title,
|
||||
featured_title = translateString('Featured'),
|
||||
recommended_title = translateString('Recommended'),
|
||||
latest_title = translateString('Latest'),
|
||||
latest_view_all_link = false,
|
||||
featured_view_all_link = true,
|
||||
recommended_view_all_link = true,
|
||||
|
@ -4,6 +4,7 @@ import { PageStore } from '../utils/stores/';
|
||||
import { MediaListWrapper } from '../components/MediaListWrapper';
|
||||
import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListAsync';
|
||||
import { Page } from './Page';
|
||||
import { translateString } from '../utils/helpers/';
|
||||
|
||||
interface LatestMediaPageProps {
|
||||
id?: string;
|
||||
@ -12,7 +13,7 @@ interface LatestMediaPageProps {
|
||||
|
||||
export const LatestMediaPage: React.FC<LatestMediaPageProps> = ({
|
||||
id = 'latest-media',
|
||||
title = PageStore.get('config-enabled').pages.latest.title,
|
||||
title = translateString('Recent uploads'),
|
||||
}) => (
|
||||
<Page id={id}>
|
||||
<ApiUrlConsumer>
|
||||
|
@ -7,6 +7,7 @@ import { MediaListWrapper } from '../components/MediaListWrapper';
|
||||
import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListAsync';
|
||||
import { ProfileLikedPage } from './ProfileLikedPage';
|
||||
import { Page } from './Page';
|
||||
import { translateString } from '../utils/helpers/';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@ -21,7 +22,7 @@ interface AnonymousLikedMediaPageProps {
|
||||
|
||||
export const AnonymousLikedMediaPage: React.FC<AnonymousLikedMediaPageProps> = ({
|
||||
id = 'liked-media',
|
||||
title = PageStore.get('config-enabled').pages.liked.title,
|
||||
title = translateString('Liked media'),
|
||||
}) => {
|
||||
const [resultsCount, setResultsCount] = useState<number | null>(null);
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { PageStore } from '../utils/stores/';
|
||||
import { MediaListWrapper } from '../components/MediaListWrapper';
|
||||
import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListAsync.jsx';
|
||||
import { Page } from './Page';
|
||||
import { translateString } from '../utils/helpers/';
|
||||
|
||||
interface RecommendedMediaPageProps {
|
||||
id?: string;
|
||||
@ -12,7 +13,7 @@ interface RecommendedMediaPageProps {
|
||||
|
||||
export const RecommendedMediaPage: React.FC<RecommendedMediaPageProps> = ({
|
||||
id = 'recommended-media',
|
||||
title = PageStore.get('config-enabled').pages.recommended.title,
|
||||
title = translateString('Recommended'),
|
||||
}) => (
|
||||
<Page id={id}>
|
||||
<ApiUrlConsumer>
|
||||
|
@ -7,6 +7,7 @@ import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListA
|
||||
import { SearchMediaFiltersRow } from '../components/search-filters/SearchMediaFiltersRow';
|
||||
import { SearchResultsFilters } from '../components/search-filters/SearchResultsFilters';
|
||||
import { Page } from './_Page';
|
||||
import { translateString } from '../utils/helpers/';
|
||||
|
||||
export class SearchPage extends Page {
|
||||
constructor(props) {
|
||||
@ -114,13 +115,13 @@ export class SearchPage extends Page {
|
||||
} else {
|
||||
if (this.state.searchCategories) {
|
||||
title = null === this.state.resultsCount || 0 === this.state.resultsCount ? 'No' : this.state.resultsCount;
|
||||
title += ' media in category "' + this.state.searchCategories + '"';
|
||||
title += ' ' + translateString('media in category') + ' "' + this.state.searchCategories + '"';
|
||||
} else if (this.state.searchTags) {
|
||||
title = null === this.state.resultsCount || 0 === this.state.resultsCount ? 'No' : this.state.resultsCount;
|
||||
title += ' media in tag "' + this.state.searchTags + '"';
|
||||
title += ' ' + translateString('media in tag') + ' "' + this.state.searchTags + '"';
|
||||
} else {
|
||||
if (null === this.state.resultsCount || 0 === this.state.resultsCount) {
|
||||
title = 'No results for "' + this.state.searchQuery + '"';
|
||||
title = translateString('No results for') + ' "' + this.state.searchQuery + '"';
|
||||
} else {
|
||||
title =
|
||||
this.state.resultsCount +
|
||||
|
@ -3,13 +3,14 @@ import { ApiUrlConsumer } from '../utils/contexts/';
|
||||
import { MediaListWrapper } from '../components/MediaListWrapper';
|
||||
import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListAsync.jsx';
|
||||
import { Page } from './Page';
|
||||
import { translateString } from '../utils/helpers/';
|
||||
|
||||
interface TagsPageProps {
|
||||
id?: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export const TagsPage: React.FC<TagsPageProps> = ({ id = 'tags', title = 'Tags' }) => (
|
||||
export const TagsPage: React.FC<TagsPageProps> = ({ id = 'tags', title = translateString('Tags') }) => (
|
||||
<Page id={id}>
|
||||
<ApiUrlConsumer>
|
||||
{(apiUrl) => (
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { addClassname, removeClassname } from '../helpers/';
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
export function UpNextLoaderView(nextItemData) {
|
||||
var timerTimeout;
|
||||
@ -39,7 +40,7 @@ export function UpNextLoaderView(nextItemData) {
|
||||
domElems.nextMediaTitle.setAttribute('class', 'next-media-title');
|
||||
domElems.nextMediaAuthor.setAttribute('class', 'next-media-author');
|
||||
|
||||
domElems.upNextLabel.innerHTML = 'Up Next';
|
||||
domElems.upNextLabel.innerHTML = translateString('Up Next');
|
||||
domElems.nextMediaTitle.innerHTML = nextItemData.title;
|
||||
domElems.nextMediaAuthor.innerHTML = nextItemData.author_name;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
const config = mediacmsConfig(window.MediaCMS);
|
||||
|
||||
@ -17,7 +18,7 @@ function popupTopNavItems() {
|
||||
items.push({
|
||||
link: links.user.addMedia,
|
||||
icon: 'video_call',
|
||||
text: 'Upload media',
|
||||
text: translateString('Upload media'),
|
||||
itemAttr: {
|
||||
className: 'visible-only-in-small',
|
||||
},
|
||||
@ -27,7 +28,7 @@ function popupTopNavItems() {
|
||||
items.push({
|
||||
link: user.pages.media,
|
||||
icon: 'video_library',
|
||||
text: 'My media',
|
||||
text: translateString('My media'),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -35,7 +36,7 @@ function popupTopNavItems() {
|
||||
items.push({
|
||||
link: links.signout,
|
||||
icon: 'exit_to_app',
|
||||
text: 'Sign out',
|
||||
text: translateString('Sign out'),
|
||||
});
|
||||
}
|
||||
|
||||
@ -64,7 +65,7 @@ function popupMiddleNavItems() {
|
||||
itemType: 'link',
|
||||
icon: 'login',
|
||||
iconPos: 'left',
|
||||
text: 'Sign in',
|
||||
text: translateString('Sign in'),
|
||||
link: links.signin,
|
||||
linkAttr: {
|
||||
className: hasThemeSwitcher ? 'visible-only-in-small' : 'visible-only-in-extra-small',
|
||||
@ -77,7 +78,7 @@ function popupMiddleNavItems() {
|
||||
itemType: 'link',
|
||||
icon: 'person_add',
|
||||
iconPos: 'left',
|
||||
text: 'Register',
|
||||
text: translateString('Register'),
|
||||
link: links.register,
|
||||
linkAttr: {
|
||||
className: hasThemeSwitcher ? 'visible-only-in-small' : 'visible-only-in-extra-small',
|
||||
@ -88,14 +89,14 @@ function popupMiddleNavItems() {
|
||||
items.push({
|
||||
link: links.user.editProfile,
|
||||
icon: 'brush',
|
||||
text: 'Edit profile',
|
||||
text: translateString('Edit profile'),
|
||||
});
|
||||
|
||||
if (user.can.changePassword) {
|
||||
items.push({
|
||||
link: links.changePassword,
|
||||
icon: 'lock',
|
||||
text: 'Change password',
|
||||
text: translateString('Change password'),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -12,3 +12,5 @@ export * from './propTypeFilters';
|
||||
export { default as publishedOnDate } from './publishedOnDate';
|
||||
export * from './quickSort';
|
||||
export * from './requests';
|
||||
export { translateString } from './translate';
|
||||
export { replaceString } from './replacementStrings';
|
||||
|
@ -0,0 +1,8 @@
|
||||
// check templates/config/installation/translations.html for more
|
||||
|
||||
export function replaceString(string) {
|
||||
for (const key in window.REPLACEMENTS) {
|
||||
string = string.replace(key, window.REPLACEMENTS[key]);
|
||||
}
|
||||
return string;
|
||||
}
|
9
frontend/src/static/js/utils/helpers/translate.js
Normal file
9
frontend/src/static/js/utils/helpers/translate.js
Normal file
@ -0,0 +1,9 @@
|
||||
// check templates/config/installation/translations.html for more
|
||||
|
||||
export function translateString(string) {
|
||||
if (window.TRANSLATION && window.TRANSLATION[string]) {
|
||||
return window.TRANSLATION[string];
|
||||
} else {
|
||||
return string;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { useItemList } from './useItemList';
|
||||
import { translateString } from '../../utils/helpers/';
|
||||
|
||||
export function useItemListSync(props) {
|
||||
const itemsListRef = useRef(null);
|
||||
@ -32,7 +33,7 @@ export function useItemListSync(props) {
|
||||
|
||||
return 1 > listHandler.totalPages() || listHandler.loadedAllItems() ? null : (
|
||||
<button className="load-more" onClick={onClickLoadMore}>
|
||||
SHOW MORE
|
||||
{translateString("SHOW MORE")}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
MediaItemEditLink,
|
||||
} from '../../components/list-item/includes/items';
|
||||
import { useItem } from './useItem';
|
||||
import { replaceString } from '../../utils/helpers/';
|
||||
|
||||
export function itemClassname(defaultClassname, inheritedClassname, isActiveInPlaylistPlayback) {
|
||||
let classname = defaultClassname;
|
||||
@ -56,7 +57,7 @@ export function useMediaItem(props) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const publishDate = format(new Date(props.publish_date));
|
||||
const publishDate = replaceString(format(new Date(props.publish_date)));
|
||||
const publishDateTime =
|
||||
'string' === typeof props.publish_date
|
||||
? Date.parse(props.publish_date)
|
||||
|
Reference in New Issue
Block a user