Move translations to server

This commit is contained in:
Deluan
2020-05-01 18:29:50 -04:00
committed by Deluan Quintão
parent 1a9663d432
commit 41cf99541d
19 changed files with 954 additions and 801 deletions
+3 -8
View File
@@ -4,8 +4,6 @@ import { createHashHistory } from 'history'
import { Admin, Resource } from 'react-admin'
import dataProvider from './dataProvider'
import authProvider from './authProvider'
import polyglotI18nProvider from 'ra-i18n-polyglot'
import messages from './i18n'
import { Layout, Login } from './layout'
import transcoding from './transcoding'
import player from './player'
@@ -18,11 +16,7 @@ import { albumViewReducer } from './album/albumState'
import customRoutes from './routes'
import themeReducer from './personal/themeReducer'
import createAdminStore from './store/createAdminStore'
const i18nProvider = polyglotI18nProvider(
(locale) => (messages[locale] ? messages[locale] : messages.en),
localStorage.getItem('locale') || 'en'
)
import i18nProvider from './i18nProvider'
const history = createHashHistory()
@@ -52,7 +46,6 @@ const App = () => (
<Resource name="artist" {...artist} options={{ subMenu: 'library' }} />,
<Resource name="album" {...album} options={{ subMenu: 'library' }} />,
<Resource name="song" {...song} options={{ subMenu: 'library' }} />,
<Resource name="albumSong" />,
permissions === 'admin' ? (
<Resource name="user" {...user} options={{ subMenu: 'settings' }} />
) : null,
@@ -70,6 +63,8 @@ const App = () => (
) : (
<Resource name="transcoding" />
),
<Resource name="albumSong" />,
<Resource name="translation" />,
<Player />,
]}
</Admin>
-1
View File
@@ -47,7 +47,6 @@ const Player = () => {
destroyText: translate('player.destroyText'),
downloadText: translate('player.downloadText'),
removeAudioListsText: translate('player.removeAudioListsText'),
controllerTitle: translate('player.controllerTitle'),
clickToDeleteText: (name) =>
translate('player.clickToDeleteText', { name }),
emptyLyricText: translate('player.emptyLyricText'),
-148
View File
@@ -1,148 +0,0 @@
import deepmerge from 'deepmerge'
import englishMessages from 'ra-language-english'
export default deepmerge(englishMessages, {
languageName: 'English',
resources: {
song: {
name: 'Song |||| Songs',
fields: {
title: 'Title',
artist: 'Artist',
album: 'Album',
path: 'File Path',
genre: 'Genre',
compilation: 'Compilation',
duration: 'Time',
year: 'Year',
trackNumber: '#',
playCount: 'Plays',
size: 'File Size',
updatedAt: 'Updated At',
},
actions: {
playNow: 'Play Now',
addToQueue: 'Play Later',
},
},
album: {
name: 'Album |||| Albums',
fields: {
albumArtist: 'Album Artist',
name: 'Name',
artist: 'Artist',
songCount: 'Songs',
playCount: 'Plays',
genre: 'Genre',
compilation: 'Compilation',
duration: 'Duration',
year: 'Year',
},
actions: {
playAll: 'Play Now',
playNext: 'Play Next',
addToQueue: 'Play Later',
shuffle: 'Shuffle',
},
},
artist: {
name: 'Artist |||| Artists',
fields: {
name: 'Nome',
albumCount: 'Album Count',
},
},
user: {
name: 'User |||| Users',
fields: {
userName: 'Username',
name: 'Name',
isAdmin: 'Is Admin?',
lastLoginAt: 'Last Login',
updatedAt: 'Updated At',
},
},
player: {
name: 'Player |||| Players',
fields: {
name: 'Name',
transcodingId: 'Transcoding',
maxBitRate: 'Max BitRate',
client: 'Client',
userName: 'Username',
lastSeen: 'Last Seen',
},
},
transcoding: {
name: 'Transcoding |||| Transcodings',
fields: {
name: 'Name',
targetFormat: 'Target Format',
defaultBitRate: 'Default BitRate',
command: 'Command',
},
},
},
ra: {
auth: {
welcome1: 'Thanks for installing Navidrome!',
welcome2: 'To start, create an admin user',
confirmPassword: 'Confirm Password',
buttonCreateAdmin: 'Create Admin',
},
validation: {
invalidChars: 'Please only use letter and numbers',
passwordDoesNotMatch: 'Password does not match',
},
},
message: {
note: 'NOTE',
transcodingDisabled:
'Changing the transcoding configuration through the web interface is disabled for security ' +
'reasons. If you would like to change (edit or add) transcoding options, restart the server with ' +
'the %{config} configuration option.',
transcodingEnabled:
'Navidrome is currently running with %{config}, making it possible to run system ' +
'commands from the transcoding settings using the web interface. We recommend to disable it for security reasons ' +
'and only enable it when configuring Transcoding options.',
},
menu: {
library: 'Library',
settings: 'Settings',
version: 'Version %{version}',
theme: 'Theme',
personal: {
name: 'Personal',
options: {
theme: 'Theme',
language: 'Language',
},
},
},
player: {
playListsText: 'Play Queue',
openText: 'Open',
closeText: 'Close',
notContentText: 'No music',
clickToPlayText: 'Click to play',
clickToPauseText: 'Click to pause',
nextTrackText: 'Next track',
previousTrackText: 'Previous track',
reloadText: 'Reload',
volumeText: 'Volume',
toggleLyricText: 'Toggle lyric',
toggleMiniModeText: 'Minimize',
destroyText: 'Destroy',
downloadText: 'Download',
removeAudioListsText: 'Delete audio lists',
controllerTitle: '',
clickToDeleteText: `Click to delete %{name}`,
emptyLyricText: 'No lyric',
playModeText: {
order: 'In order',
orderLoop: 'Repeat',
singleLoop: 'Repeat One',
shufflePlay: 'Shuffle',
},
},
})
-127
View File
@@ -1,127 +0,0 @@
import deepmerge from 'deepmerge'
import frenchMessages from 'ra-language-french'
export default deepmerge(frenchMessages, {
languageName: 'Français',
resources: {
song: {
name: 'Piste |||| Pistes',
fields: {
title: 'Titre',
artist: 'Artiste',
album: 'Album',
path: 'Chemin',
genre: 'Genre',
compilation: 'Compilation',
duration: 'Durée',
year: 'Année',
playCount: "Nombre d'écoutes",
trackNumber: '#',
size: 'Taille',
updatedAt: 'Mise à jour',
},
actions: {
addToQueue: 'Ajouter à la file',
},
},
album: {
name: 'Album |||| Albums',
fields: {
name: 'Nom',
artist: 'Artiste',
songCount: 'Numéro de piste',
genre: 'Genre',
playCount: "Numbre d'écoutes",
compilation: 'Compilation',
duration: 'Durée',
year: 'Année',
},
actions: {
playAll: 'Lire',
playNext: 'Lire ensuite',
addToQueue: 'Ajouter à la file',
shuffle: 'Mélanger',
},
},
artist: {
name: 'Artiste |||| Artistes',
fields: {
name: 'Nom',
albumCount: "Nombre d'albums",
},
},
user: {
name: 'Utilisateur |||| Utilisateurs',
fields: {
userName: "Nom d'utilisateur",
isAdmin: 'Administrateur',
lastLoginAt: 'Dernière connexion',
updatedAt: 'Dernière mise à jour',
name: 'Nom',
},
},
player: {
name: 'Lecteur |||| Lecteurs',
fields: {
name: 'Nom',
transcodingId: 'Transcodage',
maxBitRate: 'Bitrate maximum',
client: 'Client',
userName: "Nom d'utilisateur",
lastSeen: 'Vu pour la dernière fois',
},
},
transcoding: {
name: 'Conversion |||| Conversions',
fields: {
name: 'Nom',
targetFormat: 'Format',
defaultBitRate: 'Bitrate par défaut',
command: 'Commande',
},
},
},
ra: {
auth: {
welcome1: "Merci d'avoir installé Navidrome !",
welcome2: 'Pour commencer, créez un compte administrateur',
confirmPassword: 'Confirmer votre mot de passe',
buttonCreateAdmin: 'Créer un compte administrateur',
},
validation: {
invalidChars: "Merci d'utiliser uniquement des chiffres et des lettres",
passwordDoesNotMatch: 'Les mots de passes ne correspondent pas',
},
},
menu: {
library: 'Bibliothèque',
settings: 'Paramètres',
version: 'Version%{version}',
personal: {
name: 'Paramètres personel',
options: {
theme: 'Thème',
language: 'Langue',
},
},
},
player: {
playListsText: 'File de lecture',
openText: 'Ouvrir',
closeText: 'Fermer',
clickToPlayText: 'Cliquer pour lire',
clickToPauseText: 'Cliquer pour mettre en pause',
nextTrackText: 'Morceau suivant',
previousTrackText: 'Morceau précédent',
volumeText: 'Volume',
toggleMiniModeText: 'Minimiser',
removeAudioListsText: 'Vider la liste de lecture',
clickToDeleteText: `Cliquer pour supprimer %{name}`,
playModeText: {
order: 'Ordonner',
orderLoop: 'Tout répéter',
singleLoop: 'Repéter',
shufflePlay: 'Aleatoire',
},
},
})
-22
View File
@@ -1,22 +0,0 @@
import deepmerge from 'deepmerge'
import en from './en'
import zh from './zh'
import fr from './fr'
import it from './it'
import nl from './nl'
import pt from './pt'
const addLanguages = (lang) => {
Object.keys(lang).forEach((l) => (languages[l] = deepmerge(en, lang[l])))
}
const languages = { en }
// Add new languages to the object below (please keep alphabetic sort)
addLanguages({ fr, it, nl, pt, zh })
// "Hack" to make "albumSongs" resource use the same translations as "song"
Object.keys(languages).forEach(
(k) => (languages[k].resources.albumSong = languages[k].resources.song)
)
export default languages
-128
View File
@@ -1,128 +0,0 @@
import deepmerge from 'deepmerge'
import italianMessages from 'ra-language-italian'
export default deepmerge(italianMessages, {
languageName: 'Italiano',
resources: {
song: {
name: 'Traccia |||| Tracce',
fields: {
title: 'Titolo',
artist: 'Artista',
album: 'Album',
path: 'Percorso',
genre: 'Genere',
compilation: 'Compilation',
duration: 'Durata',
year: 'Anno',
playCount: 'Riproduzioni',
trackNumber: '#',
size: 'Dimensioni',
updatedAt: 'Ultimo aggiornamento',
},
actions: {
playNow: 'Riproduci',
addToQueue: 'Aggiungi alla coda',
},
},
album: {
name: 'Album |||| Album',
fields: {
name: 'Nome',
artist: 'Artista',
songCount: 'Tracce',
genre: 'Genere',
playCount: 'Riproduzioni',
compilation: 'Compilation',
duration: 'Durata',
year: 'Anno',
},
actions: {
playAll: 'Riproduci',
playNext: 'Riproduci come successivo',
addToQueue: 'Aggiungi alla coda',
shuffle: 'Riprodici casualmente',
},
},
artist: {
name: 'Artista |||| Artisti',
fields: {
name: 'Nome',
albumCount: 'Album',
},
},
user: {
name: 'Utente |||| Utenti',
fields: {
userName: 'Utente',
isAdmin: 'Amministratore',
lastLoginAt: 'Ultimo accesso',
updatedAt: 'Ultima modifica',
name: 'Nome',
},
},
player: {
name: 'Client |||| Client',
fields: {
name: 'Nome',
transcodingId: 'Transcodifica',
maxBitRate: 'Bitrate massimo',
client: 'Applicazione',
userName: 'Utente',
lastSeen: 'Ultimo acesso',
},
},
transcoding: {
name: 'Transcodifica |||| Transcodifiche',
fields: {
name: 'Nome',
targetFormat: 'Formato',
defaultBitRate: 'Bitrate predefinito',
command: 'Comando',
},
},
},
ra: {
auth: {
welcome1: 'Grazie per aver installato Navidrome!',
welcome2: 'Per iniziare, crea un amministratore',
confirmPassword: 'Conferma la password',
buttonCreateAdmin: 'Crea amministratore',
},
validation: {
invalidChars: 'Per favore usa solo lettere e numeri',
passwordDoesNotMatch: 'Le password non coincidono',
},
},
menu: {
library: 'Libreria',
settings: 'Impostazioni',
version: 'Versione %{version}',
personal: {
name: 'Personale',
options: {
theme: 'Tema',
language: 'Lingua',
},
},
},
player: {
playListsText: 'Coda',
openText: 'Apri',
closeText: 'Chiudi',
clickToPlayText: 'Clicca per riprodurre',
clickToPauseText: 'Clicca per mettere in pausa',
nextTrackText: 'Traccia successiva',
previousTrackText: 'Traccia precedente',
volumeText: 'Volume',
toggleMiniModeText: 'Minimizza',
removeAudioListsText: 'Cancella coda',
clickToDeleteText: `Clicca per rimuovere %{name}`,
playModeText: {
order: 'In ordine',
orderLoop: 'Ripeti',
singleLoop: 'Ripeti una volta',
shufflePlay: 'Casuale',
},
},
})
-86
View File
@@ -1,86 +0,0 @@
import deepmerge from 'deepmerge'
import englishMessages from 'ra-language-dutch'
export default deepmerge(englishMessages, {
languageName: 'Nederlands',
resources: {
song: {
name: 'Nummer |||| Nummers',
fields: {
albumArtist: 'Album Artiest',
duration: 'Tijd',
trackNumber: 'Nummer #',
playCount: 'Aantal keren afgespeeld',
},
actions: {
addToQueue: 'Toevoegen aan afspeellijst',
},
},
album: {
fields: {
albumArtist: 'Album Artiest',
artist: 'Artiest',
duration: 'Tijd',
songCount: 'Nummerss',
playCount: 'Aantal keren afgespeeld',
},
actions: {
playAll: 'Afspelen',
playNext: 'Hierna afspelen',
addToQueue: 'Toevoegen aan afspeellijst',
shuffle: 'Shuffle',
},
},
},
ra: {
auth: {
welcome1: 'Bedankt voor het installeren van Navidrome!',
welcome2: 'Maak om te beginnen een beheerdersaccount',
confirmPassword: 'Bevestig wachtwoord',
buttonCreateAdmin: 'Beheerder maken',
},
validation: {
invalidChars: 'Gebruik alleen letters en cijfers',
passwordDoesNotMatch: 'Wachtwoord komt niet overeen',
},
},
menu: {
library: 'Bibliotheek',
settings: 'Instellingen',
version: 'Versie %{version}',
theme: 'Thema',
personal: {
name: 'Persoonlijk',
options: {
theme: 'Thema',
language: 'Taal',
},
},
},
player: {
playListsText: 'Afspeellijst afspelen',
openText: 'Openen',
closeText: 'Sluiten',
notContentText: 'Geen muziek',
clickToPlayText: 'Klik om af te spelen',
clickToPauseText: 'Klik om te pauzeren',
nextTrackText: 'Volgende',
previousTrackText: 'Vorige',
reloadText: 'Herladen',
volumeText: 'Volume',
toggleLyricText: 'Songtekst aan/uit',
toggleMiniModeText: 'Minimaliseren',
destroyText: 'Vernietigen',
downloadText: 'Downloaden',
removeAudioListsText: 'Audiolijsten verwijderen',
controllerTitle: '',
clickToDeleteText: `Klik om %{name} te verwijderen`,
emptyLyricText: 'Geen songtekst',
playModeText: {
order: 'In volgorde',
orderLoop: 'Herhalen',
singleLoop: 'Herhaal Eenmalig',
shufflePlay: 'Shuffle',
},
},
})
-131
View File
@@ -1,131 +0,0 @@
import deepmerge from 'deepmerge'
import portugueseMessages from 'ra-language-portuguese'
export default deepmerge(portugueseMessages, {
languageName: 'Português',
resources: {
song: {
name: 'Música |||| Músicas',
fields: {
title: 'Título',
artist: 'Artista',
album: 'Álbum',
path: 'Arquivo',
genre: 'Gênero',
compilation: 'Coletânea',
duration: 'Duração',
year: 'Ano',
playCount: 'Execuções',
trackNumber: '#',
size: 'Tamanho',
updatedAt: 'Últ. Atualização',
},
actions: {
playNow: 'Tocar agora',
addToQueue: 'Tocar por último',
},
},
album: {
name: 'Álbum |||| Álbuns',
fields: {
name: 'Nome',
artist: 'Artista',
songCount: 'Músicas',
genre: 'Gênero',
playCount: 'Execuções',
compilation: 'Coletânea',
duration: 'Duração',
year: 'Ano',
},
actions: {
playAll: 'Tocar',
playNext: 'Tocar em seguida',
addToQueue: 'Tocar no fim',
shuffle: 'Aleatório',
},
},
artist: {
name: 'Artista |||| Artistas',
fields: {
name: 'Nome',
albumCount: 'Total de Álbuns',
},
},
user: {
name: 'Usuário |||| Usuários',
fields: {
userName: 'Usuário',
isAdmin: 'Admin?',
lastLoginAt: 'Últ. Login',
updatedAt: 'Últ. Atualização',
name: 'Nome',
},
},
player: {
name: 'Tocador |||| Tocadores',
fields: {
name: 'Nome',
transcodingId: 'Conversão',
maxBitRate: 'Bitrate máx',
client: 'Cliente',
userName: 'Usuário',
lastSeen: 'Últ. acesso',
},
},
transcoding: {
name: 'Conversão |||| Conversões',
fields: {
name: 'Nome',
targetFormat: 'Formato',
defaultBitRate: 'Bitrate padrão',
command: 'Comando',
},
},
},
ra: {
auth: {
welcome1: 'Obrigado por instalar Navidrome!',
welcome2: 'Para iniciar, crie um usuário admin',
confirmPassword: 'Confirme a senha',
buttonCreateAdmin: 'Criar Admin',
},
validation: {
invalidChars: 'Somente use letras e numeros',
passwordDoesNotMatch: 'Senha não confere',
},
page: {
create: 'Criar %{name}',
},
},
menu: {
library: 'Biblioteca',
settings: 'Configurações',
version: 'Versão %{version}',
personal: {
name: 'Pessoal',
options: {
theme: 'Tema',
language: 'Língua',
},
},
},
player: {
playListsText: 'Fila de Execução',
openText: 'Abrir',
closeText: 'Fechar',
clickToPlayText: 'Clique para tocar',
clickToPauseText: 'Clique para pausar',
nextTrackText: 'Próxima faixa',
previousTrackText: 'Faixa anterior',
volumeText: 'Volume',
toggleMiniModeText: 'Minimizar',
removeAudioListsText: 'Limpar fila de execução',
clickToDeleteText: `Clique para remover %{name}`,
playModeText: {
order: 'Em ordem',
orderLoop: 'Repetir tudo',
singleLoop: 'Repetir',
shufflePlay: 'Aleatório',
},
},
})
-136
View File
@@ -1,136 +0,0 @@
import deepmerge from 'deepmerge'
import chineseMessages from 'ra-language-chinese'
export default deepmerge(chineseMessages, {
languageName: '简体中文',
resources: {
song: {
name: '歌曲 |||| 曲库',
fields: {
title: '标题',
artist: '歌手',
album: '专辑',
path: '路径',
genre: '类型',
compilation: '收录',
albumArtist: '专辑歌手',
duration: '时长',
year: '年份',
playCount: '播放次数',
trackNumber: '音轨 #',
size: '大小',
updatedAt: '上次更新',
},
actions: {
addToQueue: '稍后播放',
},
},
album: {
name: '专辑 |||| 专辑',
fields: {
name: '名称',
albumArtist: '专辑歌手',
artist: '歌手',
duration: '时长',
songCount: '曲目数',
playCount: '播放次数',
compilation: '合辑',
year: '年份',
},
actions: {
playAll: '播放',
playNext: '播放下一首',
addToQueue: '稍后播放',
shuffle: '刷新',
},
},
artist: {
name: '歌手 |||| 歌手',
fields: {
name: '名称',
albumCount: '歌手数',
},
},
user: {
name: '用户 |||| 用户',
fields: {
userName: '用户名',
isAdmin: '管理员',
lastLoginAt: '最后一次访问',
updatedAt: '上次修改',
name: '名称',
},
},
player: {
name: '用户 |||| 用户',
fields: {
name: '名称',
transcodingId: '转码',
maxBitRate: '最大比特率',
client: '应用程序',
userName: '用户',
lastSeen: '最后一次访问',
},
},
transcoding: {
name: '转码 |||| 转码',
fields: {
name: '名称',
targetFormat: '格式',
defaultBitRate: '默认比特率',
command: '命令',
},
},
},
ra: {
auth: {
welcome1: '感谢您安装Navidrome!',
welcome2: '为了开始使用,请创建一个管理员账户',
confirmPassword: '确认密码',
buttonCreateAdmin: '创建管理员',
},
validation: {
invalidChars: '请只使用字母和数字',
passwordDoesNotMatch: '密码不匹配',
},
},
menu: {
library: '曲库',
settings: '设置',
version: '版本 %{version}',
theme: '主题',
personal: {
name: '个性化',
options: {
theme: '主题',
language: '语言',
},
},
},
player: {
playListsText: '播放队列',
openText: '打开',
closeText: '关闭',
notContentText: '无音乐',
clickToPlayText: '点击播放',
clickToPauseText: '点击暂停',
nextTrackText: '下一首',
previousTrackText: '上一首',
reloadText: 'Reload',
volumeText: '音量',
toggleLyricText: '切换歌词',
toggleMiniModeText: '最小化',
destroyText: '损坏',
downloadText: '下载',
removeAudioListsText: '清空播放列表',
controllerTitle: '',
clickToDeleteText: `点击删除 %{name}`,
emptyLyricText: '无歌词',
playModeText: {
order: '顺序播放',
orderLoop: '列表循环',
singleLoop: '单曲循环',
shufflePlay: '随机播放',
},
},
})
+258
View File
@@ -0,0 +1,258 @@
{
"languageName": "English",
"resources": {
"song": {
"name": "Song |||| Songs",
"fields": {
"albumArtist": "Album Artist",
"duration": "Time",
"trackNumber": "Track #",
"playCount": "Plays",
"title": "Title",
"artist": "Artist",
"album": "Album",
"path": "File path",
"genre": "Genre",
"compilation": "Compilation",
"year": "Year",
"size": "File size",
"updatedAt": "Uploaded at"
},
"actions": {
"addToQueue": "Play Later"
},
"action": {
"playNow": "Play Now"
}
},
"album": {
"name": "Album |||| Albums",
"fields": {
"albumArtist": "Album Artist",
"artist": "Artist",
"duration": "Time",
"songCount": "Songs",
"playCount": "Plays",
"name": "Name",
"genre": "Genre",
"compilation": "Compilation",
"year": "Year"
},
"actions": {
"playAll": "Play",
"playNext": "Play Next",
"addToQueue": "Play Later",
"shuffle": "Shuffle"
}
},
"artist": {
"name": "Artist |||| Artists",
"fields": {
"name": "Name",
"albumCount": "Album Count"
}
},
"user": {
"name": "User |||| Users",
"fields": {
"userName": "Username",
"isAdmin": "Is Admin",
"lastLoginAt": "Last Login At",
"updatedAt": "Updated At",
"name": "Name"
}
},
"player": {
"name": "Player |||| Players",
"fields": {
"name": "Name",
"transcodingId": "Transcoding ID",
"maxBitRate": "Max. Bit Rate",
"client": "Client",
"userName": "Username",
"lastSeen": "Last Seen At"
}
},
"transcoding": {
"name": "Transcoding |||| Transcodings",
"fields": {
"name": "Name",
"targetFormat": "Target Format",
"defaultBitRate": "Default Bit Rate",
"command": "Command"
}
}
},
"ra": {
"auth": {
"welcome1": "Thanks for installing Navidrome!",
"welcome2": "To start, create an admin user",
"confirmPassword": "Confirm Password",
"buttonCreateAdmin": "Create Admin",
"auth_check_error": "Please login to continue",
"user_menu": "Profile",
"username": "Username",
"password": "Password",
"sign_in": "Sign in",
"sign_in_error": "Authentication failed, please retry",
"logout": "Logout"
},
"validation": {
"invalidChars": "Please only use letter and numbers",
"passwordDoesNotMatch": "Password does not match",
"required": "Required",
"minLength": "Must be %{min} characters at least",
"maxLength": "Must be %{max} characters or less",
"minValue": "Must be at least %{min}",
"maxValue": "Must be %{max} or less",
"number": "Must be a number",
"email": "Must be a valid email",
"oneOf": "Must be one of: %{options}",
"regex": "Must match a specific format (regexp): %{pattern}"
},
"action": {
"add_filter": "Add filter",
"add": "Add",
"back": "Go Back",
"bulk_actions": "1 item selected |||| %{smart_count} items selected",
"cancel": "Cancel",
"clear_input_value": "Clear value",
"clone": "Clone",
"confirm": "Confirm",
"create": "Create",
"delete": "Delete",
"edit": "Edit",
"export": "Export",
"list": "List",
"refresh": "Refresh",
"remove_filter": "Remove this filter",
"remove": "Remove",
"save": "Save",
"search": "Search",
"show": "Show",
"sort": "Sort",
"undo": "Undo",
"expand": "Expand",
"close": "Close",
"open_menu": "Open menu",
"close_menu": "Close menu"
},
"boolean": {
"true": "Yes",
"false": "No"
},
"page": {
"create": "Create %{name}",
"dashboard": "Dashboard",
"edit": "%{name} #%{id}",
"error": "Something went wrong",
"list": "%{name}",
"loading": "Loading",
"not_found": "Not Found",
"show": "%{name} #%{id}",
"empty": "No %{name} yet.",
"invite": "Do you want to add one?"
},
"input": {
"file": {
"upload_several": "Drop some files to upload, or click to select one.",
"upload_single": "Drop a file to upload, or click to select it."
},
"image": {
"upload_several": "Drop some pictures to upload, or click to select one.",
"upload_single": "Drop a picture to upload, or click to select it."
},
"references": {
"all_missing": "Unable to find references data.",
"many_missing": "At least one of the associated references no longer appears to be available.",
"single_missing": "Associated reference no longer appears to be available."
},
"password": {
"toggle_visible": "Hide password",
"toggle_hidden": "Show password"
}
},
"message": {
"about": "About",
"are_you_sure": "Are you sure?",
"bulk_delete_content": "Are you sure you want to delete this %{name}? |||| Are you sure you want to delete these %{smart_count} items?",
"bulk_delete_title": "Delete %{name} |||| Delete %{smart_count} %{name}",
"delete_content": "Are you sure you want to delete this item?",
"delete_title": "Delete %{name} #%{id}",
"details": "Details",
"error": "A client error occurred and your request couldn't be completed.",
"invalid_form": "The form is not valid. Please check for errors",
"loading": "The page is loading, just a moment please",
"no": "No",
"not_found": "Either you typed a wrong URL, or you followed a bad link.",
"yes": "Yes",
"unsaved_changes": "Some of your changes weren't saved. Are you sure you want to ignore them?"
},
"navigation": {
"no_results": "No results found",
"no_more_results": "The page number %{page} is out of boundaries. Try the previous page.",
"page_out_of_boundaries": "Page number %{page} out of boundaries",
"page_out_from_end": "Cannot go after last page",
"page_out_from_begin": "Cannot go before page 1",
"page_range_info": "%{offsetBegin}-%{offsetEnd} of %{total}",
"page_rows_per_page": "Rows per page:",
"next": "Next",
"prev": "Prev"
},
"notification": {
"updated": "Element updated |||| %{smart_count} elements updated",
"created": "Element created",
"deleted": "Element deleted |||| %{smart_count} elements deleted",
"bad_item": "Incorrect element",
"item_doesnt_exist": "Element does not exist",
"http_error": "Server communication error",
"data_provider_error": "dataProvider error. Check the console for details.",
"i18n_error": "Cannot load the translations for the specified language",
"canceled": "Action cancelled",
"logged_out": "Your session has ended, please reconnect."
}
},
"message": {
"note": "NOTE",
"transcodingDisabled": "Changing the transcoding configuration through the web interface is disabled for security reasons. If you would like to change (edit or add) transcoding options, restart the server with the %{config} configuration option.",
"transcodingEnabled": "Navidrome is currently running with %{config}, making it possible to run system commands from the transcoding settings using the web interface. We recommend to disable it for security reasons and only enable it when configuring Transcoding options."
},
"menu": {
"library": "Library",
"settings": "Settings",
"version": "Version %{version}",
"theme": "Theme",
"personal": {
"name": "Personal",
"options": {
"theme": "Theme",
"language": "Language"
}
}
},
"player": {
"playListsText": "Play Queue",
"openText": "Open",
"closeText": "Close",
"notContentText": "No music",
"clickToPlayText": "Click to play",
"clickToPauseText": "Click to pause",
"nextTrackText": "Next track",
"previousTrackText": "Previous track",
"reloadText": "Reload",
"volumeText": "Volume",
"toggleLyricText": "Toggle lyric",
"toggleMiniModeText": "Minimize",
"destroyText": "Destroy",
"downloadText": "Download",
"removeAudioListsText": "Delete audio lists",
"clickToDeleteText": "Click to delete %{name}",
"emptyLyricText": "No lyric",
"playModeText": {
"order": "In order",
"orderLoop": "Repeat",
"singleLoop": "Repeat One",
"shufflePlay": "Shuffle"
}
}
}
+28
View File
@@ -0,0 +1,28 @@
import polyglotI18nProvider from 'ra-i18n-polyglot'
import dataProvider from '../dataProvider'
import en from './en.json'
const defaultLocale = function () {
const locale = localStorage.getItem('locale')
const current = JSON.parse(localStorage.getItem('translation'))
if (current && current.id === locale) {
return locale
}
return 'en'
}
const i18nProvider = polyglotI18nProvider((locale) => {
if (locale === 'en') {
return en
}
const current = JSON.parse(localStorage.getItem('translation'))
if (current && current.id === locale) {
return JSON.parse(current.data)
}
return dataProvider.getOne('translation', { id: locale }).then((res) => {
localStorage.setItem('translation', JSON.stringify(res.data))
return JSON.parse(res.data.data)
})
}, defaultLocale())
export default i18nProvider
+23 -10
View File
@@ -2,18 +2,18 @@ import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Card } from '@material-ui/core'
import {
Title,
SimpleForm,
SelectInput,
useTranslate,
useSetLocale,
SimpleForm,
Title,
useGetList,
useLocale,
useSetLocale,
useTranslate,
} from 'react-admin'
import { makeStyles } from '@material-ui/core/styles'
import HelpOutlineIcon from '@material-ui/icons/HelpOutline'
import { changeTheme } from './actions'
import themes from '../themes'
import i18n from '../i18n'
import { docsUrl } from '../utils/docsUrl'
const useStyles = makeStyles({
@@ -35,23 +35,35 @@ const HelpMsg = ({ caption }) => (
)
const SelectLanguage = (props) => {
const { ids, data, loaded } = useGetList(
'translation',
{ page: 1, perPage: -1 },
{ field: '', order: '' },
{}
)
const translate = useTranslate()
const locale = useLocale()
const setLocale = useSetLocale()
const langChoices = Object.keys(i18n).map((key) => {
return { id: key, name: i18n[key].languageName }
})
const locale = useLocale()
const langChoices = [{ id: 'en', name: 'English' }]
if (loaded) {
ids.forEach((id) => langChoices.push({ id: id, name: data[id].name }))
}
langChoices.sort((a, b) => a.name.localeCompare(b.name))
langChoices.push({
id: helpKey,
name: <HelpMsg caption={'Help to translate'} />,
})
return (
<SelectInput
{...props}
source="lamguage"
source="language"
label={translate('menu.personal.options.language')}
defaultValue={locale}
choices={langChoices}
translateChoice={false}
onChange={(event) => {
if (event.target.value === helpKey) {
openInNewTab(docsUrl('/docs/developers/translations/'))
@@ -81,6 +93,7 @@ const SelectTheme = (props) => {
source="theme"
label={translate('menu.personal.options.theme')}
defaultValue={currentTheme}
translateChoice={false}
choices={themeChoices}
onChange={(event) => {
if (event.target.value === helpKey) {