Implement locales in codebase

This commit is contained in:
Lei Nelissen
2020-11-02 22:50:00 +01:00
parent 0df9d4a621
commit 6cf421f24f
14 changed files with 47 additions and 33 deletions

View File

@@ -6,6 +6,7 @@
"clear-queue": "Clear Queue",
"no-results": "No results...",
"album": "Album",
"albums": "Albums",
"all-albums": "All Albums",
"search": "Search",
"music": "Music",

View File

@@ -5,6 +5,7 @@ export type LocaleKeys = 'play-next'
| 'clear-queue'
| 'no-results'
| 'album'
| 'albums'
| 'all-albums'
| 'search'
| 'music'

View File

@@ -6,6 +6,7 @@ import Album from './stacks/Album';
import RecentAlbums from './stacks/RecentAlbums';
import Search from './stacks/Search';
import { THEME_COLOR } from 'CONSTANTS';
import { t } from '@localisation';
const Stack = createStackNavigator<StackParams>();
@@ -17,10 +18,10 @@ const navigationOptions = {
function MusicStack() {
return (
<Stack.Navigator initialRouteName="RecentAlbums" screenOptions={navigationOptions}>
<Stack.Screen name="RecentAlbums" component={RecentAlbums} options={{ headerTitle: 'Recent Albums' }} />
<Stack.Screen name="Albums" component={Albums} />
<Stack.Screen name="Album" component={Album} />
<Stack.Screen name="Search" component={Search} />
<Stack.Screen name="RecentAlbums" component={RecentAlbums} options={{ headerTitle: t('recent-albums') }} />
<Stack.Screen name="Albums" component={Albums} options={{ headerTitle: t('albums') }} />
<Stack.Screen name="Album" component={Album} options={{ headerTitle: t('album') }} />
<Stack.Screen name="Search" component={Search} options={{ headerTitle: t('search') }} />
</Stack.Navigator>
);
}

View File

@@ -15,6 +15,7 @@ import TouchableHandler from 'components/TouchableHandler';
import useCurrentTrack from 'utility/useCurrentTrack';
import { colors } from 'components/Colors';
import TrackPlayer from 'react-native-track-player';
import { t } from '@localisation';
type Route = RouteProp<StackParams, 'Album'>;
@@ -114,7 +115,7 @@ const Album: React.FC = () => {
<AlbumImage source={{ uri: getImage(album?.Id) }} style={colors.imageBackground} />
<Text style={styles.name} >{album?.Name}</Text>
<Text style={styles.artist}>{album?.AlbumArtist}</Text>
<Button title="Play Album" onPress={selectAlbum} color={THEME_COLOR} />
<Button title={t('play-album')} onPress={selectAlbum} color={THEME_COLOR} />
{album?.Tracks?.length ? album.Tracks.map((trackId) =>
<TouchableHandler
key={trackId}

View File

@@ -13,6 +13,7 @@ import { useRecentAlbums } from 'store/music/selectors';
import { Header } from 'components/Typography';
import ListButton from 'components/ListButton';
import { colors } from 'components/Colors';
import { t } from '@localisation';
const styles = StyleSheet.create({
artist: {
@@ -28,9 +29,9 @@ const NavigationHeader: React.FC = () => {
return (
<ListContainer>
<ListButton onPress={handleAllAlbumsClick}>All Albums</ListButton>
<ListButton onPress={handleSearchClick}>Search</ListButton>
<Header style={colors.text}>Recent Albums</Header>
<ListButton onPress={handleAllAlbumsClick}>{t('all-albums')}</ListButton>
<ListButton onPress={handleSearchClick}>{t('search')}</ListButton>
<Header style={colors.text}>{t('recent-albums')}</Header>
</ListContainer>
);
};

View File

@@ -12,6 +12,7 @@ import { useGetImage } from 'utility/JellyfinApi';
import { NavigationProp } from '../types';
import FastImage from 'react-native-fast-image';
import { colors } from 'components/Colors';
import { t } from '@localisation';
const Container = styled.View`
padding: 0 20px;
@@ -88,8 +89,8 @@ export default function Search() {
const HeaderComponent = React.useMemo(() => (
<Container>
<Input value={searchTerm} onChangeText={setSearchTerm} style={colors.input} placeholder="Search..." />
{(searchTerm.length && !results.length) ? <Text>No results...</Text> : null}
<Input value={searchTerm} onChangeText={setSearchTerm} style={colors.input} placeholder={t('search') + '...'} />
{(searchTerm.length && !results.length) ? <Text>{t('no-results')}</Text> : null}
</Container>
), [searchTerm, results, setSearchTerm]);
@@ -110,7 +111,7 @@ export default function Search() {
<Text numberOfLines={1} ellipsizeMode="tail" style={colors.text}>
{album.Name} - {album.AlbumArtist}
</Text>
<HalfOpacity style={colors.text}>Album</HalfOpacity>
<HalfOpacity style={colors.text}>{t('album')}</HalfOpacity>
</View>
</SearchResult>
</TouchableHandler>

View File

@@ -7,6 +7,7 @@ import { NavigationProp } from 'screens';
import { useTypedSelector } from 'store';
import { useDispatch } from 'react-redux';
import { setOnboardingStatus } from 'store/settings/actions';
import { t } from '@localisation';
const Container = styled.SafeAreaView`
background-color: ${THEME_COLOR};
@@ -57,16 +58,16 @@ function Onboarding() {
<TextContainer contentContainerStyle={{ flexGrow: 1, justifyContent: 'center' }}>
<Logo source={require('../../assets/app-icon-white.png')} />
<Text >
Welcome!
{t('onboarding-welcome')}
</Text>
<Text>
Jellyfin Audio Player will allow you to stream your music library from anywhere, with full support for background audio and casting.
{t('onboarding-intro')}
</Text>
<Text>
In order to get started, you need a Jellyfin server. Click the button below to enter your Jellyfin server address and login to it.
{t('onboarding-cta')}
</Text>
<ButtonContainer>
<Button title="Set Jellyfin Server" color="#ffffff" onPress={handleClick} />
<Button title={t('set-jellyfin-server')} color="#ffffff" onPress={handleClick} />
</ButtonContainer>
</TextContainer>
</Container>

View File

@@ -7,6 +7,7 @@ import TouchableHandler from 'components/TouchableHandler';
import TrackPlayer from 'react-native-track-player';
import { THEME_COLOR } from 'CONSTANTS';
import { colors } from 'components/Colors';
import { t } from '@localisation';
const QueueItem = styled.View<{ active?: boolean, alreadyPlayed?: boolean, isDark?: boolean }>`
padding: 10px;
@@ -52,7 +53,7 @@ export default function Queue() {
return (
<View>
<Text style={{ marginTop: 20, marginBottom: 20 }}>Queue</Text>
<Text style={{ marginTop: 20, marginBottom: 20 }}>{t('queue')}</Text>
{queue.map((track, i) => (
<TouchableHandler id={track.id} onPress={playTrack} key={i}>
<QueueItem
@@ -70,7 +71,7 @@ export default function Queue() {
</TouchableHandler>
))}
<ClearQueue>
<Button title="Clear Queue" color={THEME_COLOR} onPress={clearQueue} />
<Button title={t('clear-queue')} color={THEME_COLOR} onPress={clearQueue} />
</ClearQueue>
</View>
);

View File

@@ -5,6 +5,7 @@ import { Text, Button } from 'react-native';
import { THEME_COLOR } from 'CONSTANTS';
import { useDispatch } from 'react-redux';
import music from 'store/music';
import { t } from '@localisation';
export default function CacheSettings() {
const dispatch = useDispatch();
@@ -18,9 +19,9 @@ export default function CacheSettings() {
return (
<>
<SubHeader>Cache</SubHeader>
<Text>If you have updated your Jellyfin library, but the app is holding on to cached assets, you can forcefully clear the cache using this button. This will force the app to fetch the library from scratch.</Text>
<Button title="Reset Cache" onPress={handleClearCache} color={THEME_COLOR} />
<SubHeader>{t('setting-cache')}</SubHeader>
<Text>{t('setting-cache-description')}</Text>
<Button title={t('reset-cache')} onPress={handleClearCache} color={THEME_COLOR} />
</>
);
}

View File

@@ -7,6 +7,7 @@ import { SubHeader } from 'components/Typography';
import { colors } from 'components/Colors';
import { NavigationProp } from '../..';
import { useTypedSelector } from 'store';
import { t } from '@localisation';
const InputContainer = styled.View`
margin: 10px 0;
@@ -25,20 +26,20 @@ export default function LibrarySettings() {
return (
<>
<SubHeader>Jellyfin Library</SubHeader>
<SubHeader>{t('jellyfin-library')}</SubHeader>
<InputContainer>
<Text style={colors.text}>Jellyfin Server URL</Text>
<Text style={colors.text}>{t('jellyfin-server-url')}</Text>
<Input placeholder="https://jellyfin.yourserver.com/" value={jellyfin?.uri} editable={false} style={colors.input} />
</InputContainer>
<InputContainer>
<Text style={colors.text}>Jellyfin Access Token</Text>
<Text style={colors.text}>{t('jellyfin-access-token')}</Text>
<Input placeholder="deadbeefdeadbeefdeadbeef" value={jellyfin?.access_token} editable={false} style={colors.input} />
</InputContainer>
<InputContainer>
<Text style={colors.text}>Jellyfin User ID</Text>
<Text style={colors.text}>{t('jellyfin-user-id')}</Text>
<Input placeholder="deadbeefdeadbeefdeadbeef" value={jellyfin?.user_id} editable={false} style={colors.input} />
</InputContainer>
<Button title="Set Jellyfin server" onPress={handleSetLibrary} color={THEME_COLOR} />
<Button title={t('set-jellyfin-server')} onPress={handleSetLibrary} color={THEME_COLOR} />
</>
);
}

View File

@@ -4,13 +4,14 @@ import { Header } from 'components/Typography';
import { colors } from 'components/Colors';
import Library from './components/Library';
import Cache from './components/Cache';
import { t } from '@localisation';
export default function Settings() {
return (
<ScrollView>
<SafeAreaView>
<View style={{ padding: 20 }}>
<Header style={colors.text}>Settings</Header>
<Header style={colors.text}>{t('settings')}</Header>
<Library />
<Cache />
</View>

View File

@@ -14,6 +14,7 @@ import { useTypedSelector } from 'store';
import Onboarding from './Onboarding';
import TrackPopupMenu from './modals/TrackPopupMenu';
import { ModalStackParams } from './types';
import { t } from '@localisation';
const Stack = createStackNavigator<ModalStackParams>();
const Tab = createBottomTabNavigator();
@@ -64,9 +65,9 @@ function Screens() {
inactiveTintColor: 'gray',
}}
>
<Tab.Screen name="NowPlaying" component={Player} options={{ tabBarLabel: 'Now Playing' }} />
<Tab.Screen name="Music" component={Music} />
<Tab.Screen name="Settings" component={Settings} />
<Tab.Screen name="NowPlaying" component={Player} options={{ tabBarLabel: t('now-playing') }} />
<Tab.Screen name="Music" component={Music} options={{ tabBarLabel: t('music') }} />
<Tab.Screen name="Settings" component={Settings} options={{ tabBarLabel: t('settings') }} />
</Tab.Navigator>
);
}

View File

@@ -8,6 +8,7 @@ import { useNavigation, StackActions } from '@react-navigation/native';
import CredentialGenerator from './components/CredentialGenerator';
import { THEME_COLOR } from 'CONSTANTS';
import { colors } from 'components/Colors';
import { t } from '@localisation';
export default function SetJellyfinServer() {
// State for first screen
@@ -34,7 +35,7 @@ export default function SetJellyfinServer() {
) : (
<View style={{ padding: 20, flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={colors.text}>
Please enter your Jellyfin server URL. Make sure to include the protocol and port
{t('set-jellyfin-server-instruction')}
</Text>
<Input
placeholder="https://jellyfin.yourserver.io/"
@@ -46,7 +47,7 @@ export default function SetJellyfinServer() {
style={{ ...colors.input, width: '100%' }}
/>
<Button
title="Set server"
title={t('set-jellyfin-server')}
onPress={() => setIsLogginIn(true)}
disabled={!serverUrl?.length}
color={THEME_COLOR}

View File

@@ -8,6 +8,7 @@ import { THEME_COLOR } from 'CONSTANTS';
import { SubHeader } from 'components/Typography';
import styled from 'styled-components/native';
import usePlayTrack from 'utility/usePlayTrack';
import { t } from '@localisation';
type Route = RouteProp<ModalStackParams, 'TrackPopupMenu'>;
@@ -48,8 +49,8 @@ function TrackPopupMenu() {
<SubHeader>{track?.Name}</SubHeader>
<Text>{track?.Album} - {track?.AlbumArtist}</Text>
<Buttons>
<Button title="Play Next" color={THEME_COLOR} onPress={handlePlayNext} />
<Button title="Add to Queue" color={THEME_COLOR} onPress={handleAddToQueue} />
<Button title={t('play-next')} color={THEME_COLOR} onPress={handlePlayNext} />
<Button title={t('add-to-queue')} color={THEME_COLOR} onPress={handleAddToQueue} />
</Buttons>
</Container>
</Modal>