Exposing components for translation mapping; Queue and AAlbum views now moved to translation file
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
|
||||
import { memo } from 'react';
|
||||
import { content } from '../locale';
|
||||
|
||||
/**
|
||||
* Format time duration
|
||||
@ -50,21 +51,21 @@ const durationSentence = (milliseconds = null) => {
|
||||
const totalMinutes = Math.floor(milliseconds / (1000 * 60));
|
||||
const totalHours = Math.floor(milliseconds / (1000 * 60 * 60));
|
||||
|
||||
if (totalHours > 1) return `${totalHours}+ hrs`;
|
||||
if (totalMinutes > 1) return `${totalMinutes} mins`;
|
||||
if (totalSeconds) return `${totalSeconds} sec`;
|
||||
return '0 mins';
|
||||
if (totalHours > 1) return `${totalHours}+ ${content('time.hours.short')}`;
|
||||
if (totalMinutes > 1) return `${totalMinutes} ${content('time.minutes.short')}`;
|
||||
if (totalSeconds) return `${totalSeconds} ${content('time.seconds.short')}`;
|
||||
return `0 ${content('time.minutes.short')}`;
|
||||
};
|
||||
|
||||
export default memo((props) => {
|
||||
if (props.data === undefined) {
|
||||
const dater = (type, data) => {
|
||||
if (data === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (props.type) {
|
||||
switch (type) {
|
||||
case 'total-time':
|
||||
var duration = 0;
|
||||
var tracks = props.data;
|
||||
var tracks = data;
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
if (tracks[i].duration) {
|
||||
duration += parseInt(tracks[i].duration);
|
||||
@ -73,22 +74,22 @@ export default memo((props) => {
|
||||
return durationSentence(duration);
|
||||
|
||||
case 'length':
|
||||
return durationTime(props.data);
|
||||
return durationTime(data);
|
||||
|
||||
case 'date':
|
||||
|
||||
// A four-character date indicates just a year (rather than a full date)
|
||||
if (props.data.length == 4) {
|
||||
return props.data;
|
||||
if (data.length == 4) {
|
||||
return data;
|
||||
|
||||
// Digest as a date string
|
||||
}
|
||||
var date = new Date(props.data);
|
||||
var date = new Date(data);
|
||||
return `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`;
|
||||
|
||||
|
||||
case 'ago':
|
||||
var date = new Date(props.data);
|
||||
var date = new Date(data);
|
||||
var diff = new Date() - date;
|
||||
var seconds = Math.floor(diff / 1000);
|
||||
var minutes = Math.floor(diff / (1000 * 60));
|
||||
@ -98,18 +99,27 @@ export default memo((props) => {
|
||||
var years = Math.floor(diff / (1000 * 60 * 60 * 24 * 7 * 52));
|
||||
|
||||
if (seconds < 60) {
|
||||
return `${seconds} second${seconds > 1 ? 's' : ''}`;
|
||||
return `${seconds} ${content(`time.seconds.${seconds > 1 ? 'singular' : 'plural'}`)}`;
|
||||
} if (minutes < 60) {
|
||||
return `${minutes} minute${minutes > 1 ? 's' : ''}`;
|
||||
return `${minutes} ${content(`time.minutes.${minutes > 1 ? 'singular' : 'plural'}`)}`;
|
||||
} if (hours < 24) {
|
||||
return `${hours} hour${hours > 1 ? 's' : ''}`;
|
||||
return `${hours} ${content(`time.hours.${hours > 1 ? 'singular' : 'plural'}`)}`;
|
||||
} if (days < 7) {
|
||||
return `${days} day${days > 1 ? 's' : ''}`;
|
||||
return `${days} ${content(`time.days.${days > 1 ? 'singular' : 'plural'}`)}`;
|
||||
} if (weeks < 54) {
|
||||
return `${weeks} week${weeks > 1 ? 's' : ''}`;
|
||||
return `${weeks} ${content(`time.weeks.${weeks > 1 ? 'singular' : 'plural'}`)}`;
|
||||
}
|
||||
return `${years} year${years > 1 ? 's' : ''}`;
|
||||
return `${years} ${content(`time.years.${years > 1 ? 'singular' : 'plural'}`)}`;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const Dater = memo(({ type, data }) => dater(type, data));
|
||||
|
||||
export {
|
||||
Dater,
|
||||
dater,
|
||||
};
|
||||
|
||||
export default Dater;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
|
||||
import React, { memo } from 'react';
|
||||
|
||||
export default memo((props) => {
|
||||
let formatted = parseInt(props.value);
|
||||
const nice_number = (value) => {
|
||||
let formatted = parseInt(value);
|
||||
|
||||
// > 1 million
|
||||
if (formatted > 1000000) {
|
||||
@ -14,10 +14,19 @@ export default memo((props) => {
|
||||
} else if (formatted > 1000) {
|
||||
formatted /= 1000;
|
||||
formatted = Math.round(formatted * 10) / 10;
|
||||
formatted = `${formatted}k`;
|
||||
formatted = `${formatted}k`;
|
||||
} else {
|
||||
formatted = formatted.toLocaleString();
|
||||
}
|
||||
|
||||
return formatted;
|
||||
});
|
||||
};
|
||||
|
||||
const NiceNumber = memo(({ value }) => nice_number(value));
|
||||
|
||||
export {
|
||||
NiceNumber,
|
||||
nice_number,
|
||||
};
|
||||
|
||||
export default NiceNumber;
|
||||
|
||||
@ -1,3 +1,41 @@
|
||||
errors:
|
||||
uri_not_found: Could not find anything with URI %{uri}
|
||||
specs:
|
||||
tracks: %{count} tracks
|
||||
followers: %{count} followers
|
||||
listeners: %{count} listeners
|
||||
plays: %{count} plays
|
||||
actions:
|
||||
play: Play
|
||||
pause: Pause
|
||||
stop: Stop
|
||||
add_to_library: Add to library
|
||||
remove_from_library: Remove from library
|
||||
time:
|
||||
seconds:
|
||||
short: secs
|
||||
singular: second
|
||||
plural: seconds
|
||||
minutes:
|
||||
short: mins
|
||||
singular: minute
|
||||
plural: minutes
|
||||
hours:
|
||||
short: hrs
|
||||
singular: hour
|
||||
plural: hours
|
||||
days:
|
||||
short: days
|
||||
singular: day
|
||||
plural: days
|
||||
weeks:
|
||||
short: wks
|
||||
singular: week
|
||||
plural: weeks
|
||||
years:
|
||||
short: yrs
|
||||
singular: year
|
||||
plural: years
|
||||
sidebar:
|
||||
now_playing: Now playing
|
||||
search: Search
|
||||
@ -20,9 +58,16 @@ now_playing:
|
||||
history: History
|
||||
add_uri: Add URI
|
||||
current_track:
|
||||
playing_from: Playling from
|
||||
playing_from: Playing from
|
||||
shuffle: Shuffle
|
||||
clear: Clear
|
||||
radio: Radio
|
||||
album:
|
||||
title: Album
|
||||
title_window: %{name} by %{artist} (album)
|
||||
wiki:
|
||||
title: About
|
||||
published: 'Published: %{date}'
|
||||
search:
|
||||
title: 'Search: %{term}'
|
||||
context_actions:
|
||||
|
||||
@ -8,7 +8,6 @@ const PARAMS_REG_EXP = '%{(.*?)}';
|
||||
const paramsRegExp = new RegExp(PARAMS_REG_EXP, 'g');
|
||||
|
||||
const content = (path, params = {}, transform) => {
|
||||
console.log(window.language);
|
||||
const dictionary = dictionaries[window.language || 'en'] || dictionaries.en;
|
||||
|
||||
let value = get((dictionary), path, '');
|
||||
|
||||
@ -3,18 +3,17 @@ import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
|
||||
import ErrorMessage from '../components/ErrorMessage';
|
||||
import Header from '../components/Header';
|
||||
import TrackList from '../components/TrackList';
|
||||
import Thumbnail from '../components/Thumbnail';
|
||||
import Parallax from '../components/Parallax';
|
||||
import LinksSentence from '../components/LinksSentence';
|
||||
import Loader from '../components/Loader';
|
||||
import FollowButton from '../components/Fields/FollowButton';
|
||||
import NiceNumber from '../components/NiceNumber';
|
||||
import NiceNumber, { nice_number } from '../components/NiceNumber';
|
||||
import Dater from '../components/Dater';
|
||||
import LazyLoadListener from '../components/LazyLoadListener';
|
||||
import ContextMenuTrigger from '../components/ContextMenuTrigger';
|
||||
import Icon from '../components/Icon';
|
||||
import { content } from '../locale';
|
||||
import * as coreActions from '../services/core/actions';
|
||||
import * as uiActions from '../services/ui/actions';
|
||||
import * as mopidyActions from '../services/mopidy/actions';
|
||||
@ -100,24 +99,21 @@ export class Album extends React.Component {
|
||||
}
|
||||
|
||||
setWindowTitle = (album = this.props.album) => {
|
||||
const { uiActions: { setWindowTitle } } = this.props;
|
||||
const { uiActions: { setWindowTitle }, artists } = this.props;
|
||||
|
||||
if (album) {
|
||||
let artists = '';
|
||||
let artistNames = [];
|
||||
if (album.artists_uris && artists) {
|
||||
for (let i = 0; i < album.artists_uris.length; i++) {
|
||||
const uri = album.artists_uris[i];
|
||||
if (artists.hasOwnProperty(uri)) {
|
||||
if (artists != '') {
|
||||
artists += ', ';
|
||||
}
|
||||
artists += artists[uri].name;
|
||||
artistNames.push(artists[uri].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
setWindowTitle(`${album.name} by ${artists} (album)`);
|
||||
setWindowTitle(content('album.title_window', { name: album.name, artist: artistNames.join() }));
|
||||
} else {
|
||||
setWindowTitle('Album');
|
||||
setWindowTitle(content('album.title'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +187,7 @@ export class Album extends React.Component {
|
||||
return (
|
||||
<ErrorMessage type="not-found" title="Not found">
|
||||
<p>
|
||||
{`Could not find album with URI "${encodeURIComponent(uri)}"`}
|
||||
{content('errors.uri_not_found', { uri: encodeURIComponent(uri) })}
|
||||
</p>
|
||||
</ErrorMessage>
|
||||
);
|
||||
@ -236,9 +232,10 @@ export class Album extends React.Component {
|
||||
) : null}
|
||||
{album.tracks ? (
|
||||
<li>
|
||||
{album.tracks_total || album.tracks.length}
|
||||
{' '}
|
||||
tracks
|
||||
{content(
|
||||
'specs.tracks',
|
||||
{ count: album.tracks_total || album.tracks.length },
|
||||
)}
|
||||
</li>
|
||||
) : null}
|
||||
{!this.props.slim_mode && album.tracks ? (
|
||||
@ -248,31 +245,33 @@ tracks
|
||||
) : null}
|
||||
{!this.props.slim_mode && album.play_count ? (
|
||||
<li>
|
||||
<NiceNumber value={album.play_count} />
|
||||
{' '}
|
||||
plays
|
||||
{content(
|
||||
'specs.plays',
|
||||
{ count: nice_number(album.play_count) },
|
||||
)}
|
||||
</li>
|
||||
) : null}
|
||||
{!this.props.slim_mode && album.listeners ? (
|
||||
<li>
|
||||
<NiceNumber value={album.listeners} />
|
||||
{' '}
|
||||
listeners
|
||||
{content(
|
||||
'specs.plays',
|
||||
{ count: nice_number(album.listeners) },
|
||||
)}
|
||||
</li>
|
||||
) : null}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="actions">
|
||||
<button className="button button--primary" onClick={(e) => this.play()}>
|
||||
Play
|
||||
<button type="button" className="button button--primary" onClick={(e) => this.play()}>
|
||||
{content('actions.play')}
|
||||
</button>
|
||||
{uriSource(this.props.uri) == 'spotify' ? (
|
||||
<FollowButton
|
||||
className="secondary"
|
||||
uri={this.props.uri}
|
||||
addText="Add to library"
|
||||
removeText="Remove from library"
|
||||
addText={content('actions.add_to_library')}
|
||||
removeText={content('actions.remove_from_library')}
|
||||
is_following={this.inLibrary()}
|
||||
/>
|
||||
) : null}
|
||||
@ -294,14 +293,15 @@ listeners
|
||||
|
||||
{album.wiki ? (
|
||||
<section className="wiki">
|
||||
<h4 className="wiki__title">About</h4>
|
||||
<h4 className="wiki__title">{content('album.wiki.title')}</h4>
|
||||
<div className="wiki__text">
|
||||
<p>{album.wiki}</p>
|
||||
<br />
|
||||
<div className="mid_grey-text">
|
||||
Published:
|
||||
{' '}
|
||||
{album.wiki_publish_date}
|
||||
{content(
|
||||
'album.wiki.published',
|
||||
{ date: album.wiki_publish_date },
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -201,7 +201,11 @@ class Queue extends React.Component {
|
||||
<div className="current-track__added-from__text">
|
||||
{'Playing from '}
|
||||
<LinksSentence items={items} />
|
||||
{uri_type === 'radio' && <span className="flag flag--blue">Radio</span>}
|
||||
{uri_type === 'radio' && (
|
||||
<span className="flag flag--blue">
|
||||
{content('now_playing.current_track.radio')}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -225,16 +229,16 @@ class Queue extends React.Component {
|
||||
{this.props.spotify_enabled && (
|
||||
<Link className="button button--no-hover" to="/queue/radio">
|
||||
<Icon name="radio" />
|
||||
Radio
|
||||
{content('now_playing.context_actions.radio')}
|
||||
</Link>
|
||||
)}
|
||||
<Link className="button button--no-hover" to="/queue/history">
|
||||
<Icon name="history" />
|
||||
History
|
||||
{content('now_playing.context_actions.history')}
|
||||
</Link>
|
||||
<Link className="button button--no-hover" to="/queue/add-uri">
|
||||
<Icon name="playlist_add" />
|
||||
Add URI
|
||||
{content('now_playing.context_actions.add_uri')}
|
||||
</Link>
|
||||
</span>
|
||||
);
|
||||
@ -279,7 +283,7 @@ class Queue extends React.Component {
|
||||
<li>
|
||||
<a onClick={this.props.mopidyActions.shuffleTracklist}>
|
||||
<Icon name="shuffle" />
|
||||
Shuffle
|
||||
{content('now_playing.current_track.shuffle')}
|
||||
</a>
|
||||
</li>
|
||||
)}
|
||||
@ -287,7 +291,7 @@ class Queue extends React.Component {
|
||||
<li>
|
||||
<a onClick={this.props.mopidyActions.clearTracklist}>
|
||||
<Icon name="delete_sweep" />
|
||||
Clear
|
||||
{content('now_playing.current_track.clear')}
|
||||
</a>
|
||||
</li>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user