Translate TracksPage

This commit is contained in:
Paul Bienkowski 2022-07-24 17:45:10 +02:00
parent f1f40a254a
commit 1533fdc450
4 changed files with 75 additions and 24 deletions

View file

@ -1,16 +1,15 @@
import React from 'react' import React from 'react'
import {Link} from 'react-router-dom' import {Grid, Loader, Header, Item} from 'semantic-ui-react'
import {Message, Grid, Loader, Header, Item} from 'semantic-ui-react'
import {useObservable} from 'rxjs-hooks' import {useObservable} from 'rxjs-hooks'
import {of, from} from 'rxjs' import {of, from} from 'rxjs'
import {map, switchMap} from 'rxjs/operators' import {map, switchMap} from 'rxjs/operators'
import {useTranslation, Trans as Translate} from 'react-i18next' import {useTranslation} from 'react-i18next'
import api from 'api' import api from 'api'
import {Stats, Page} from 'components' import {Stats, Page} from 'components'
import type {Track} from 'types' import type {Track} from 'types'
import {TrackListItem} from './TracksPage' import {TrackListItem, NoPublicTracksMessage} from './TracksPage'
function MostRecentTrack() { function MostRecentTrack() {
const {t} = useTranslation() const {t} = useTranslation()
@ -30,11 +29,7 @@ function MostRecentTrack() {
<Header as="h2">{t('HomePage.mostRecentTrack')}</Header> <Header as="h2">{t('HomePage.mostRecentTrack')}</Header>
<Loader active={track === null} /> <Loader active={track === null} />
{track === undefined ? ( {track === undefined ? (
<Message> <NoPublicTracksMessage />
<Translate i18nKey="HomePage.noPublicTracks">
No public tracks yet. <Link to="/upload">Upload the first!</Link>
</Translate>
</Message>
) : track ? ( ) : track ? (
<Item.Group> <Item.Group>
<TrackListItem track={track} /> <TrackListItem track={track} />

View file

@ -6,6 +6,7 @@ import {Link} from 'react-router-dom'
import {of, from, concat} from 'rxjs' import {of, from, concat} from 'rxjs'
import {map, switchMap, distinctUntilChanged} from 'rxjs/operators' import {map, switchMap, distinctUntilChanged} from 'rxjs/operators'
import _ from 'lodash' import _ from 'lodash'
import {useTranslation, Trans as Translate} from 'react-i18next'
import type {Track} from 'types' import type {Track} from 'types'
import {Avatar, Page, StripMarkdown} from 'components' import {Avatar, Page, StripMarkdown} from 'components'
@ -38,10 +39,11 @@ function TrackList({privateTracks}: {privateTracks: boolean}) {
const {tracks, trackCount} = data || {tracks: [], trackCount: 0} const {tracks, trackCount} = data || {tracks: [], trackCount: 0}
const loading = !data const loading = !data
const totalPages = Math.ceil(trackCount / pageSize) const totalPages = Math.ceil(trackCount / pageSize)
const {t} = useTranslation()
return ( return (
<div> <div>
<Loader content="Loading" active={loading} /> <Loader content={t('general.loading')} active={loading} />
{!loading && totalPages > 1 && ( {!loading && totalPages > 1 && (
<Pagination <Pagination
activePage={page} activePage={page}
@ -57,15 +59,23 @@ function TrackList({privateTracks}: {privateTracks: boolean}) {
))} ))}
</Item.Group> </Item.Group>
) : ( ) : (
<Message> <NoPublicTracksMessage />
No public tracks yet. <Link to="/upload">Upload the first!</Link>
</Message>
)} )}
</div> </div>
) )
} }
function maxLength(t, max) { export function NoPublicTracksMessage() {
return (
<Message>
<Translate i18nKey="TracksPage.noPublicTracks">
No public tracks yet. <Link to="/upload">Upload the first!</Link>
</Translate>
</Message>
)
}
function maxLength(t: string|null, max: number): string|null {
if (t && t.length > max) { if (t && t.length > max) {
return t.substring(0, max) + ' ...' return t.substring(0, max) + ' ...'
} else { } else {
@ -82,6 +92,8 @@ const COLOR_BY_STATUS = {
} }
export function TrackListItem({track, privateTracks = false}) { export function TrackListItem({track, privateTracks = false}) {
const {t} = useTranslation()
return ( return (
<Item key={track.slug}> <Item key={track.slug}>
<Item.Image size="tiny"> <Item.Image size="tiny">
@ -89,10 +101,12 @@ export function TrackListItem({track, privateTracks = false}) {
</Item.Image> </Item.Image>
<Item.Content> <Item.Content>
<Item.Header as={Link} to={`/tracks/${track.slug}`}> <Item.Header as={Link} to={`/tracks/${track.slug}`}>
{track.title || 'Unnamed track'} {track.title || t('general.unnamedTrack')}
</Item.Header> </Item.Header>
<Item.Meta> <Item.Meta>
Created by {track.author.username} on {track.createdAt} <Translate i18nKey="TracksPage.createdBy">
Created by <span style={{margin: 0}}>{{author: track.author.username}}</span> on <span style={{margin: 0}}>{{date: track.createdAt}}</span>
</Translate>
</Item.Meta> </Item.Meta>
<Item.Description> <Item.Description>
<StripMarkdown>{maxLength(track.description, 200)}</StripMarkdown> <StripMarkdown>{maxLength(track.description, 200)}</StripMarkdown>
@ -101,17 +115,18 @@ export function TrackListItem({track, privateTracks = false}) {
<Item.Extra> <Item.Extra>
{track.public ? ( {track.public ? (
<> <>
<Icon color="blue" name="eye" fitted /> Public <Icon color="blue" name="eye" fitted /> {t('general.public')}
</> </>
) : ( ) : (
<> <>
<Icon name="eye slash" fitted /> Private <Icon name="eye slash" fitted /> {t('general.private')}
</> </>
)} )}
<span style={{marginLeft: '1em'}}> <span style={{marginLeft: '1em'}}>
<Icon color={COLOR_BY_STATUS[track.processingStatus]} name="bolt" fitted /> Processing{' '} <Icon color={COLOR_BY_STATUS[track.processingStatus]} name="bolt" fitted />
{track.processingStatus} {' '}
{t(`TracksPage.processing.${track.processingStatus}`)}
</span> </span>
</Item.Extra> </Item.Extra>
)} )}
@ -121,6 +136,7 @@ export function TrackListItem({track, privateTracks = false}) {
} }
function UploadButton({navigate, ...props}) { function UploadButton({navigate, ...props}) {
const {t} = useTranslation()
const onClick = useCallback( const onClick = useCallback(
(e) => { (e) => {
e.preventDefault() e.preventDefault()
@ -130,13 +146,15 @@ function UploadButton({navigate, ...props}) {
) )
return ( return (
<Button onClick={onClick} {...props} color="green" style={{float: 'right'}}> <Button onClick={onClick} {...props} color="green" style={{float: 'right'}}>
Upload {t('TracksPage.upload')}
</Button> </Button>
) )
} }
const TracksPage = connect((state) => ({login: (state as any).login}))(function TracksPage({login, privateTracks}) { const TracksPage = connect((state) => ({login: (state as any).login}))(function TracksPage({login, privateTracks}) {
const title = privateTracks ? 'My tracks' : 'Public tracks' const {t} = useTranslation()
const title = privateTracks ? t('TracksPage.titleUser') : t('TracksPage.titlePublic')
return ( return (
<Page title={title}> <Page title={title}>
<Header as='h2'>{title}</Header> <Header as='h2'>{title}</Header>

View file

@ -1,3 +1,9 @@
general:
loading: Lädt
unnamedTrack: Unbenannte Fahrt
public: Öffentlich
private: Privat
App: App:
footer: footer:
aboutTheProject: Über das Projekt aboutTheProject: Über das Projekt
@ -29,7 +35,6 @@ LoginButton:
HomePage: HomePage:
mostRecentTrack: Neueste Fahrt mostRecentTrack: Neueste Fahrt
noPublicTracks: Es gibt noch keine öffentlichen Fahrten. <1>Lade die erste hoch!</1>
Stats: Stats:
title: Statistik title: Statistik
@ -43,3 +48,17 @@ Stats:
thisMonth: Dieser Monat thisMonth: Dieser Monat
thisYear: Dieses Jahr thisYear: Dieses Jahr
allTime: Immer allTime: Immer
TracksPage:
titlePublic: Öffentliche Fahrten
titleUser: Meine Fahrten
noPublicTracks: Es gibt noch keine öffentlichen Fahrten. <1>Lade die erste hoch!</1>
createdBy: Erstellt von <1>{{author}}</1> am <1>{{date}}</1>
upload: Hochladen
processing:
created: Nicht verarbeitet
queued: Verarbeitung in Warteschlage
processing: Verarbeite...
complete: Verarbeitet
error: Fehler bei Verarbeitung

View file

@ -2,6 +2,12 @@ locales:
en: English en: English
de: Deutsch de: Deutsch
general:
loading: Loading
unnamedTrack: Unnamed track
public: Public
private: Private
App: App:
footer: footer:
aboutTheProject: About the project aboutTheProject: About the project
@ -33,7 +39,6 @@ LoginButton:
HomePage: HomePage:
mostRecentTrack: Most recent track mostRecentTrack: Most recent track
noPublicTracks: No public tracks yet. <1>Upload the first!</1>
Stats: Stats:
title: Statistics title: Statistics
@ -47,3 +52,17 @@ Stats:
thisMonth: This month thisMonth: This month
thisYear: This year thisYear: This year
allTime: All time allTime: All time
TracksPage:
titlePublic: Public tracks
titleUser: My tracks
noPublicTracks: No public tracks yet. <1>Upload the first!</1>
createdBy: Created by <1>{author}</1> on <1>{date}</1>
upload: Upload
processing:
created: Not processed
queued: Processing queued
processing: Processing...
complete: Processed
error: Error while processing