mirror of
https://github.com/navidrome/navidrome.git
synced 2026-01-21 05:08:15 -05:00
Compare commits
9 Commits
update-tra
...
plugins-js
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
678efed9b3 | ||
|
|
f3532ec9e6 | ||
|
|
fa016528c4 | ||
|
|
6a57fd71cf | ||
|
|
2fb383b58a | ||
|
|
6fce30c133 | ||
|
|
6c7f8314e2 | ||
|
|
37aa54fe06 | ||
|
|
fae58bb390 |
6
go.mod
6
go.mod
@@ -59,14 +59,14 @@ require (
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/sirupsen/logrus v1.9.4
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/spf13/viper v1.21.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/tetratelabs/wazero v1.11.0
|
||||
github.com/unrolled/secure v1.17.0
|
||||
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342
|
||||
go.senan.xyz/taglib v0.0.0-00010101000000-000000000000
|
||||
go.senan.xyz/taglib v0.11.1
|
||||
go.uber.org/goleak v1.3.0
|
||||
golang.org/x/image v0.35.0
|
||||
golang.org/x/net v0.49.0
|
||||
@@ -98,7 +98,7 @@ require (
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20260111202518-71be6bfdd440 // indirect
|
||||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect
|
||||
github.com/google/subcommands v1.2.0 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
|
||||
10
go.sum
10
go.sum
@@ -110,8 +110,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-pipeline v0.0.0-20230411140531-6cbedfc1d3fc h1:hd+uUVsB1vdxohPneMrhGH2YfQuH5hRIK9u4/XCeUtw=
|
||||
github.com/google/go-pipeline v0.0.0-20230411140531-6cbedfc1d3fc/go.mod h1:SL66SJVysrh7YbDCP9tH30b8a9o/N2HeiQNUm85EKhc=
|
||||
github.com/google/pprof v0.0.0-20260111202518-71be6bfdd440 h1:oKBqR+eQXiIM7X8K1JEg9aoTEePLq/c6Awe484abOuA=
|
||||
github.com/google/pprof v0.0.0-20260111202518-71be6bfdd440/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
|
||||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc=
|
||||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
|
||||
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
|
||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
@@ -245,8 +245,8 @@ github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr
|
||||
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
|
||||
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
@@ -275,7 +275,6 @@ github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRci
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
@@ -364,7 +363,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
||||
@@ -4,10 +4,10 @@ go 1.25
|
||||
|
||||
require (
|
||||
github.com/extism/go-pdk v1.1.3
|
||||
github.com/onsi/ginkgo/v2 v2.27.3
|
||||
github.com/onsi/gomega v1.38.3
|
||||
github.com/onsi/ginkgo/v2 v2.27.5
|
||||
github.com/onsi/gomega v1.39.0
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
|
||||
golang.org/x/tools v0.40.0
|
||||
golang.org/x/tools v0.41.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
@@ -16,11 +16,11 @@ require (
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
|
||||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/mod v0.31.0 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
golang.org/x/mod v0.32.0 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
)
|
||||
|
||||
@@ -20,8 +20,8 @@ github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc=
|
||||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
|
||||
github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE=
|
||||
github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
@@ -32,10 +32,10 @@ github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo=
|
||||
github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
|
||||
github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE=
|
||||
github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A=
|
||||
github.com/onsi/ginkgo/v2 v2.27.3 h1:ICsZJ8JoYafeXFFlFAG75a7CxMsJHwgKwtO+82SE9L8=
|
||||
github.com/onsi/ginkgo/v2 v2.27.3/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
|
||||
github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM=
|
||||
github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
|
||||
github.com/onsi/ginkgo/v2 v2.27.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE=
|
||||
github.com/onsi/ginkgo/v2 v2.27.5/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
|
||||
github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q=
|
||||
github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
@@ -54,18 +54,18 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
||||
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"type": "array",
|
||||
"title": "User Tokens",
|
||||
"description": "Discord tokens for each Navidrome user. WARNING: Store tokens securely!",
|
||||
"default": [{}],
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -63,7 +63,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["clientid"]
|
||||
"required": ["clientid", "users"]
|
||||
},
|
||||
"uiSchema": {
|
||||
"type": "VerticalLayout",
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
"type": "array",
|
||||
"title": "User Tokens",
|
||||
"description": "Discord tokens for each Navidrome user. WARNING: Store tokens securely!",
|
||||
"default": [{}],
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -67,7 +67,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["clientid"]
|
||||
"required": ["clientid", "users"]
|
||||
},
|
||||
"uiSchema": {
|
||||
"type": "VerticalLayout",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,8 +36,7 @@
|
||||
"bitDepth": "Λίγο βάθος",
|
||||
"sampleRate": "Ποσοστό δειγματοληψίας",
|
||||
"missing": "Απών",
|
||||
"libraryName": "Βιβλιοθήκη",
|
||||
"composer": "Συνθέτης"
|
||||
"libraryName": "Βιβλιοθήκη"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "Αναπαραγωγη Μετα",
|
||||
@@ -329,80 +328,6 @@
|
||||
"scanInProgress": "Σάρωση σε εξέλιξη...",
|
||||
"noLibrariesAssigned": "Δεν έχουν αντιστοιχιστεί βιβλιοθήκες σε αυτόν τον χρήστη"
|
||||
}
|
||||
},
|
||||
"plugin": {
|
||||
"name": "Πρόσθετο |||| Πρόσθετα",
|
||||
"fields": {
|
||||
"id": "ID",
|
||||
"name": "Όνομα",
|
||||
"description": "Περιγραφή",
|
||||
"version": "Έκδοση",
|
||||
"author": "Καλλιτέχνης",
|
||||
"website": "Ιστοσελίδα",
|
||||
"permissions": "Άδειες",
|
||||
"enabled": "Ενεργό",
|
||||
"status": "Κατάσταση",
|
||||
"path": "Διαδρομή",
|
||||
"lastError": "Σφάλμα",
|
||||
"hasError": "Σφάλμα",
|
||||
"updatedAt": "Ενημερώθηκε",
|
||||
"createdAt": "Εγκατασταθηκε",
|
||||
"configKey": "Κλειδί",
|
||||
"configValue": "Τιμή",
|
||||
"allUsers": "Επιτρέψτε όλους τους χρήστες",
|
||||
"selectedUsers": "Επιλογή χρηστών",
|
||||
"allLibraries": "Επιτρέψτε όλες τις βιβλιοθήκες",
|
||||
"selectedLibraries": "Επιλεγμένες βιβλιοθήκες"
|
||||
},
|
||||
"sections": {
|
||||
"status": "Κατάσταση",
|
||||
"info": "Πληροφορίες Πρόσθετου",
|
||||
"configuration": "Παραμετροποίηση",
|
||||
"manifest": "Manifest",
|
||||
"usersPermission": "Άδειες Χρηστών",
|
||||
"libraryPermission": "Άδειες Βιβλιοθηκών"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Ενεργό",
|
||||
"disabled": "Ανενεργό"
|
||||
},
|
||||
"actions": {
|
||||
"enable": "Ενεργοποίηση",
|
||||
"disable": "Απενεργοποίηση",
|
||||
"disabledDueToError": "Διορθώστε το σφάλμα πριν την ενεργοποίηση",
|
||||
"disabledUsersRequired": "Επιλέξτε χρήστες πριν την ενεργοποίηση",
|
||||
"disabledLibrariesRequired": "Επιλέξτε βιβλιοθήκες πριν την ενεργοποίηση",
|
||||
"addConfig": "Προσθήκη παραμετροποίησης",
|
||||
"rescan": "Σάρωση ξανά"
|
||||
},
|
||||
"notifications": {
|
||||
"enabled": "Πρόσθετο ενεργοποιημένο",
|
||||
"disabled": "Πρόσθετο απενεργοποιημένο",
|
||||
"updated": "Πρόσθετο ενημερωμένο",
|
||||
"error": "Σφάλμα κατά την ενημέρωση του πρόσθετου"
|
||||
},
|
||||
"validation": {
|
||||
"invalidJson": "Η παραμετροποίηση πρέπει να είναι συμβατό JSON"
|
||||
},
|
||||
"messages": {
|
||||
"configHelp": "Παραμετροποιήστε το πρόσθετο με χρήση ζεύγων κλειδιών-τιμών. Αφήστε κενό αν το πρόσθετο δεν απαιτεί παραμετροποίηση",
|
||||
"clickPermissions": "Κάνετε κλικ για λεπτομέρειες αδειών",
|
||||
"noConfig": "Δεν ορίστηκε παραμετροποίηση",
|
||||
"allUsersHelp": "Όταν είναι ενεργό, το πρόσθετο θα έχει πρόσβαση σε όλους τους χρήστες, συμπεριλαμβανομένων και όσων δημιουργηθούν στο μέλλον.",
|
||||
"noUsers": "Δεν επιλέχθηκαν χρήστες",
|
||||
"permissionReason": "Αιτία",
|
||||
"usersRequired": "Το πρόσθετο απαιτεί πρόσβαση στις πληροφορίες χρηστών. Ορίστε τους χρήστες που θα έχει πρόσβαση το πρόσθετο, ή ενεργοποιήστε το 'Επιτρέψτε όλους τους χρήστες'",
|
||||
"allLibrariesHelp": "Όταν είναι ενεργό, το πρόσθετο θα έχει πρόσβαση σε όλες τις βιβλιοθήκες, συμπεριλαμβανομένων και όσων δημιουργηθούν στο μέλλον.",
|
||||
"noLibraries": "Δεν επιλέχθηκαν βιβλιοθήκες",
|
||||
"librariesRequired": "Αυτό το πρόσθετο απαιτεί πρόσβαση στις πληροφορίες βιβλιοθήκης. Επιλέξτε σε ποιές βιβλιοθήκες μπορεί να έχει πρόσβαση το πρόσθετο, ή ενεργοποιήστε το 'Επιτρέψτε όλες τις βιβλιοθήκες'",
|
||||
"requiredHosts": "Απαιτούμενοι hosts",
|
||||
"configValidationError": "",
|
||||
"schemaRenderError": ""
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "κλειδί",
|
||||
"configValue": "τιμή"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ra": {
|
||||
|
||||
@@ -12,12 +12,16 @@
|
||||
"artist": "Artista",
|
||||
"album": "Álbum",
|
||||
"path": "Ruta del archivo",
|
||||
"libraryName": "Biblioteca",
|
||||
"genre": "Género",
|
||||
"compilation": "Compilación",
|
||||
"year": "Año",
|
||||
"size": "Tamaño del archivo",
|
||||
"updatedAt": "Actualizado el",
|
||||
"bitRate": "Tasa de bits",
|
||||
"bitDepth": "Profundidad de bits",
|
||||
"sampleRate": "Frecuencia de muestreo",
|
||||
"channels": "Canales",
|
||||
"discSubtitle": "Subtítulo del disco",
|
||||
"starred": "Favorito",
|
||||
"comment": "Comentario",
|
||||
@@ -25,7 +29,6 @@
|
||||
"quality": "Calidad",
|
||||
"bpm": "BPM",
|
||||
"playDate": "Últimas reproducciones",
|
||||
"channels": "Canales",
|
||||
"createdAt": "Creado el",
|
||||
"grouping": "Agrupación",
|
||||
"mood": "Estado de ánimo",
|
||||
@@ -33,21 +36,17 @@
|
||||
"tags": "Etiquetas",
|
||||
"mappedTags": "Etiquetas asignadas",
|
||||
"rawTags": "Etiquetas sin procesar",
|
||||
"bitDepth": "Profundidad de bits",
|
||||
"sampleRate": "Frecuencia de muestreo",
|
||||
"missing": "Faltante",
|
||||
"libraryName": "Biblioteca",
|
||||
"composer": "Compositor"
|
||||
"missing": "Faltante"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "Reproducir después",
|
||||
"playNow": "Reproducir ahora",
|
||||
"addToPlaylist": "Agregar a la playlist",
|
||||
"showInPlaylist": "Mostrar en la lista de reproducción",
|
||||
"shuffleAll": "Todas aleatorias",
|
||||
"download": "Descarga",
|
||||
"playNext": "Siguiente",
|
||||
"info": "Obtener información",
|
||||
"showInPlaylist": "Mostrar en la lista de reproducción"
|
||||
"info": "Obtener información"
|
||||
}
|
||||
},
|
||||
"album": {
|
||||
@@ -58,38 +57,38 @@
|
||||
"duration": "Duración",
|
||||
"songCount": "Canciones",
|
||||
"playCount": "Reproducciones",
|
||||
"size": "Tamaño del archivo",
|
||||
"name": "Nombre",
|
||||
"libraryName": "Biblioteca",
|
||||
"genre": "Género",
|
||||
"compilation": "Compilación",
|
||||
"year": "Año",
|
||||
"updatedAt": "Actualizado el",
|
||||
"comment": "Comentario",
|
||||
"rating": "Calificación",
|
||||
"createdAt": "Creado el",
|
||||
"size": "Tamaño del archivo",
|
||||
"date": "Fecha de grabación",
|
||||
"originalDate": "Original",
|
||||
"releaseDate": "Publicado",
|
||||
"releases": "Lanzamiento |||| Lanzamientos",
|
||||
"released": "Publicado",
|
||||
"updatedAt": "Actualizado el",
|
||||
"comment": "Comentario",
|
||||
"rating": "Calificación",
|
||||
"createdAt": "Creado el",
|
||||
"recordLabel": "Discográfica",
|
||||
"catalogNum": "Número de catálogo",
|
||||
"releaseType": "Tipo de lanzamiento",
|
||||
"grouping": "Agrupación",
|
||||
"media": "Medios",
|
||||
"mood": "Estado de ánimo",
|
||||
"date": "Fecha de grabación",
|
||||
"missing": "Faltante",
|
||||
"libraryName": "Biblioteca"
|
||||
"missing": "Faltante"
|
||||
},
|
||||
"actions": {
|
||||
"playAll": "Reproducir",
|
||||
"playNext": "Reproducir siguiente",
|
||||
"addToQueue": "Reproducir después",
|
||||
"share": "Compartir",
|
||||
"shuffle": "Aleatorio",
|
||||
"addToPlaylist": "Agregar a la lista",
|
||||
"download": "Descargar",
|
||||
"info": "Obtener información",
|
||||
"share": "Compartir"
|
||||
"info": "Obtener información"
|
||||
},
|
||||
"lists": {
|
||||
"all": "Todos",
|
||||
@@ -107,10 +106,10 @@
|
||||
"name": "Nombre",
|
||||
"albumCount": "Número de álbumes",
|
||||
"songCount": "Número de canciones",
|
||||
"size": "Tamaño",
|
||||
"playCount": "Reproducciones",
|
||||
"rating": "Calificación",
|
||||
"genre": "Género",
|
||||
"size": "Tamaño",
|
||||
"role": "Rol",
|
||||
"missing": "Faltante"
|
||||
},
|
||||
@@ -131,9 +130,9 @@
|
||||
"maincredit": "Artista del álbum o Artista |||| Artistas del álbum o Artistas"
|
||||
},
|
||||
"actions": {
|
||||
"topSongs": "Más destacadas",
|
||||
"shuffle": "Aleatorio",
|
||||
"radio": "Radio",
|
||||
"topSongs": "Más destacadas"
|
||||
"radio": "Radio"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
@@ -142,6 +141,7 @@
|
||||
"userName": "Nombre de usuario",
|
||||
"isAdmin": "Es administrador",
|
||||
"lastLoginAt": "Último inicio de sesión",
|
||||
"lastAccessAt": "Último acceso",
|
||||
"updatedAt": "Actualizado el",
|
||||
"name": "Nombre",
|
||||
"password": "Contraseña",
|
||||
@@ -150,7 +150,6 @@
|
||||
"currentPassword": "Contraseña actual",
|
||||
"newPassword": "Nueva contraseña",
|
||||
"token": "Token",
|
||||
"lastAccessAt": "Último acceso",
|
||||
"libraries": "Bibliotecas"
|
||||
},
|
||||
"helperTexts": {
|
||||
@@ -212,9 +211,9 @@
|
||||
"selectPlaylist": "Seleccione una lista:",
|
||||
"addNewPlaylist": "Creada \"%{name}\"",
|
||||
"export": "Exportar",
|
||||
"saveQueue": "Guardar la fila de reproducción en una playlist",
|
||||
"makePublic": "Hazla pública",
|
||||
"makePrivate": "Hazla privada",
|
||||
"saveQueue": "Guardar la fila de reproducción en una playlist",
|
||||
"searchOrCreate": "Buscar listas de reproducción o escribe para crear una nueva…",
|
||||
"pressEnterToCreate": "Pulsa Enter para crear una nueva lista de reproducción",
|
||||
"removeFromSelection": "Quitar de la selección"
|
||||
@@ -245,6 +244,7 @@
|
||||
"username": "Compartido por",
|
||||
"url": "URL",
|
||||
"description": "Descripción",
|
||||
"downloadable": "¿Permitir descargas?",
|
||||
"contents": "Contenido",
|
||||
"expiresAt": "Caduca el",
|
||||
"lastVisitedAt": "Visitado por última vez el",
|
||||
@@ -252,12 +252,14 @@
|
||||
"format": "Formato",
|
||||
"maxBitRate": "Tasa de bits Máx.",
|
||||
"updatedAt": "Actualizado el",
|
||||
"createdAt": "Creado el",
|
||||
"downloadable": "¿Permitir descargas?"
|
||||
}
|
||||
"createdAt": "Creado el"
|
||||
},
|
||||
"notifications": {},
|
||||
"actions": {}
|
||||
},
|
||||
"missing": {
|
||||
"name": "Fichero faltante |||| Ficheros faltantes",
|
||||
"empty": "No faltan archivos",
|
||||
"fields": {
|
||||
"path": "Ruta",
|
||||
"size": "Tamaño",
|
||||
@@ -270,8 +272,7 @@
|
||||
},
|
||||
"notifications": {
|
||||
"removed": "Eliminado"
|
||||
},
|
||||
"empty": "No faltan archivos"
|
||||
}
|
||||
},
|
||||
"library": {
|
||||
"name": "Biblioteca |||| Bibliotecas",
|
||||
@@ -301,20 +302,20 @@
|
||||
},
|
||||
"actions": {
|
||||
"scan": "Escanear biblioteca",
|
||||
"manageUsers": "Gestionar el acceso de usarios",
|
||||
"viewDetails": "Ver detalles",
|
||||
"quickScan": "Escaneo rápido",
|
||||
"fullScan": "Escaneo completo"
|
||||
"fullScan": "Escaneo completo",
|
||||
"manageUsers": "Gestionar el acceso de usarios",
|
||||
"viewDetails": "Ver detalles"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "La biblioteca se creó correctamente",
|
||||
"updated": "La biblioteca se actualizó correctamente",
|
||||
"deleted": "La biblioteca se eliminó correctamente",
|
||||
"scanStarted": "El escaneo de la biblioteca ha comenzado",
|
||||
"scanCompleted": "El escaneo de la biblioteca se completó",
|
||||
"quickScanStarted": "Escaneo rápido ha comenzado",
|
||||
"fullScanStarted": "Escaneo completo ha comenzado",
|
||||
"scanError": "Error al iniciar el escaneo. Revisa los registros"
|
||||
"scanError": "Error al iniciar el escaneo. Revisa los registros",
|
||||
"scanCompleted": "El escaneo de la biblioteca se completó"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "El nombre de la biblioteca es obligatorio",
|
||||
@@ -395,9 +396,7 @@
|
||||
"allLibrariesHelp": "Cuando se active, el plugin tendrá acceso a todas las bibliotecas, incluidas las que se creen en el futuro.",
|
||||
"noLibraries": "Ninguna biblioteca seleccionada",
|
||||
"librariesRequired": "Este plugin requiere acceso a la información de las bibliotecas. Selecciona a qué bibliotecas puede acceder el plugin, o activa 'Permitir todas las bibliotecas'.",
|
||||
"requiredHosts": "Hosts requeridos",
|
||||
"configValidationError": "",
|
||||
"schemaRenderError": ""
|
||||
"requiredHosts": "Hosts requeridos"
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "clave",
|
||||
@@ -440,6 +439,7 @@
|
||||
"add": "Añadir",
|
||||
"back": "Ir atrás",
|
||||
"bulk_actions": "1 elemento seleccionado |||| %{smart_count} elementos seleccionados",
|
||||
"bulk_actions_mobile": "1 |||| %{smart_count}",
|
||||
"cancel": "Cancelar",
|
||||
"clear_input_value": "Limpiar valor",
|
||||
"clone": "Duplicar",
|
||||
@@ -463,7 +463,6 @@
|
||||
"close_menu": "Cerrar menú",
|
||||
"unselect": "Deseleccionado",
|
||||
"skip": "Omitir",
|
||||
"bulk_actions_mobile": "1 |||| %{smart_count}",
|
||||
"share": "Compartir",
|
||||
"download": "Descargar"
|
||||
},
|
||||
@@ -555,41 +554,47 @@
|
||||
"transcodingDisabled": "Cambiar la configuración de la transcodificación a través de la interfaz web esta deshabilitado por motivos de seguridad. Si quieres cambiar (editar o agregar) opciones de transcodificación, reinicia el servidor con la %{config} opción de configuración.",
|
||||
"transcodingEnabled": "Navidrom se esta ejecutando con %{config}, lo que hace posible ejecutar comandos de sistema desde el apartado de transcodificación en la interfaz web. Recomendamos deshabilitarlo por motivos de seguridad y solo habilitarlo cuando se este configurando opciones de transcodificación.",
|
||||
"songsAddedToPlaylist": "1 canción agregada a la lista |||| %{smart_count} canciones agregadas a la lista",
|
||||
"noSimilarSongsFound": "No se encontraron canciones similares",
|
||||
"noTopSongsFound": "No se encontraron canciones destacadas",
|
||||
"noPlaylistsAvailable": "Ninguna lista disponible",
|
||||
"delete_user_title": "Eliminar usuario '%{name}'",
|
||||
"delete_user_content": "¿Esta seguro de eliminar a este usuario y todos sus datos (incluyendo listas y preferencias)?",
|
||||
"remove_missing_title": "Eliminar archivos faltantes",
|
||||
"remove_missing_content": "¿Realmente desea eliminar los archivos faltantes seleccionados de la base de datos? Esto eliminará permanentemente cualquier referencia a ellos, incluidas sus reproducciones y valoraciones.",
|
||||
"remove_all_missing_title": "Eliminar todos los archivos faltantes",
|
||||
"remove_all_missing_content": "¿Realmente desea eliminar todos los archivos faltantes de la base de datos? Esto eliminará permanentemente cualquier referencia a ellos, incluidas sus reproducciones y valoraciones.",
|
||||
"notifications_blocked": "Las notificaciones de este sitio están bloqueadas en tu navegador",
|
||||
"notifications_not_available": "Este navegador no soporta notificaciones o no ingresaste a Navidrome usando https",
|
||||
"lastfmLinkSuccess": "Last.fm esta conectado y el scrobbling esta activado",
|
||||
"lastfmLinkFailure": "No se pudo conectar con Last.fm",
|
||||
"lastfmUnlinkSuccess": "Last.fm se ha desconectado y el scrobbling se desactivo",
|
||||
"lastfmUnlinkFailure": "No se pudo desconectar Last.fm",
|
||||
"listenBrainzLinkSuccess": "Se ha conectado correctamente a ListenBrainz y se activó el scrobbling como el usuario: %{user}",
|
||||
"listenBrainzLinkFailure": "No se pudo conectar con ListenBrainz: %{error}",
|
||||
"listenBrainzUnlinkSuccess": "Se desconectó ListenBrainz y se desactivó el scrobbling",
|
||||
"listenBrainzUnlinkFailure": "No se pudo desconectar ListenBrainz",
|
||||
"openIn": {
|
||||
"lastfm": "Ver en Last.fm",
|
||||
"musicbrainz": "Ver en MusicBrainz"
|
||||
},
|
||||
"lastfmLink": "Leer más...",
|
||||
"listenBrainzLinkSuccess": "Se ha conectado correctamente a ListenBrainz y se activó el scrobbling como el usuario: %{user}",
|
||||
"listenBrainzLinkFailure": "No se pudo conectar con ListenBrainz: %{error}",
|
||||
"listenBrainzUnlinkSuccess": "Se desconectó ListenBrainz y se desactivó el scrobbling",
|
||||
"listenBrainzUnlinkFailure": "No se pudo desconectar ListenBrainz",
|
||||
"downloadOriginalFormat": "Descargar formato original",
|
||||
"shareOriginalFormat": "Compartir formato original",
|
||||
"shareDialogTitle": "Compartir %{resource} '%{name}'",
|
||||
"shareBatchDialogTitle": "Compartir 1 %{resource} |||| Compartir %{smart_count} %{resource}",
|
||||
"shareCopyToClipboard": "Copiar al portapapeles: Ctrl+C, Intro",
|
||||
"shareSuccess": "URL copiada al portapapeles: %{url}",
|
||||
"shareFailure": "Error al copiar la URL %{url} al portapapeles",
|
||||
"downloadDialogTitle": "Descargar %{resource} '%{name}' (%{size})",
|
||||
"shareCopyToClipboard": "Copiar al portapapeles: Ctrl+C, Intro",
|
||||
"remove_missing_title": "Eliminar archivos faltantes",
|
||||
"remove_missing_content": "¿Realmente desea eliminar los archivos faltantes seleccionados de la base de datos? Esto eliminará permanentemente cualquier referencia a ellos, incluidas sus reproducciones y valoraciones.",
|
||||
"remove_all_missing_title": "Eliminar todos los archivos faltantes",
|
||||
"remove_all_missing_content": "¿Realmente desea eliminar todos los archivos faltantes de la base de datos? Esto eliminará permanentemente cualquier referencia a ellos, incluidas sus reproducciones y valoraciones.",
|
||||
"noSimilarSongsFound": "No se encontraron canciones similares",
|
||||
"noTopSongsFound": "No se encontraron canciones destacadas"
|
||||
"downloadOriginalFormat": "Descargar formato original"
|
||||
},
|
||||
"menu": {
|
||||
"library": "Biblioteca",
|
||||
"librarySelector": {
|
||||
"allLibraries": "Todas las bibliotecas (%{count})",
|
||||
"multipleLibraries": "%{selected} de %{total} bibliotecas",
|
||||
"selectLibraries": "Seleccionar bibliotecas",
|
||||
"none": "Ninguno"
|
||||
},
|
||||
"settings": "Ajustes",
|
||||
"version": "Versión",
|
||||
"theme": "Tema",
|
||||
@@ -600,6 +605,7 @@
|
||||
"language": "Idioma",
|
||||
"defaultView": "Vista por defecto",
|
||||
"desktop_notifications": "Notificaciones de escritorio",
|
||||
"lastfmNotConfigured": "La clave API de Last.fm no está configurada",
|
||||
"lastfmScrobbling": "Scrobble a Last.fm",
|
||||
"listenBrainzScrobbling": "Scrobble a ListenBrainz",
|
||||
"replaygain": "Modo de ReplayGain",
|
||||
@@ -608,20 +614,13 @@
|
||||
"none": "Desactivado",
|
||||
"album": "Ganancia del álbum",
|
||||
"track": "Ganancia de pista"
|
||||
},
|
||||
"lastfmNotConfigured": "La clave API de Last.fm no está configurada"
|
||||
}
|
||||
}
|
||||
},
|
||||
"albumList": "Álbumes",
|
||||
"about": "Acerca de",
|
||||
"playlists": "Playlists",
|
||||
"sharedPlaylists": "Playlists Compartidas",
|
||||
"librarySelector": {
|
||||
"allLibraries": "Todas las bibliotecas (%{count})",
|
||||
"multipleLibraries": "%{selected} de %{total} bibliotecas",
|
||||
"selectLibraries": "Seleccionar bibliotecas",
|
||||
"none": "Ninguno"
|
||||
}
|
||||
"about": "Acerca de"
|
||||
},
|
||||
"player": {
|
||||
"playListsText": "Fila de reproducción",
|
||||
@@ -680,12 +679,17 @@
|
||||
"totalScanned": "Total de carpetas escaneadas",
|
||||
"quickScan": "Escaneo rápido",
|
||||
"fullScan": "Escaneo completo",
|
||||
"selectiveScan": "Selectivo",
|
||||
"serverUptime": "Uptime del servidor",
|
||||
"serverDown": "OFFLINE",
|
||||
"scanType": "Tipo",
|
||||
"status": "Error de escaneo",
|
||||
"elapsedTime": "Tiempo transcurrido",
|
||||
"selectiveScan": "Selectivo"
|
||||
"elapsedTime": "Tiempo transcurrido"
|
||||
},
|
||||
"nowPlaying": {
|
||||
"title": "En reproducción",
|
||||
"empty": "Nada en reproducción",
|
||||
"minutesAgo": "Hace %{smart_count} minuto |||| Hace %{smart_count} minutos"
|
||||
},
|
||||
"help": {
|
||||
"title": "Atajos de teclado de Navidrome",
|
||||
@@ -695,15 +699,10 @@
|
||||
"toggle_play": "Reproducir / Pausar",
|
||||
"prev_song": "Canción anterior",
|
||||
"next_song": "Siguiente canción",
|
||||
"current_song": "Canción actual",
|
||||
"vol_up": "Subir volumen",
|
||||
"vol_down": "Bajar volumen",
|
||||
"toggle_love": "Marca esta canción como favorita",
|
||||
"current_song": "Canción actual"
|
||||
"toggle_love": "Marca esta canción como favorita"
|
||||
}
|
||||
},
|
||||
"nowPlaying": {
|
||||
"title": "En reproducción",
|
||||
"empty": "Nada en reproducción",
|
||||
"minutesAgo": "Hace %{smart_count} minuto |||| Hace %{smart_count} minutos"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
"bitDepth": "Bittisyvyys",
|
||||
"sampleRate": "Näytteenottotaajuus",
|
||||
"missing": "Puuttuva",
|
||||
"libraryName": "Kirjasto",
|
||||
"composer": ""
|
||||
"libraryName": "Kirjasto"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "Lisää jonoon",
|
||||
@@ -329,80 +328,6 @@
|
||||
"scanInProgress": "Skannaus käynnissä...",
|
||||
"noLibrariesAssigned": "Tälle käyttäjälle ei ole määritetty kirjastoja"
|
||||
}
|
||||
},
|
||||
"plugin": {
|
||||
"name": "Liitännäinen |||| Liitännäiset",
|
||||
"fields": {
|
||||
"id": "ID",
|
||||
"name": "Nimi",
|
||||
"description": "Kuvaus",
|
||||
"version": "Versio",
|
||||
"author": "Tekijä",
|
||||
"website": "Verkkosivusto",
|
||||
"permissions": "Oikeudet",
|
||||
"enabled": "Käytössä",
|
||||
"status": "Tila",
|
||||
"path": "Polku",
|
||||
"lastError": "Virhe",
|
||||
"hasError": "Virhe",
|
||||
"updatedAt": "Päivitetty",
|
||||
"createdAt": "Asennettu",
|
||||
"configKey": "Avain",
|
||||
"configValue": "Arvo",
|
||||
"allUsers": "Salli kaikki käyttäjät",
|
||||
"selectedUsers": "Valitut käyttäjät",
|
||||
"allLibraries": "Salli kaikki kirjastot",
|
||||
"selectedLibraries": "Valitut kirjastot"
|
||||
},
|
||||
"sections": {
|
||||
"status": "Tila",
|
||||
"info": "Lisäosan tiedot",
|
||||
"configuration": "Määritykset",
|
||||
"manifest": "Luettelo",
|
||||
"usersPermission": "Käyttäjäoikeudet",
|
||||
"libraryPermission": "Kirjaston oikeudet"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Käytössä",
|
||||
"disabled": "Ei käytössä"
|
||||
},
|
||||
"actions": {
|
||||
"enable": "Ota käyttöön",
|
||||
"disable": "Poista käytöstä",
|
||||
"disabledDueToError": "Korjaa virhe ennen käyttöönottoa",
|
||||
"disabledUsersRequired": "Valitse käyttäjät ennen käyttöönottoa",
|
||||
"disabledLibrariesRequired": "Valitse kirjastot ennen käyttöönottoa",
|
||||
"addConfig": "Lisää määritykset",
|
||||
"rescan": "Skannaa uudelleen"
|
||||
},
|
||||
"notifications": {
|
||||
"enabled": "Lisäosa käytössä",
|
||||
"disabled": "Lisäosa ei käytössä",
|
||||
"updated": "Lisäosa päivitetty",
|
||||
"error": "Virhe lisäosaa päivitettäessä"
|
||||
},
|
||||
"validation": {
|
||||
"invalidJson": "Määrityksen on oltava kelvollinen JSON"
|
||||
},
|
||||
"messages": {
|
||||
"configHelp": "Määritä lisäosa avain-arvo-parien avulla. Jätä tyhjäksi, jos lisäosa ei vaadi määrityksiä.",
|
||||
"clickPermissions": "Napsauta käyttöoikeutta saadaksesi lisätietoja",
|
||||
"noConfig": "Ei määritettyjä asetuksia",
|
||||
"allUsersHelp": "Kun tämä on käytössä, laajennuksella on pääsy kaikkiin käyttäjiin, myös tulevaisuudessa luotaviin.",
|
||||
"noUsers": "Ei valittuja käyttäjiä",
|
||||
"permissionReason": "Syy",
|
||||
"usersRequired": "Tämä laajennus vaatii pääsyn käyttäjätietoihin. Valitse käyttäjät, joihin laajennus voi päästä, tai ota käyttöön 'Salli kaikki käyttäjät'.",
|
||||
"allLibrariesHelp": "Kun tämä on käytössä, laajennuksella on pääsy kaikkiin kirjastoihin, myös tulevaisuudessa luotaviin.",
|
||||
"noLibraries": "Ei valittuja kirjastoja",
|
||||
"librariesRequired": "Tämä laajennus vaatii pääsyn kirjastotietoihin. Valitse, mihin kirjastoihin laajennus voi käyttää, tai ota käyttöön 'Salli kaikki kirjastot'.",
|
||||
"requiredHosts": "Vaaditut palvelimet",
|
||||
"configValidationError": "",
|
||||
"schemaRenderError": ""
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "avain",
|
||||
"configValue": "arvo"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ra": {
|
||||
@@ -661,16 +586,16 @@
|
||||
},
|
||||
"tabs": {
|
||||
"about": "Tietoja",
|
||||
"config": "Määritykset"
|
||||
"config": "Kokoonpano"
|
||||
},
|
||||
"config": {
|
||||
"configName": "Konfiguraation nimi",
|
||||
"environmentVariable": "Ympäristömuuttuja",
|
||||
"currentValue": "Nykyinen arvo",
|
||||
"configurationFile": "Määritystiedosto",
|
||||
"exportToml": "Vie määritys (TOML)",
|
||||
"exportSuccess": "Määritykset viety leikepöydälle TOML-muodossa",
|
||||
"exportFailed": "Määritysten kopiointi epäonnistui",
|
||||
"configurationFile": "Konfiguraatiotiedosto",
|
||||
"exportToml": "Vie konfiguraatio (TOML)",
|
||||
"exportSuccess": "Konfiguraatio viety leikepöydälle TOML-muodossa",
|
||||
"exportFailed": "Konfiguraation kopiointi epäonnistui",
|
||||
"devFlagsHeader": "Kehitysliput (voivat muuttua/poistua)",
|
||||
"devFlagsComment": "Nämä ovat kokeellisia asetuksia ja ne voidaan poistaa tulevissa versioissa"
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
"bitDepth": "Calidade de Bit",
|
||||
"sampleRate": "Taxa de mostra",
|
||||
"missing": "Falta",
|
||||
"libraryName": "Biblioteca",
|
||||
"composer": "Composición"
|
||||
"libraryName": "Biblioteca"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "Ao final da cola",
|
||||
@@ -329,80 +328,6 @@
|
||||
"scanInProgress": "Escaneo en progreso…",
|
||||
"noLibrariesAssigned": "Sen bibliotecas asignadas a esta usuaria"
|
||||
}
|
||||
},
|
||||
"plugin": {
|
||||
"name": "Complemento |||| Complementos",
|
||||
"fields": {
|
||||
"id": "ID",
|
||||
"name": "Nome",
|
||||
"description": "Descrición",
|
||||
"version": "Versión",
|
||||
"author": "Autoría",
|
||||
"website": "Sitio web",
|
||||
"permissions": "Permisos",
|
||||
"enabled": "Activado",
|
||||
"status": "Estado",
|
||||
"path": "Ruta",
|
||||
"lastError": "Erro",
|
||||
"hasError": "Erro",
|
||||
"updatedAt": "Actualizado",
|
||||
"createdAt": "Instalado",
|
||||
"configKey": "Clave",
|
||||
"configValue": "Valor",
|
||||
"allUsers": "Para todas as usuarias",
|
||||
"selectedUsers": "Usuarias seleccionadas",
|
||||
"allLibraries": "Permitir todas as bibliotecas",
|
||||
"selectedLibraries": "Selecciona bibliotecas"
|
||||
},
|
||||
"sections": {
|
||||
"status": "Estado",
|
||||
"info": "Info do complemento",
|
||||
"configuration": "Configuración",
|
||||
"manifest": "Manifesto",
|
||||
"usersPermission": "Permiso sobre usuarias",
|
||||
"libraryPermission": "Permiso sobre bibliotecas"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Activado",
|
||||
"disabled": "Desactivado"
|
||||
},
|
||||
"actions": {
|
||||
"enable": "Activar",
|
||||
"disable": "Desactivar",
|
||||
"disabledDueToError": "Arranxar erro antes de activar",
|
||||
"disabledUsersRequired": "Selección de usuarias antes de activar",
|
||||
"disabledLibrariesRequired": "Selección de bibliotecas antes de activar",
|
||||
"addConfig": "Engadir configuración",
|
||||
"rescan": "Volver a escanear"
|
||||
},
|
||||
"notifications": {
|
||||
"enabled": "Complemento activado",
|
||||
"disabled": "Complemento desactivado",
|
||||
"updated": "Complemento actualizado",
|
||||
"error": "Erro ao actualizar o complemento"
|
||||
},
|
||||
"validation": {
|
||||
"invalidJson": "A configuración debe ser un JSON válido"
|
||||
},
|
||||
"messages": {
|
||||
"configHelp": "Configura o complemento usando pares clave-valor. Deixa baleiro se o complemento non require configuración.",
|
||||
"clickPermissions": "Preme nun permiso para ver detalles",
|
||||
"noConfig": "Sen configuración establecida",
|
||||
"allUsersHelp": "Ao activalo, o complemento terá acceso a todas as usuarias, incluíndo aquelas que se creen no futuro.",
|
||||
"noUsers": "Sen usuarias seleccionadas",
|
||||
"permissionReason": "Motivo",
|
||||
"usersRequired": "O complemento precisa acceso á información sobre a usuaria. Selecciona as usuarias ás que pode acceder, ou activa 'Todas as usuarias'.",
|
||||
"allLibrariesHelp": "Ao activalo, o complemento terá acceso a todas as bibliotecas, incluíndo aquelas que se creen no futuro.",
|
||||
"noLibraries": "Sen bibliotecas seleccionadas",
|
||||
"librariesRequired": "O complemento precisa acceso á información sobre a biblioteca. Selecciona as bibliotecas ás que pode acceder, ou activa 'Todas as bibliotecas'.",
|
||||
"requiredHosts": "Servidores requeridos",
|
||||
"configValidationError": "Fallou a comprobación da configuración:",
|
||||
"schemaRenderError": "Non se puido aplicar a configuración. O esquema do complemento podería non ser válido."
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "clave",
|
||||
"configValue": "valor"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ra": {
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
"bitDepth": "Bit diepte",
|
||||
"sampleRate": "Sample waarde",
|
||||
"missing": "Ontbrekend",
|
||||
"libraryName": "Bibliotheek",
|
||||
"composer": ""
|
||||
"libraryName": "Bibliotheek"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "Voeg toe aan wachtrij",
|
||||
@@ -329,80 +328,6 @@
|
||||
"scanInProgress": "Scan is bezig...",
|
||||
"noLibrariesAssigned": "Geen bibliotheken aan deze gebruiker toegewezen"
|
||||
}
|
||||
},
|
||||
"plugin": {
|
||||
"name": "Plugin |||| Plugins",
|
||||
"fields": {
|
||||
"id": "ID",
|
||||
"name": "Naam",
|
||||
"description": "Omschrijving",
|
||||
"version": "Versie",
|
||||
"author": "Auteur",
|
||||
"website": "Website",
|
||||
"permissions": "Permissies",
|
||||
"enabled": "Aangezet",
|
||||
"status": "Status",
|
||||
"path": "Pad",
|
||||
"lastError": "Fout",
|
||||
"hasError": "Fout",
|
||||
"updatedAt": "Geupdate",
|
||||
"createdAt": "Geinstalleerd",
|
||||
"configKey": "Sleutel",
|
||||
"configValue": "Waarde",
|
||||
"allUsers": "Alle gebruikers toelaten",
|
||||
"selectedUsers": "Geselecteerde gebruikers",
|
||||
"allLibraries": "Alle bibliotheken toestaan",
|
||||
"selectedLibraries": "Geselecteerde bibliotheken"
|
||||
},
|
||||
"sections": {
|
||||
"status": "Status",
|
||||
"info": "Plugin informatie",
|
||||
"configuration": "Configuratie",
|
||||
"manifest": "Manifest",
|
||||
"usersPermission": "Gebruikers permissie",
|
||||
"libraryPermission": "Bibliotheekpermissie"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Aangezet",
|
||||
"disabled": "Uitgezet"
|
||||
},
|
||||
"actions": {
|
||||
"enable": "Aanzetten",
|
||||
"disable": "Uitzetten",
|
||||
"disabledDueToError": "Herstel de fout voor aanzetten",
|
||||
"disabledUsersRequired": "Selecteer gebruikers voor aanzetten",
|
||||
"disabledLibrariesRequired": "Selecteer bibliotheek voor aanzetten",
|
||||
"addConfig": "Configuratie toevoegen",
|
||||
"rescan": "Opnieuw scannen"
|
||||
},
|
||||
"notifications": {
|
||||
"enabled": "Plugin actief",
|
||||
"disabled": "Plugin niet actief",
|
||||
"updated": "Plugin geupdate",
|
||||
"error": "Fout bij updaten plugin"
|
||||
},
|
||||
"validation": {
|
||||
"invalidJson": "Configuratie moet geldige JSON zijn"
|
||||
},
|
||||
"messages": {
|
||||
"configHelp": "",
|
||||
"clickPermissions": "Klik op permissie voor details",
|
||||
"noConfig": "Geen configuratie ingesteld",
|
||||
"allUsersHelp": "",
|
||||
"noUsers": "Geen gebruikers geselecteerd",
|
||||
"permissionReason": "Reden",
|
||||
"usersRequired": "",
|
||||
"allLibrariesHelp": "",
|
||||
"noLibraries": "Geen bibliotheken geselecteerd",
|
||||
"librariesRequired": "",
|
||||
"requiredHosts": "Benodigde hosts",
|
||||
"configValidationError": "",
|
||||
"schemaRenderError": ""
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "Sleutel",
|
||||
"configValue": "Waarde"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ra": {
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
"bitDepth": "Głębokość próbkowania",
|
||||
"sampleRate": "Częstotliwość próbkowania",
|
||||
"missing": "Brak",
|
||||
"libraryName": "Biblioteka",
|
||||
"composer": "Kompozytor"
|
||||
"libraryName": "Biblioteka"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "Odtwarzaj Później",
|
||||
@@ -329,80 +328,6 @@
|
||||
"scanInProgress": "Skanowanie w trakcie...",
|
||||
"noLibrariesAssigned": "Brak bibliotek przypisanych do tego użytkownika"
|
||||
}
|
||||
},
|
||||
"plugin": {
|
||||
"name": "\nWtyczka |||| Wtyczki",
|
||||
"fields": {
|
||||
"id": "ID",
|
||||
"name": "Nazwa",
|
||||
"description": "Opis",
|
||||
"version": "Wersja",
|
||||
"author": "Autor",
|
||||
"website": "Witryna",
|
||||
"permissions": "Uprawnienia",
|
||||
"enabled": "Aktywny",
|
||||
"status": "Status",
|
||||
"path": "Ścieżka",
|
||||
"lastError": "Błąd",
|
||||
"hasError": "Błąd",
|
||||
"updatedAt": "Zaktualizowana",
|
||||
"createdAt": "Zainstalowana",
|
||||
"configKey": "Klucz",
|
||||
"configValue": "Wartość",
|
||||
"allUsers": "Zezwalaj wszystkim użytkownikom",
|
||||
"selectedUsers": "Wybrani użytkownicy",
|
||||
"allLibraries": "Zezwalaj dla wszystkich bibliotek",
|
||||
"selectedLibraries": ""
|
||||
},
|
||||
"sections": {
|
||||
"status": "",
|
||||
"info": "",
|
||||
"configuration": "",
|
||||
"manifest": "",
|
||||
"usersPermission": "",
|
||||
"libraryPermission": ""
|
||||
},
|
||||
"status": {
|
||||
"enabled": "",
|
||||
"disabled": ""
|
||||
},
|
||||
"actions": {
|
||||
"enable": "",
|
||||
"disable": "",
|
||||
"disabledDueToError": "",
|
||||
"disabledUsersRequired": "",
|
||||
"disabledLibrariesRequired": "",
|
||||
"addConfig": "",
|
||||
"rescan": ""
|
||||
},
|
||||
"notifications": {
|
||||
"enabled": "",
|
||||
"disabled": "",
|
||||
"updated": "",
|
||||
"error": ""
|
||||
},
|
||||
"validation": {
|
||||
"invalidJson": "Konfiguracja musić być w poprawnym formacie JSON"
|
||||
},
|
||||
"messages": {
|
||||
"configHelp": "Użyj par klucz-wartość, aby skonfigurować wtyczkę. Pozostaw puste, jeśli wtyczka nie wymaga konfiguracji.",
|
||||
"clickPermissions": "Kliknij uprawnienie, aby uzyskać szczegółowe informacje",
|
||||
"noConfig": "Nie wybrano konfiguracji",
|
||||
"allUsersHelp": "Po włączeniu wtyczka będzie miała dostęp do wszystkich użytkowników, także tych utworzonych w przyszłości.",
|
||||
"noUsers": "Nie wybrano użytkowników",
|
||||
"permissionReason": "Powód",
|
||||
"usersRequired": "Ta wtyczka wymaga dostępu do informacji o użytkowniku. Wybierz użytkowników, do których wtyczka ma mieć dostęp, lub włącz opcję „Zezwól wszystkim użytkownikom”.",
|
||||
"allLibrariesHelp": "Po włączeniu wtyczka będzie miała dostęp do wszystkich bibliotek, także tych utworzonych w przyszłości.",
|
||||
"noLibraries": "Nie wybrano biblioteki",
|
||||
"librariesRequired": "Wtyczka wymaga dostępu do informacji o bibliotece. Wybierz, dla której biblioteki zezwolić dostęp, lub włącz 'Zezwalaj dla wszystkich bibliotek'.",
|
||||
"requiredHosts": "",
|
||||
"configValidationError": "",
|
||||
"schemaRenderError": ""
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "klucz",
|
||||
"configValue": "wartość"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ra": {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"artist": "Artista",
|
||||
"album": "Álbum",
|
||||
"path": "Arquivo",
|
||||
"libraryName": "Biblioteca",
|
||||
"genre": "Gênero",
|
||||
"compilation": "Coletânea",
|
||||
"year": "Ano",
|
||||
@@ -35,9 +36,7 @@
|
||||
"rawTags": "Tags originais",
|
||||
"bitDepth": "Profundidade de bits",
|
||||
"sampleRate": "Taxa de amostragem",
|
||||
"missing": "Ausente",
|
||||
"libraryName": "Biblioteca",
|
||||
"composer": "Compositor"
|
||||
"missing": "Ausente"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "Adicionar à fila",
|
||||
@@ -59,6 +58,7 @@
|
||||
"songCount": "Músicas",
|
||||
"playCount": "Execuções",
|
||||
"name": "Nome",
|
||||
"libraryName": "Biblioteca",
|
||||
"genre": "Gênero",
|
||||
"compilation": "Coletânea",
|
||||
"year": "Ano",
|
||||
@@ -78,8 +78,7 @@
|
||||
"media": "Mídia",
|
||||
"mood": "Mood",
|
||||
"date": "Data de Lançamento",
|
||||
"missing": "Ausente",
|
||||
"libraryName": "Biblioteca"
|
||||
"missing": "Ausente"
|
||||
},
|
||||
"actions": {
|
||||
"playAll": "Tocar",
|
||||
@@ -131,9 +130,9 @@
|
||||
"maincredit": "Artista do Álbum ou Artista |||| Artistas do Álbum ou Artistas"
|
||||
},
|
||||
"actions": {
|
||||
"topSongs": "Mais tocadas",
|
||||
"shuffle": "Aleatório",
|
||||
"radio": "Rádio",
|
||||
"topSongs": "Mais tocadas"
|
||||
"radio": "Rádio"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
@@ -162,14 +161,14 @@
|
||||
"updated": "Usuário atualizado com sucesso",
|
||||
"deleted": "Usuário deletado com sucesso"
|
||||
},
|
||||
"validation": {
|
||||
"librariesRequired": "Pelo menos uma biblioteca deve ser selecionada para usuários não-administradores"
|
||||
},
|
||||
"message": {
|
||||
"listenBrainzToken": "Entre seu token do ListenBrainz",
|
||||
"clickHereForToken": "Clique aqui para obter seu token",
|
||||
"selectAllLibraries": "Selecionar todas as bibliotecas",
|
||||
"adminAutoLibraries": "Usuários administradores têm acesso automático a todas as bibliotecas"
|
||||
},
|
||||
"validation": {
|
||||
"librariesRequired": "Pelo menos uma biblioteca deve ser selecionada para usuários não-administradores"
|
||||
}
|
||||
},
|
||||
"player": {
|
||||
@@ -254,15 +253,17 @@
|
||||
"updatedAt": "Últ. Atualização",
|
||||
"createdAt": "Data de Criação",
|
||||
"downloadable": "Permitir Baixar?"
|
||||
}
|
||||
},
|
||||
"notifications": {},
|
||||
"actions": {}
|
||||
},
|
||||
"missing": {
|
||||
"name": "Arquivo ausente |||| Arquivos ausentes",
|
||||
"fields": {
|
||||
"path": "Caminho",
|
||||
"size": "Tamanho",
|
||||
"updatedAt": "Desaparecido em",
|
||||
"libraryName": "Biblioteca"
|
||||
"libraryName": "Biblioteca",
|
||||
"updatedAt": "Desaparecido em"
|
||||
},
|
||||
"actions": {
|
||||
"remove": "Remover",
|
||||
@@ -301,20 +302,20 @@
|
||||
},
|
||||
"actions": {
|
||||
"scan": "Scanear Biblioteca",
|
||||
"manageUsers": "Gerenciar Acesso do Usuário",
|
||||
"viewDetails": "Ver Detalhes",
|
||||
"quickScan": "Scan Rápido",
|
||||
"fullScan": "Scan Completo"
|
||||
"fullScan": "Scan Completo",
|
||||
"manageUsers": "Gerenciar Acesso do Usuário",
|
||||
"viewDetails": "Ver Detalhes"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "Biblioteca criada com sucesso",
|
||||
"updated": "Biblioteca atualizada com sucesso",
|
||||
"deleted": "Biblioteca excluída com sucesso",
|
||||
"scanStarted": "Scan da biblioteca iniciada",
|
||||
"scanCompleted": "Scan da biblioteca concluída",
|
||||
"quickScanStarted": "Scan rápido iniciado",
|
||||
"fullScanStarted": "Scan completo iniciado",
|
||||
"scanError": "Erro ao iniciar o scan. Verifique os logs"
|
||||
"scanError": "Erro ao iniciar o scan. Verifique os logs",
|
||||
"scanCompleted": "Scan da biblioteca concluída"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "Nome da biblioteca é obrigatório",
|
||||
@@ -386,6 +387,8 @@
|
||||
},
|
||||
"messages": {
|
||||
"configHelp": "Configure o plugin usando pares chave-valor. Deixe vazio se o plugin não precisa de configuração.",
|
||||
"configValidationError": "Falha na validação da configuração:",
|
||||
"schemaRenderError": "Não foi possível renderizar o formulário de configuração. O schema do plugin pode estar inválido.",
|
||||
"clickPermissions": "Clique em uma permissão para ver detalhes",
|
||||
"noConfig": "Nenhuma configuração definida",
|
||||
"allUsersHelp": "Quando habilitado, o plugin terá acesso a todos os usuários, incluindo os criados no futuro.",
|
||||
@@ -395,9 +398,7 @@
|
||||
"allLibrariesHelp": "Quando habilitado, o plugin terá acesso a todas as bibliotecas, incluindo as criadas no futuro.",
|
||||
"noLibraries": "Nenhuma biblioteca selecionada",
|
||||
"librariesRequired": "Este plugin requer acesso a informações de bibliotecas. Selecione quais bibliotecas o plugin pode acessar, ou habilite 'Permitir todas as bibliotecas'.",
|
||||
"requiredHosts": "Hosts necessários",
|
||||
"configValidationError": "Falha na validação da configuração:",
|
||||
"schemaRenderError": "Não foi possível renderizar o formulário de configuração. O schema do plugin pode estar inválido."
|
||||
"requiredHosts": "Hosts necessários"
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "chave",
|
||||
@@ -555,6 +556,8 @@
|
||||
"transcodingDisabled": "Por questão de segurança, esta tela de configuração está desabilitada. Se você quiser alterar estas configurações, reinicie o servidor com a opção %{config}",
|
||||
"transcodingEnabled": "Navidrome está sendo executado com a opção %{config}. Isto permite que potencialmente se execute comandos do sistema pela interface Web. É recomendado que vc mantenha esta opção desabilitada, e só a habilite quando precisar configurar opções de Conversão",
|
||||
"songsAddedToPlaylist": "Música adicionada à playlist |||| %{smart_count} músicas adicionadas à playlist",
|
||||
"noSimilarSongsFound": "Nenhuma música semelhante encontrada",
|
||||
"noTopSongsFound": "Nenhuma música mais tocada encontrada",
|
||||
"noPlaylistsAvailable": "Nenhuma playlist",
|
||||
"delete_user_title": "Excluir usuário '%{name}'",
|
||||
"delete_user_content": "Você tem certeza que deseja excluir o usuário e todos os seus dados (incluindo suas playlists e preferências)?",
|
||||
@@ -584,12 +587,16 @@
|
||||
"remove_missing_title": "Remover arquivos ausentes",
|
||||
"remove_missing_content": "Você tem certeza que deseja remover os arquivos selecionados do banco de dados? Isso removerá permanentemente qualquer referência a eles, incluindo suas contagens de reprodução e classificações.",
|
||||
"remove_all_missing_title": "Remover todos os arquivos ausentes",
|
||||
"remove_all_missing_content": "Você tem certeza que deseja remover todos os arquivos ausentes do banco de dados? Isso removerá permanentemente qualquer referência a eles, incluindo suas contagens de reprodução e classificações.",
|
||||
"noSimilarSongsFound": "Nenhuma música semelhante encontrada",
|
||||
"noTopSongsFound": "Nenhuma música mais tocada encontrada"
|
||||
"remove_all_missing_content": "Você tem certeza que deseja remover todos os arquivos ausentes do banco de dados? Isso removerá permanentemente qualquer referência a eles, incluindo suas contagens de reprodução e classificações."
|
||||
},
|
||||
"menu": {
|
||||
"library": "Biblioteca",
|
||||
"librarySelector": {
|
||||
"allLibraries": "Todas as Bibliotecas (%{count})",
|
||||
"multipleLibraries": "%{selected} de %{total} Bibliotecas",
|
||||
"selectLibraries": "Selecionar Bibliotecas",
|
||||
"none": "Nenhuma"
|
||||
},
|
||||
"settings": "Configurações",
|
||||
"version": "Versão",
|
||||
"theme": "Tema",
|
||||
@@ -615,13 +622,7 @@
|
||||
"albumList": "Álbuns",
|
||||
"about": "Info",
|
||||
"playlists": "Playlists",
|
||||
"sharedPlaylists": "Compartilhadas",
|
||||
"librarySelector": {
|
||||
"allLibraries": "Todas as Bibliotecas (%{count})",
|
||||
"multipleLibraries": "%{selected} de %{total} Bibliotecas",
|
||||
"selectLibraries": "Selecionar Bibliotecas",
|
||||
"none": "Nenhuma"
|
||||
}
|
||||
"sharedPlaylists": "Compartilhadas"
|
||||
},
|
||||
"player": {
|
||||
"playListsText": "Fila de Execução",
|
||||
@@ -680,12 +681,17 @@
|
||||
"totalScanned": "Total de pastas scaneadas",
|
||||
"quickScan": "Rápido",
|
||||
"fullScan": "Completo",
|
||||
"selectiveScan": "Seletivo",
|
||||
"serverUptime": "Uptime do servidor",
|
||||
"serverDown": "DESCONECTADO",
|
||||
"scanType": "Último Scan",
|
||||
"status": "Erro",
|
||||
"elapsedTime": "Duração",
|
||||
"selectiveScan": "Seletivo"
|
||||
"elapsedTime": "Duração"
|
||||
},
|
||||
"nowPlaying": {
|
||||
"title": "Tocando agora",
|
||||
"empty": "Nada tocando",
|
||||
"minutesAgo": "%{smart_count} minuto atrás |||| %{smart_count} minutos atrás"
|
||||
},
|
||||
"help": {
|
||||
"title": "Teclas de atalho",
|
||||
@@ -700,10 +706,5 @@
|
||||
"toggle_love": "Marcar/desmarcar favorita",
|
||||
"current_song": "Vai para música atual"
|
||||
}
|
||||
},
|
||||
"nowPlaying": {
|
||||
"title": "Tocando agora",
|
||||
"empty": "Nada tocando",
|
||||
"minutesAgo": "%{smart_count} minuto atrás |||| %{smart_count} minutos atrás"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
"bitDepth": "Битовая глубина (Bit)",
|
||||
"sampleRate": "Частота дискретизации (Hz)",
|
||||
"missing": "Поле отсутствует",
|
||||
"libraryName": "Библиотека",
|
||||
"composer": "Композитор"
|
||||
"libraryName": "Библиотека"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "В очередь",
|
||||
@@ -329,80 +328,6 @@
|
||||
"scanInProgress": "Сканирование продолжается...",
|
||||
"noLibrariesAssigned": "Нет библиотек, назначенных этому пользователю"
|
||||
}
|
||||
},
|
||||
"plugin": {
|
||||
"name": "Плагин |||| Плагины",
|
||||
"fields": {
|
||||
"id": "ID",
|
||||
"name": "Имя",
|
||||
"description": "Описание",
|
||||
"version": "Версия",
|
||||
"author": "Автор",
|
||||
"website": "Вебсайт",
|
||||
"permissions": "Разрешения",
|
||||
"enabled": "Включено",
|
||||
"status": "Статус",
|
||||
"path": "Путь",
|
||||
"lastError": "Ошибка",
|
||||
"hasError": "Ошибка",
|
||||
"updatedAt": "Обновлено",
|
||||
"createdAt": "Установленный",
|
||||
"configKey": "Ключ",
|
||||
"configValue": "Значение",
|
||||
"allUsers": "Разрешить всем пользователям",
|
||||
"selectedUsers": "Выбранные пользователи",
|
||||
"allLibraries": "Разрешить доступ ко всем библиотекам",
|
||||
"selectedLibraries": "Избранные библиотеки"
|
||||
},
|
||||
"sections": {
|
||||
"status": "Статус",
|
||||
"info": "Информация о плагине",
|
||||
"configuration": "Конфигурация",
|
||||
"manifest": "Манифест",
|
||||
"usersPermission": "Разрешение пользователей",
|
||||
"libraryPermission": "Разрешение на использование библиотеки"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Включено",
|
||||
"disabled": "Отключить"
|
||||
},
|
||||
"actions": {
|
||||
"enable": "Включить",
|
||||
"disable": "Отключить",
|
||||
"disabledDueToError": "Исправьте ошибку перед включением",
|
||||
"disabledUsersRequired": "Выберите пользователей перед включением",
|
||||
"disabledLibrariesRequired": "Выберите библиотеки перед включением",
|
||||
"addConfig": "Добавить конфигурацию",
|
||||
"rescan": "Повторное сканирование"
|
||||
},
|
||||
"notifications": {
|
||||
"enabled": "Плагин включен",
|
||||
"disabled": "Плагин отключен",
|
||||
"updated": "Плагин обновлен",
|
||||
"error": "Ошибка обновления плагина"
|
||||
},
|
||||
"validation": {
|
||||
"invalidJson": "Конфигурация должна быть в формате JSON, допустимом для всех пользователей"
|
||||
},
|
||||
"messages": {
|
||||
"configHelp": "Настройте плагин, используя пары ключ-значение. Оставьте поле пустым, если плагин не требует настройки.",
|
||||
"clickPermissions": "Нажмите на разрешение для получения подробной информации",
|
||||
"noConfig": "Конфигурация не задана",
|
||||
"allUsersHelp": "При включении плагин получит доступ ко всем пользователям, включая тех, кто будет создан в будущем.",
|
||||
"noUsers": "Не выбрано ни одного пользователя",
|
||||
"permissionReason": "Причина",
|
||||
"usersRequired": "Этому плагину требуется доступ к пользовательской информации. Выберите, к каким пользователям плагин может получить доступ, или включите \"Разрешить всем пользователям\".",
|
||||
"allLibrariesHelp": "После включения плагин будет иметь доступ ко всем библиотекам, включая те, которые будут созданы в будущем.",
|
||||
"noLibraries": "Библиотеки не выбраны",
|
||||
"librariesRequired": "Этому плагину требуется доступ к библиотечной информации. Выберите, к каким библиотекам плагин может получить доступ, или включите \"Разрешить все библиотеки\".",
|
||||
"requiredHosts": "Необходимые хосты",
|
||||
"configValidationError": "Проверка конфигурации завершилась неудачей:",
|
||||
"schemaRenderError": "Не удалось отобразить форму конфигурации. Возможно, схема плагина недействительна."
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "ключ",
|
||||
"configValue": "значение"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ra": {
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
"bitDepth": "Bitna globina",
|
||||
"sampleRate": "Frekvenca vzorčenja",
|
||||
"missing": "Manjka",
|
||||
"libraryName": "Knjižnica",
|
||||
"composer": "Skladatelj"
|
||||
"libraryName": "Knjižnica"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "Predvajaj kasneje",
|
||||
@@ -302,19 +301,14 @@
|
||||
"actions": {
|
||||
"scan": "Skeniraj knjižnico",
|
||||
"manageUsers": "Upravljanje dostopa uporabnikov",
|
||||
"viewDetails": "Ogled podrobnosti",
|
||||
"quickScan": "Hitro skeniranje",
|
||||
"fullScan": "Popolno skeniranje"
|
||||
"viewDetails": "Ogled podrobnosti"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "Knjižnica je uspešno ustvarjena",
|
||||
"updated": "Knjižnica je bila uspešno posodobljena",
|
||||
"deleted": "Knjižnica je uspešno izbrisana",
|
||||
"scanStarted": "Skeniranje knjižnice se je začelo",
|
||||
"scanCompleted": "Skeniranje knjižnice končano",
|
||||
"quickScanStarted": "Hitro skeniranje se je začelo",
|
||||
"fullScanStarted": "Popolno skeniranje se je začelo",
|
||||
"scanError": "Napaka pri začetku skeniranja. Preverite dnevnike"
|
||||
"scanCompleted": "Skeniranje knjižnice končano"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "Ime knjižnice je obvezno",
|
||||
@@ -329,80 +323,6 @@
|
||||
"scanInProgress": "Skeniranje v teku...",
|
||||
"noLibrariesAssigned": "Uporabnik nima dodeljenih knjižnic"
|
||||
}
|
||||
},
|
||||
"plugin": {
|
||||
"name": "Vtičnik |||| Vtičniki",
|
||||
"fields": {
|
||||
"id": "ID",
|
||||
"name": "Ime",
|
||||
"description": "Opis",
|
||||
"version": "Verzija",
|
||||
"author": "Avtor",
|
||||
"website": "Spletna stran",
|
||||
"permissions": "Dovoljenja",
|
||||
"enabled": "Vključeno",
|
||||
"status": "Status",
|
||||
"path": "Pot",
|
||||
"lastError": "Napaka",
|
||||
"hasError": "Napaka",
|
||||
"updatedAt": "Posodobljeno",
|
||||
"createdAt": "Inštalirano",
|
||||
"configKey": "Ključ",
|
||||
"configValue": "Vrednost",
|
||||
"allUsers": "Dovoli vsem uporabnikom",
|
||||
"selectedUsers": "Izbrani uporabniki",
|
||||
"allLibraries": "Dovoli vse knjižnice",
|
||||
"selectedLibraries": "Izbrane knjižnice"
|
||||
},
|
||||
"sections": {
|
||||
"status": "Status",
|
||||
"info": "Informacije o vtičniku",
|
||||
"configuration": "Konfiguracija",
|
||||
"manifest": "Manifest",
|
||||
"usersPermission": "Uporabniška dovoljenja",
|
||||
"libraryPermission": "Knjižnična dovoljenja"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Vključeno",
|
||||
"disabled": "Izključeno"
|
||||
},
|
||||
"actions": {
|
||||
"enable": "Vključi",
|
||||
"disable": "Izključi",
|
||||
"disabledDueToError": "Popravi napako pred vključitvijo",
|
||||
"disabledUsersRequired": "Izberi uporabnike pred vključitvijo",
|
||||
"disabledLibrariesRequired": "Izberi knjižnice pred vključitvijo",
|
||||
"addConfig": "Dodaj konfiguracijo",
|
||||
"rescan": "Ponovi skeniranje"
|
||||
},
|
||||
"notifications": {
|
||||
"enabled": "Vtičnik vključen",
|
||||
"disabled": "Vtičnik izključen",
|
||||
"updated": "Vtičnik posodobljen",
|
||||
"error": "Napaka pri posodobitvi vtičnika"
|
||||
},
|
||||
"validation": {
|
||||
"invalidJson": "Konfiguracija mora biti pravilen JSON"
|
||||
},
|
||||
"messages": {
|
||||
"configHelp": "Konfiguriraj vtičnik z uporabo key-value parov. Pusti prazno, če vtičnik ne potrebuje konfiguracije.",
|
||||
"clickPermissions": "Klikni za dovoljenje o podrobnostih",
|
||||
"noConfig": "Konfiguracija ni nastavljena",
|
||||
"allUsersHelp": "Ko vključeno, bo vtičnik imel dostop do vseh uporabnikov, tudi prihodnjih.",
|
||||
"noUsers": "Uporabniki niso izbrani",
|
||||
"permissionReason": "Razlog",
|
||||
"usersRequired": "Vtičnik potrebuje dostop do uporabnikovih informacij. Izberi uporabnike ali vključi dostop vsem uporabnikom.",
|
||||
"allLibrariesHelp": "Ko vključeno, bo vtičnik imel dostop do vseh knjižnic, tudi prihodnjih.",
|
||||
"noLibraries": "Ni izbranih knjižnic",
|
||||
"librariesRequired": "Vtičnik zahteva dostop do knjižnih informacij. Izberi do katerih knjižnic lahko dostopa, ali vključi dostop do vseh knjižnic.",
|
||||
"requiredHosts": "Zahtevani gostitelji",
|
||||
"configValidationError": "",
|
||||
"schemaRenderError": ""
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "ključ",
|
||||
"configValue": "vrednost"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ra": {
|
||||
@@ -684,8 +604,7 @@
|
||||
"serverDown": "NEPOVEZAN",
|
||||
"scanType": "Tip",
|
||||
"status": "Napaka pri skeniranju",
|
||||
"elapsedTime": "Pretečeni čas",
|
||||
"selectiveScan": "Selektivno"
|
||||
"elapsedTime": "Pretečeni čas"
|
||||
},
|
||||
"help": {
|
||||
"title": "Hitre tipke",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"playCount": "Spelningar",
|
||||
"title": "Titel",
|
||||
"artist": "Artist",
|
||||
"composer": "Kompositör",
|
||||
"album": "Album",
|
||||
"path": "Sökväg",
|
||||
"genre": "Genre",
|
||||
@@ -36,8 +37,7 @@
|
||||
"bitDepth": "Bitdjup",
|
||||
"sampleRate": "Samplingsfrekvens",
|
||||
"missing": "Saknade",
|
||||
"libraryName": "Bibliotek",
|
||||
"composer": "Kompositör"
|
||||
"libraryName": "Bibliotek"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "Lägg till i kön",
|
||||
@@ -329,80 +329,6 @@
|
||||
"scanInProgress": "Scanning pågår...",
|
||||
"noLibrariesAssigned": "Inga bibliotek har tilldelats den här användaren"
|
||||
}
|
||||
},
|
||||
"plugin": {
|
||||
"name": "Tillägg |||| Tillägg",
|
||||
"fields": {
|
||||
"id": "ID",
|
||||
"name": "Namn",
|
||||
"description": "Beskrivning",
|
||||
"version": "Version",
|
||||
"author": "Författare",
|
||||
"website": "Website",
|
||||
"permissions": "Behörigheter",
|
||||
"enabled": "Aktiverad",
|
||||
"status": "Status",
|
||||
"path": "Sökväg",
|
||||
"lastError": "Fel",
|
||||
"hasError": "Fel",
|
||||
"updatedAt": "Uppdaterad",
|
||||
"createdAt": "Installerad",
|
||||
"configKey": "Nyckel",
|
||||
"configValue": "Värde",
|
||||
"allUsers": "Tillåt alla användare",
|
||||
"selectedUsers": "Valda användare",
|
||||
"allLibraries": "Tillåt alla bibliotek",
|
||||
"selectedLibraries": "Valda bibliotek"
|
||||
},
|
||||
"sections": {
|
||||
"status": "Status",
|
||||
"info": "Tilläggsinformation",
|
||||
"configuration": "Konfiguration",
|
||||
"manifest": "Manifest",
|
||||
"usersPermission": "Användarbehörigheter",
|
||||
"libraryPermission": "Biblioteksbehörigheter"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Aktiverad",
|
||||
"disabled": "Inaktiverad"
|
||||
},
|
||||
"actions": {
|
||||
"enable": "Aktivera",
|
||||
"disable": "Inaktivera",
|
||||
"disabledDueToError": "Åtgärda felet innan aktivering",
|
||||
"disabledUsersRequired": "Välj användare före aktivering",
|
||||
"disabledLibrariesRequired": "Välj bibliotek före aktivering",
|
||||
"addConfig": "Lägg till konfiguration",
|
||||
"rescan": "Scanna om"
|
||||
},
|
||||
"notifications": {
|
||||
"enabled": "Tillägg aktiverat",
|
||||
"disabled": "Tillägg inaktiverat",
|
||||
"updated": "Tillägg uppdaterat",
|
||||
"error": "Fel vid uppdatering av tillägg"
|
||||
},
|
||||
"validation": {
|
||||
"invalidJson": "Konfigurationen måste vara giltig JSON"
|
||||
},
|
||||
"messages": {
|
||||
"configHelp": "Konfigurera tillägget med nyckel–värde-par. Lämna tomt om tillägget inte kräver någon konfiguration.",
|
||||
"clickPermissions": "Klicka på en behörighet för mer information",
|
||||
"noConfig": "Ingen konfiguration angiven",
|
||||
"allUsersHelp": "När den är aktiverad får tillägget tillgång till alla användare, inklusive de som skapas i framtiden.",
|
||||
"noUsers": "Inga användare valda",
|
||||
"permissionReason": "Orsak",
|
||||
"usersRequired": "Detta tillägg kräver åtkomst till användarinformation. Välj vilka användare insticksprogrammet ska ha åtkomst till, eller aktivera 'Tillåt alla användare'.",
|
||||
"allLibrariesHelp": "När den är aktiverad får tillägget tillgång till alla bibliotek, inklusive de som skapas i framtiden.",
|
||||
"noLibraries": "Inga bibliotek valda",
|
||||
"librariesRequired": "Detta tillägg kräver tillgång till biblioteksinformation. Välj vilka bibliotek tillägget kan komma åt eller aktivera 'Tillåt alla bibliotek'.",
|
||||
"requiredHosts": "Krävda värdar",
|
||||
"configValidationError": "",
|
||||
"schemaRenderError": ""
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "nyckel",
|
||||
"configValue": "värde"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ra": {
|
||||
@@ -619,7 +545,7 @@
|
||||
"librarySelector": {
|
||||
"allLibraries": "Alla bibliotek (%{count})",
|
||||
"multipleLibraries": "%{selected} av %{total} bibliotek",
|
||||
"selectLibraries": "Välj bibliotek",
|
||||
"selectLibraries": "Valda bibliotek",
|
||||
"none": "Inga"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
"bitDepth": "Bit depth",
|
||||
"sampleRate": "แซมเปิ้ลเรต",
|
||||
"missing": "หายไป",
|
||||
"libraryName": "ห้องสมุด",
|
||||
"composer": ""
|
||||
"libraryName": "ห้องสมุด"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "เพิ่มในคิว",
|
||||
@@ -329,80 +328,6 @@
|
||||
"scanInProgress": "กำลังสแกน...",
|
||||
"noLibrariesAssigned": "ไม่มีห้องสมุดสำหรับผู้ใช้นี้"
|
||||
}
|
||||
},
|
||||
"plugin": {
|
||||
"name": "ปลั๊กอิน |||| ปลั๊กอิน",
|
||||
"fields": {
|
||||
"id": "ID",
|
||||
"name": "ชื่อ",
|
||||
"description": "รายละเอียด",
|
||||
"version": "เวอร์ชั่น",
|
||||
"author": "ผู้สร้าง",
|
||||
"website": "เว็บไซต์",
|
||||
"permissions": "การอนุญาติ",
|
||||
"enabled": "เปิดใช้",
|
||||
"status": "สถานะ",
|
||||
"path": "เส้นทาง",
|
||||
"lastError": "ผิดพลาด",
|
||||
"hasError": "ผิดพลาด",
|
||||
"updatedAt": "อัพเดทแล้ว",
|
||||
"createdAt": "ติดตั้งแล้ว",
|
||||
"configKey": "คีย์",
|
||||
"configValue": "ค่า",
|
||||
"allUsers": "อนุญาติผู้ใช้ทั้งหมด",
|
||||
"selectedUsers": "ผู้ใช้ถูกเลือก",
|
||||
"allLibraries": "อนุญาติห้องสมุดเพลงทั้งหมด",
|
||||
"selectedLibraries": "ห้องสมุดเพลงถูกเลือก"
|
||||
},
|
||||
"sections": {
|
||||
"status": "สถานะ",
|
||||
"info": "ข้อมูลปลั๊กอิน",
|
||||
"configuration": "การตั้งค่า",
|
||||
"manifest": "แสดง",
|
||||
"usersPermission": "สิทธิของผู้ใช้",
|
||||
"libraryPermission": "สิทธิของห้องสมุดเพลง"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "เปิดใช้งานแล้ว",
|
||||
"disabled": "ปิดใช้งานแล้ว"
|
||||
},
|
||||
"actions": {
|
||||
"enable": "เปิดใช้งาน",
|
||||
"disable": "ปิดใช้งาน",
|
||||
"disabledDueToError": "แก้ไขข้อผิดพลาดก่อนเปิดใช้งาน",
|
||||
"disabledUsersRequired": "เลือกผู้ใช้ที่จะเปิดใช้งาน",
|
||||
"disabledLibrariesRequired": "เลือกห้องสมุดเพลงที่จะเปิดใช้งาน",
|
||||
"addConfig": "เพิ่มการตั้งค่า",
|
||||
"rescan": "สแกนซ้ำ"
|
||||
},
|
||||
"notifications": {
|
||||
"enabled": "เปิดใช้ปลั๊กอินแล้ว",
|
||||
"disabled": "ปิดใช้ปลั๊กอินแล้ว",
|
||||
"updated": "ปลั๊กอินอัพเดท",
|
||||
"error": "อัพเดทผิดพลาด"
|
||||
},
|
||||
"validation": {
|
||||
"invalidJson": "ต้องตั้งค่าตามไวยากรณ์ JSON"
|
||||
},
|
||||
"messages": {
|
||||
"configHelp": "ใส่ค่าให้เข้าคู่กับคีย์ของปลั๊กอิน ปล่อยว่างถ้าปลั๊กอินไม่ต้องการใช้",
|
||||
"clickPermissions": "กดดูรายละเอียดของการอนุญาติ",
|
||||
"noConfig": "ไม่ได้ตั้งค่า",
|
||||
"allUsersHelp": "เมื่อเปิดใช้ ปลั๊กอินจะใช้กับผู้ใช้ทุกคน รวมถึงผู้ใช้ใหม่ในอนาคต",
|
||||
"noUsers": "ไม่ได้เลือกผู้ใช้",
|
||||
"permissionReason": "เหตุผล",
|
||||
"usersRequired": "ปลั๊กอินนี้ต้องการเข้าถึงข้อมูลผู้ใช้ เลือกผู้ใช้ที่ต้องการให้ปลั๊กอินเข้าถึงหรือเปิดใช้งานกับผู้ใช้ทั้งหมด",
|
||||
"allLibrariesHelp": "เมื่อเปิดใช้งาน ปลั๊กอินจะเข้าถึงทุกห้องสมุดเพลง รวมถึงของผู้ใช้ใหม่ในอนาคต",
|
||||
"noLibraries": "ไม่มีห้องสมุดเพลงถูกเลือก",
|
||||
"librariesRequired": "ปลั๊กอินนี้ต้องการเข้าถึงข้อมูลห้องสมุดเพลง เลือกห้องสมุดเพลงที่ต้องการให้ปลั๊กอินเข้าถึงหรือเปิดใช้งานกับห้องสมุดเพลงทั้งหมด",
|
||||
"requiredHosts": "ต้องการ Host",
|
||||
"configValidationError": "",
|
||||
"schemaRenderError": ""
|
||||
},
|
||||
"placeholders": {
|
||||
"configKey": "คีย์",
|
||||
"configValue": "ค่า"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ra": {
|
||||
|
||||
BIN
ui/public/fonts/Unbounded-Variable.woff2
Normal file
BIN
ui/public/fonts/Unbounded-Variable.woff2
Normal file
Binary file not shown.
@@ -228,7 +228,7 @@ const AlbumDetails = (props) => {
|
||||
let notes =
|
||||
albumInfo?.notes?.replace(new RegExp('<.*>', 'g'), '') || record.notes
|
||||
|
||||
if (notes !== undefined) {
|
||||
if (notes) {
|
||||
notes += '..'
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ const AlbumDetails = (props) => {
|
||||
)}
|
||||
</Typography>
|
||||
)}
|
||||
{isDesktop && (
|
||||
{isDesktop && notes && (
|
||||
<Collapse
|
||||
collapsedHeight={'2.75em'}
|
||||
in={expanded}
|
||||
@@ -364,7 +364,7 @@ const AlbumDetails = (props) => {
|
||||
{!isDesktop && record['comment'] && (
|
||||
<CollapsibleComment record={record} />
|
||||
)}
|
||||
{!isDesktop && (
|
||||
{!isDesktop && notes && (
|
||||
<div className={classes.notes}>
|
||||
<Collapse collapsedHeight={'1.5em'} in={expanded} timeout={'auto'}>
|
||||
<Typography
|
||||
|
||||
@@ -4,18 +4,26 @@ import FavoriteIcon from '@material-ui/icons/Favorite'
|
||||
import FavoriteBorderIcon from '@material-ui/icons/FavoriteBorder'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import clsx from 'clsx'
|
||||
import { useToggleLove } from './useToggleLove'
|
||||
import { useRecordContext } from 'react-admin'
|
||||
import config from '../config'
|
||||
import { isDateSet } from '../utils/validations'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
love: {
|
||||
color: (props) => props.color,
|
||||
visibility: (props) =>
|
||||
props.visible === false ? 'hidden' : props.loved ? 'visible' : 'inherit',
|
||||
const useStyles = makeStyles(
|
||||
{
|
||||
love: {
|
||||
color: (props) => props.color,
|
||||
visibility: (props) =>
|
||||
props.visible === false
|
||||
? 'hidden'
|
||||
: props.loved
|
||||
? 'visible'
|
||||
: 'inherit',
|
||||
},
|
||||
},
|
||||
})
|
||||
{ name: 'NDLoveButton' },
|
||||
)
|
||||
|
||||
export const LoveButton = ({
|
||||
resource,
|
||||
@@ -25,9 +33,11 @@ export const LoveButton = ({
|
||||
component: Button,
|
||||
addLabel,
|
||||
disabled,
|
||||
className,
|
||||
record: recordProp,
|
||||
...rest
|
||||
}) => {
|
||||
const record = useRecordContext(rest) || {}
|
||||
const record = useRecordContext({ record: recordProp }) || {}
|
||||
const classes = useStyles({ color, visible, loved: record.starred })
|
||||
const [toggleLove, loading] = useToggleLove(resource, record)
|
||||
|
||||
@@ -48,7 +58,7 @@ export const LoveButton = ({
|
||||
onClick={handleToggleLove}
|
||||
size={'small'}
|
||||
disabled={disabled || loading || record.missing}
|
||||
className={classes.love}
|
||||
className={clsx(classes.love, className)}
|
||||
title={
|
||||
isDateSet(record.starredAt)
|
||||
? new Date(record.starredAt).toLocaleString()
|
||||
|
||||
@@ -28,6 +28,9 @@ import { useDispatch } from 'react-redux'
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
user: {},
|
||||
button: {
|
||||
color: 'inherit',
|
||||
},
|
||||
avatar: {
|
||||
width: theme.spacing(4),
|
||||
height: theme.spacing(4),
|
||||
@@ -72,12 +75,11 @@ const UserMenu = (props) => {
|
||||
<div className={classes.user}>
|
||||
<Tooltip title={label && translate(label, { _: label })}>
|
||||
<IconButton
|
||||
className={classes.button}
|
||||
aria-label={label && translate(label, { _: label })}
|
||||
aria-owns={open ? 'menu-appbar' : null}
|
||||
aria-haspopup={true}
|
||||
color="inherit"
|
||||
onClick={handleMenu}
|
||||
size={'small'}
|
||||
>
|
||||
{loaded && identity.avatar ? (
|
||||
<Avatar
|
||||
|
||||
@@ -34,7 +34,15 @@ const PlaylistEditForm = (props) => {
|
||||
return (
|
||||
<SimpleForm redirect="list" variant={'outlined'} {...props}>
|
||||
<TextInput source="name" validate={required()} />
|
||||
<TextInput multiline source="comment" />
|
||||
<TextInput
|
||||
multiline
|
||||
minRows={3}
|
||||
source="comment"
|
||||
fullWidth
|
||||
inputProps={{
|
||||
style: { resize: 'vertical' },
|
||||
}}
|
||||
/>
|
||||
{permissions === 'admin' ? (
|
||||
<ReferenceInput
|
||||
source="ownerId"
|
||||
|
||||
@@ -1,276 +0,0 @@
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
import {
|
||||
composePaths,
|
||||
computeLabel,
|
||||
createDefaultValue,
|
||||
isObjectArrayWithNesting,
|
||||
isPrimitiveArrayControl,
|
||||
rankWith,
|
||||
findUISchema,
|
||||
Resolve,
|
||||
} from '@jsonforms/core'
|
||||
import {
|
||||
JsonFormsDispatch,
|
||||
withJsonFormsArrayLayoutProps,
|
||||
} from '@jsonforms/react'
|
||||
import range from 'lodash/range'
|
||||
import merge from 'lodash/merge'
|
||||
import { Box, IconButton, Tooltip, Typography } from '@material-ui/core'
|
||||
import { Add, Delete } from '@material-ui/icons'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
arrayItem: {
|
||||
position: 'relative',
|
||||
padding: theme.spacing(2),
|
||||
marginBottom: theme.spacing(2),
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
'&:last-child': {
|
||||
marginBottom: 0,
|
||||
},
|
||||
},
|
||||
deleteButton: {
|
||||
position: 'absolute',
|
||||
top: theme.spacing(1),
|
||||
right: theme.spacing(1),
|
||||
},
|
||||
itemContent: {
|
||||
paddingRight: theme.spacing(4), // Space for delete button
|
||||
},
|
||||
}))
|
||||
|
||||
// Default translations for array controls
|
||||
const defaultTranslations = {
|
||||
addTooltip: 'Add',
|
||||
addAriaLabel: 'Add button',
|
||||
removeTooltip: 'Delete',
|
||||
removeAriaLabel: 'Delete button',
|
||||
noDataMessage: 'No data',
|
||||
}
|
||||
|
||||
// Simplified array item renderer - clean card layout
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
const ArrayItem = ({
|
||||
index,
|
||||
path,
|
||||
schema,
|
||||
uischema,
|
||||
uischemas,
|
||||
rootSchema,
|
||||
renderers,
|
||||
cells,
|
||||
enabled,
|
||||
removeItems,
|
||||
translations,
|
||||
disableRemove,
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
const childPath = composePaths(path, `${index}`)
|
||||
|
||||
const foundUISchema = useMemo(
|
||||
() =>
|
||||
findUISchema(
|
||||
uischemas,
|
||||
schema,
|
||||
uischema.scope,
|
||||
path,
|
||||
undefined,
|
||||
uischema,
|
||||
rootSchema,
|
||||
),
|
||||
[uischemas, schema, path, uischema, rootSchema],
|
||||
)
|
||||
|
||||
return (
|
||||
<Box className={classes.arrayItem}>
|
||||
{enabled && !disableRemove && (
|
||||
<Tooltip
|
||||
title={translations.removeTooltip}
|
||||
className={classes.deleteButton}
|
||||
>
|
||||
<IconButton
|
||||
onClick={() => removeItems(path, [index])()}
|
||||
size="small"
|
||||
aria-label={translations.removeAriaLabel}
|
||||
>
|
||||
<Delete fontSize="small" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Box className={classes.itemContent}>
|
||||
<JsonFormsDispatch
|
||||
enabled={enabled}
|
||||
schema={schema}
|
||||
uischema={foundUISchema}
|
||||
path={childPath}
|
||||
key={childPath}
|
||||
renderers={renderers}
|
||||
cells={cells}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
// Array toolbar with add button
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
const ArrayToolbar = ({
|
||||
label,
|
||||
description,
|
||||
enabled,
|
||||
addItem,
|
||||
path,
|
||||
createDefault,
|
||||
translations,
|
||||
disableAdd,
|
||||
}) => (
|
||||
<Box mb={1}>
|
||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||
<Typography variant="h6">{label}</Typography>
|
||||
{!disableAdd && (
|
||||
<Tooltip
|
||||
title={translations.addTooltip}
|
||||
aria-label={translations.addAriaLabel}
|
||||
>
|
||||
<IconButton
|
||||
onClick={addItem(path, createDefault())}
|
||||
disabled={!enabled}
|
||||
size="small"
|
||||
>
|
||||
<Add />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Box>
|
||||
{description && (
|
||||
<Typography variant="caption" color="textSecondary">
|
||||
{description}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
|
||||
const useArrayStyles = makeStyles((theme) => ({
|
||||
container: {
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
}))
|
||||
|
||||
// Main array layout component - items always expanded
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
const AlwaysExpandedArrayLayoutComponent = (props) => {
|
||||
const arrayClasses = useArrayStyles()
|
||||
const {
|
||||
enabled,
|
||||
data,
|
||||
path,
|
||||
schema,
|
||||
uischema,
|
||||
addItem,
|
||||
removeItems,
|
||||
renderers,
|
||||
cells,
|
||||
label,
|
||||
description,
|
||||
required,
|
||||
rootSchema,
|
||||
config,
|
||||
uischemas,
|
||||
disableAdd,
|
||||
disableRemove,
|
||||
} = props
|
||||
|
||||
const innerCreateDefaultValue = useCallback(
|
||||
() => createDefaultValue(schema, rootSchema),
|
||||
[schema, rootSchema],
|
||||
)
|
||||
|
||||
const appliedUiSchemaOptions = merge({}, config, uischema.options)
|
||||
const doDisableAdd = disableAdd || appliedUiSchemaOptions.disableAdd
|
||||
const doDisableRemove = disableRemove || appliedUiSchemaOptions.disableRemove
|
||||
const translations = defaultTranslations
|
||||
|
||||
return (
|
||||
<div className={arrayClasses.container}>
|
||||
<ArrayToolbar
|
||||
translations={translations}
|
||||
label={computeLabel(
|
||||
label,
|
||||
required,
|
||||
appliedUiSchemaOptions.hideRequiredAsterisk,
|
||||
)}
|
||||
description={description}
|
||||
path={path}
|
||||
enabled={enabled}
|
||||
addItem={addItem}
|
||||
createDefault={innerCreateDefaultValue}
|
||||
disableAdd={doDisableAdd}
|
||||
/>
|
||||
<div>
|
||||
{data > 0 ? (
|
||||
range(data).map((index) => (
|
||||
<ArrayItem
|
||||
key={index}
|
||||
index={index}
|
||||
path={path}
|
||||
schema={schema}
|
||||
uischema={uischema}
|
||||
uischemas={uischemas}
|
||||
rootSchema={rootSchema}
|
||||
renderers={renderers}
|
||||
cells={cells}
|
||||
enabled={enabled}
|
||||
removeItems={removeItems}
|
||||
translations={translations}
|
||||
disableRemove={doDisableRemove}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<Typography color="textSecondary">
|
||||
{translations.noDataMessage}
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Wrap with JSONForms HOC
|
||||
const WrappedArrayLayout = withJsonFormsArrayLayoutProps(
|
||||
AlwaysExpandedArrayLayoutComponent,
|
||||
)
|
||||
|
||||
// Custom tester that matches arrays but NOT enum arrays
|
||||
// Enum arrays should be handled by MaterialEnumArrayRenderer (for checkboxes)
|
||||
const isNonEnumArrayControl = (uischema, schema) => {
|
||||
// First check if it matches our base conditions (object array or primitive array)
|
||||
const baseCheck =
|
||||
isObjectArrayWithNesting(uischema, schema) ||
|
||||
isPrimitiveArrayControl(uischema, schema)
|
||||
|
||||
if (!baseCheck) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Resolve the actual schema for this control using JSONForms utility
|
||||
const rootSchema = schema
|
||||
const resolved = Resolve.schema(rootSchema, uischema?.scope, rootSchema)
|
||||
|
||||
// Exclude enum arrays (uniqueItems + oneOf/enum) - let MaterialEnumArrayRenderer handle them
|
||||
if (resolved?.uniqueItems && resolved?.items) {
|
||||
const { items } = resolved
|
||||
if (items.oneOf?.every((e) => e.const !== undefined) || items.enum) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Export as a renderer entry with high priority (5 > default 4)
|
||||
// Matches both object arrays with nesting and primitive arrays, but NOT enum arrays
|
||||
export const AlwaysExpandedArrayLayout = {
|
||||
tester: rankWith(5, isNonEnumArrayControl),
|
||||
renderer: WrappedArrayLayout,
|
||||
}
|
||||
@@ -4,76 +4,37 @@ import { Card, CardContent, Typography, Box } from '@material-ui/core'
|
||||
import Alert from '@material-ui/lab/Alert'
|
||||
import { SchemaConfigEditor } from './SchemaConfigEditor'
|
||||
|
||||
// Navigate schema by path parts to find the title for a field
|
||||
const findFieldTitle = (schema, parts) => {
|
||||
// Format error with field title and full path for nested fields
|
||||
const formatError = (error, schema) => {
|
||||
// Get path parts from various error formats
|
||||
const rawPath =
|
||||
error.dataPath || error.property || error.instancePath?.replace(/\//g, '.')
|
||||
const parts = rawPath?.split('.').filter(Boolean) || []
|
||||
|
||||
// Navigate schema to find field title, build bracket-notation path
|
||||
let currentSchema = schema
|
||||
let fieldName = parts[parts.length - 1] // Default to last part
|
||||
let fieldName = parts[parts.length - 1]
|
||||
const pathParts = []
|
||||
|
||||
for (const part of parts) {
|
||||
if (!currentSchema) break
|
||||
|
||||
// Skip array indices (just move to items schema)
|
||||
if (/^\d+$/.test(part)) {
|
||||
if (currentSchema.items) {
|
||||
currentSchema = currentSchema.items
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Navigate to property and always update fieldName
|
||||
if (currentSchema.properties?.[part]) {
|
||||
const propSchema = currentSchema.properties[part]
|
||||
fieldName = propSchema.title || part
|
||||
currentSchema = propSchema
|
||||
pathParts.push(`[${part}]`)
|
||||
currentSchema = currentSchema?.items
|
||||
} else {
|
||||
fieldName = currentSchema?.properties?.[part]?.title || part
|
||||
pathParts.push(part)
|
||||
currentSchema = currentSchema?.properties?.[part]
|
||||
}
|
||||
}
|
||||
|
||||
return fieldName
|
||||
}
|
||||
const path = pathParts.join('.').replace(/\.\[/g, '[')
|
||||
const isNested = path.includes('[') || path.includes('.')
|
||||
// Replace property name in message with full path for nested fields
|
||||
const message = isNested
|
||||
? error.message.replace(/'[^']+'\s*$/, `'${path}'`)
|
||||
: error.message
|
||||
|
||||
// Extract human-readable field name from JSONForms error
|
||||
const getFieldName = (error, schema) => {
|
||||
// JSONForms errors can have different path formats:
|
||||
// - dataPath: "users.1.token" (dot-separated)
|
||||
// - instancePath: "/users/1/token" (slash-separated)
|
||||
// - property: "users.1.username" (dot-separated)
|
||||
const dataPath = error.dataPath || ''
|
||||
const instancePath = error.instancePath || ''
|
||||
const property = error.property || ''
|
||||
|
||||
// Try dataPath first (dot-separated like "users.1.token")
|
||||
if (dataPath) {
|
||||
const parts = dataPath.split('.').filter(Boolean)
|
||||
if (parts.length > 0) {
|
||||
return findFieldTitle(schema, parts)
|
||||
}
|
||||
}
|
||||
|
||||
// Try property (also dot-separated)
|
||||
if (property) {
|
||||
const parts = property.split('.').filter(Boolean)
|
||||
if (parts.length > 0) {
|
||||
return findFieldTitle(schema, parts)
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to instancePath (slash-separated like "/users/1/token")
|
||||
if (instancePath) {
|
||||
const parts = instancePath.split('/').filter(Boolean)
|
||||
if (parts.length > 0) {
|
||||
return findFieldTitle(schema, parts)
|
||||
}
|
||||
}
|
||||
|
||||
// Try to extract from schemaPath like "#/properties/users/items/properties/username/minLength"
|
||||
const schemaPath = error.schemaPath || ''
|
||||
const propMatches = [...schemaPath.matchAll(/\/properties\/([^/]+)/g)]
|
||||
if (propMatches.length > 0) {
|
||||
const parts = propMatches.map((m) => m[1])
|
||||
return findFieldTitle(schema, parts)
|
||||
}
|
||||
|
||||
return null
|
||||
return { fieldName, message }
|
||||
}
|
||||
|
||||
export const ConfigCard = ({
|
||||
@@ -99,14 +60,10 @@ export const ConfigCard = ({
|
||||
|
||||
// Format validation errors with proper field names
|
||||
const formattedErrors = useMemo(() => {
|
||||
if (!hasConfigSchema) {
|
||||
return []
|
||||
}
|
||||
const { schema } = manifest.config
|
||||
return validationErrors.map((error) => ({
|
||||
fieldName: getFieldName(error, schema),
|
||||
message: error.message,
|
||||
}))
|
||||
if (!hasConfigSchema) return []
|
||||
return validationErrors.map((error) =>
|
||||
formatError(error, manifest.config.schema),
|
||||
)
|
||||
}, [validationErrors, manifest, hasConfigSchema])
|
||||
|
||||
if (!hasConfigSchema) {
|
||||
@@ -139,12 +96,14 @@ export const ConfigCard = ({
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<SchemaConfigEditor
|
||||
schema={schema}
|
||||
uiSchema={uiSchema}
|
||||
data={configData}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<Box mt={formattedErrors.length > 0 ? 0 : 2}>
|
||||
<SchemaConfigEditor
|
||||
schema={schema}
|
||||
uiSchema={uiSchema}
|
||||
data={configData}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
|
||||
@@ -40,18 +40,14 @@ const useStyles = makeStyles(
|
||||
|
||||
/**
|
||||
* Hook for common control state (focus, validation, description visibility)
|
||||
* Tracks "touched" state to only show errors after the user has interacted with the field
|
||||
*/
|
||||
const useControlState = (props) => {
|
||||
const { config, uischema, description, visible, errors } = props
|
||||
const [isFocused, setIsFocused] = useState(false)
|
||||
const [isTouched, setIsTouched] = useState(false)
|
||||
|
||||
const appliedUiSchemaOptions = merge({}, config, uischema?.options)
|
||||
// errors is a string when there are validation errors, empty/undefined when valid
|
||||
const hasErrors = errors && errors.length > 0
|
||||
// Only show as invalid after the field has been touched (blurred)
|
||||
const showError = isTouched && hasErrors
|
||||
const showError = errors && errors.length > 0
|
||||
|
||||
const showDescription = !isDescriptionHidden(
|
||||
visible,
|
||||
@@ -63,10 +59,7 @@ const useControlState = (props) => {
|
||||
const helperText = showError ? errors : showDescription ? description : ''
|
||||
|
||||
const handleFocus = () => setIsFocused(true)
|
||||
const handleBlur = () => {
|
||||
setIsFocused(false)
|
||||
setIsTouched(true)
|
||||
}
|
||||
const handleBlur = () => setIsFocused(false)
|
||||
|
||||
return {
|
||||
isFocused,
|
||||
@@ -220,9 +213,6 @@ const OutlinedEnumControl = (props) => {
|
||||
label={label}
|
||||
fullWidth
|
||||
>
|
||||
<MenuItem value="">
|
||||
<em>None</em>
|
||||
</MenuItem>
|
||||
{options?.map((option) => (
|
||||
<MenuItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { makeStyles } from '@material-ui/core/styles'
|
||||
import { Typography } from '@material-ui/core'
|
||||
import { useTranslate } from 'react-admin'
|
||||
import Ajv from 'ajv'
|
||||
import { AlwaysExpandedArrayLayout } from './AlwaysExpandedArrayLayout'
|
||||
import {
|
||||
OutlinedTextRenderer,
|
||||
OutlinedNumberRenderer,
|
||||
@@ -135,7 +134,6 @@ const customRenderers = [
|
||||
OutlinedNumberRenderer,
|
||||
OutlinedEnumRenderer,
|
||||
OutlinedOneOfEnumRenderer,
|
||||
AlwaysExpandedArrayLayout,
|
||||
// Then all the standard material renderers
|
||||
...materialRenderers,
|
||||
]
|
||||
|
||||
@@ -12,6 +12,7 @@ import CatppuccinMacchiatoTheme from './catppuccinMacchiato'
|
||||
import NuclearTheme from './nuclear'
|
||||
import AmusicTheme from './amusic'
|
||||
import SquiddiesGlassTheme from './SquiddiesGlass'
|
||||
import NautilineTheme from './nautiline'
|
||||
|
||||
export default {
|
||||
// Classic default themes
|
||||
@@ -27,6 +28,7 @@ export default {
|
||||
GruvboxDarkTheme,
|
||||
LigeraTheme,
|
||||
MonokaiTheme,
|
||||
NautilineTheme,
|
||||
NordTheme,
|
||||
NuclearTheme,
|
||||
SpotifyTheme,
|
||||
|
||||
905
ui/src/themes/nautiline.js
Normal file
905
ui/src/themes/nautiline.js
Normal file
@@ -0,0 +1,905 @@
|
||||
/**
|
||||
* Nautiline Theme for Navidrome
|
||||
* Light theme inspired by the Nautiline iOS app
|
||||
*/
|
||||
|
||||
// ============================================
|
||||
// CONFIGURATION
|
||||
// ============================================
|
||||
|
||||
const ACCENT_COLOR = '#009688' // Material teal
|
||||
|
||||
// ============================================
|
||||
// DESIGN TOKENS
|
||||
// ============================================
|
||||
|
||||
const hexToRgb = (hex) => {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
|
||||
return result
|
||||
? {
|
||||
r: parseInt(result[1], 16),
|
||||
g: parseInt(result[2], 16),
|
||||
b: parseInt(result[3], 16),
|
||||
}
|
||||
: null
|
||||
}
|
||||
|
||||
const rgb = hexToRgb(ACCENT_COLOR)
|
||||
const rgba = (alpha) =>
|
||||
rgb ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})` : 'transparent'
|
||||
|
||||
const tokens = {
|
||||
colors: {
|
||||
accent: {
|
||||
main: ACCENT_COLOR,
|
||||
faded: rgba(0.1),
|
||||
hover: rgba(0.15),
|
||||
},
|
||||
background: {
|
||||
primary: '#FFFFFF',
|
||||
secondary: '#F5F5F7',
|
||||
tertiary: '#E5E5EA',
|
||||
},
|
||||
text: {
|
||||
primary: '#1A1A1A',
|
||||
secondary: '#8E8E93',
|
||||
tertiary: '#AEAEB2',
|
||||
},
|
||||
ui: {
|
||||
separator: 'rgba(0, 0, 0, 0.08)',
|
||||
shadow: 'rgba(0, 0, 0, 0.04)',
|
||||
glassBg: 'rgba(255, 255, 255, 0.72)',
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontFamily: {
|
||||
base: [
|
||||
'-apple-system',
|
||||
'BlinkMacSystemFont',
|
||||
'"SF Pro Text"',
|
||||
'"Helvetica Neue"',
|
||||
'Arial',
|
||||
'sans-serif',
|
||||
].join(','),
|
||||
heading: '"Unbounded", sans-serif',
|
||||
},
|
||||
fontFace: `
|
||||
@font-face {
|
||||
font-family: 'Unbounded';
|
||||
font-style: normal;
|
||||
font-weight: 300 800;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Unbounded-Variable.woff2') format('woff2');
|
||||
}
|
||||
`,
|
||||
},
|
||||
spacing: {
|
||||
xs: '0.25rem',
|
||||
sm: '0.5rem',
|
||||
md: '0.75rem',
|
||||
lg: '1rem',
|
||||
xl: '1.5rem',
|
||||
},
|
||||
radii: {
|
||||
sm: '0.25rem',
|
||||
md: '0.5rem',
|
||||
lg: '0.625rem',
|
||||
xl: '0.75rem',
|
||||
full: '50%',
|
||||
pill: '1rem',
|
||||
},
|
||||
breakpoints: {
|
||||
xs: 599,
|
||||
sm: 600,
|
||||
md: 720,
|
||||
lg: 1280,
|
||||
},
|
||||
sizing: {
|
||||
cover: {
|
||||
sm: '14em',
|
||||
lg: '18em',
|
||||
},
|
||||
icon: '1.25rem',
|
||||
iconMinWidth: '2.5rem',
|
||||
},
|
||||
blur: '1.25rem',
|
||||
}
|
||||
|
||||
const { colors, typography, spacing, radii, sizing, breakpoints } = tokens
|
||||
|
||||
// ============================================
|
||||
// REUSABLE STYLE FACTORIES
|
||||
// ============================================
|
||||
|
||||
const headingStyle = (weight, letterSpacing) => ({
|
||||
fontFamily: typography.fontFamily.heading,
|
||||
fontWeight: weight,
|
||||
...(letterSpacing && { letterSpacing }),
|
||||
})
|
||||
|
||||
const coverSizing = () => ({
|
||||
[`@media (min-width: ${breakpoints.sm}px)`]: {
|
||||
height: sizing.cover.sm,
|
||||
width: sizing.cover.sm,
|
||||
minWidth: sizing.cover.sm,
|
||||
},
|
||||
[`@media (min-width: ${breakpoints.lg}px)`]: {
|
||||
height: sizing.cover.lg,
|
||||
width: sizing.cover.lg,
|
||||
minWidth: sizing.cover.lg,
|
||||
},
|
||||
})
|
||||
|
||||
const customTooltipStyle = () => ({
|
||||
display: 'inline',
|
||||
position: 'absolute',
|
||||
bottom: '100%',
|
||||
left: '50%',
|
||||
transform: 'translateX(-50%)',
|
||||
marginBottom: spacing.xs,
|
||||
fontSize: '0.75rem',
|
||||
whiteSpace: 'nowrap',
|
||||
backgroundColor: colors.text.primary,
|
||||
color: colors.background.primary,
|
||||
padding: `${spacing.xs} ${spacing.sm}`,
|
||||
borderRadius: radii.sm,
|
||||
zIndex: 9999,
|
||||
})
|
||||
|
||||
const actionButtonsStyle = () => ({
|
||||
padding: `${spacing.lg} 0`,
|
||||
alignItems: 'center',
|
||||
'@global': {
|
||||
button: {
|
||||
border: '1px solid transparent',
|
||||
backgroundColor: colors.background.secondary,
|
||||
color: colors.text.secondary,
|
||||
margin: `0 ${spacing.sm}`,
|
||||
borderRadius: radii.full,
|
||||
minWidth: 0,
|
||||
padding: spacing.lg,
|
||||
position: 'relative',
|
||||
'&:hover': {
|
||||
backgroundColor: `${colors.background.tertiary} !important`,
|
||||
border: '1px solid transparent',
|
||||
},
|
||||
},
|
||||
'button:first-child:not(:only-child)': {
|
||||
[`@media screen and (max-width: ${breakpoints.md}px)`]: {
|
||||
transform: 'scale(1.5)',
|
||||
margin: spacing.lg,
|
||||
'&:hover': {
|
||||
transform: 'scale(1.6) !important',
|
||||
},
|
||||
},
|
||||
transform: 'scale(2)',
|
||||
margin: spacing.xl,
|
||||
minWidth: 0,
|
||||
padding: '0.3125rem',
|
||||
transition: 'transform .3s ease',
|
||||
background: colors.accent.main,
|
||||
color: '#fff',
|
||||
borderRadius: radii.full,
|
||||
border: 0,
|
||||
'&:hover': {
|
||||
transform: 'scale(2.1)',
|
||||
backgroundColor: `${colors.accent.main} !important`,
|
||||
border: 0,
|
||||
},
|
||||
},
|
||||
'button:only-child': {
|
||||
margin: spacing.xl,
|
||||
},
|
||||
'button:first-child>span:first-child': {
|
||||
padding: 0,
|
||||
},
|
||||
'button>span:first-child>span': {
|
||||
display: 'none',
|
||||
},
|
||||
'button:not(:first-child):hover>span:first-child>span':
|
||||
customTooltipStyle(),
|
||||
'button:not(:first-child)>span:first-child>svg': {
|
||||
color: colors.text.secondary,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const menuIconStyle = () => ({
|
||||
color: colors.text.primary,
|
||||
minWidth: sizing.iconMinWidth,
|
||||
'& svg': {
|
||||
fontSize: sizing.icon,
|
||||
},
|
||||
})
|
||||
|
||||
const activeLinkStyle = {
|
||||
color: `${colors.accent.main} !important`,
|
||||
'& .MuiListItemIcon-root': {
|
||||
color: `${colors.accent.main} !important`,
|
||||
},
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// THEME DEFINITION
|
||||
// ============================================
|
||||
|
||||
// Note: !important declarations are required to override react-admin and third-party component styles
|
||||
const NautilineTheme = {
|
||||
themeName: 'Nautiline',
|
||||
palette: {
|
||||
type: 'light',
|
||||
primary: {
|
||||
main: colors.accent.main,
|
||||
contrastText: '#FFFFFF',
|
||||
},
|
||||
secondary: {
|
||||
main: colors.accent.main,
|
||||
contrastText: '#FFFFFF',
|
||||
},
|
||||
background: {
|
||||
default: colors.background.primary,
|
||||
paper: colors.background.primary,
|
||||
},
|
||||
text: {
|
||||
primary: colors.text.primary,
|
||||
secondary: colors.text.secondary,
|
||||
},
|
||||
action: {
|
||||
active: colors.accent.main,
|
||||
hover: colors.accent.faded,
|
||||
selected: colors.accent.faded,
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontFamily: typography.fontFamily.base,
|
||||
h1: headingStyle(700, '-0.02em'),
|
||||
h2: headingStyle(700, '-0.02em'),
|
||||
h3: headingStyle(600, '-0.01em'),
|
||||
h4: headingStyle(600),
|
||||
h5: headingStyle(600),
|
||||
h6: headingStyle(600),
|
||||
subtitle1: { fontWeight: 500 },
|
||||
subtitle2: { fontWeight: 500 },
|
||||
body1: { fontWeight: 400 },
|
||||
body2: { fontWeight: 400 },
|
||||
button: { fontWeight: 500, textTransform: 'none' },
|
||||
},
|
||||
shape: {
|
||||
borderRadius: radii.xl,
|
||||
},
|
||||
overrides: {
|
||||
MuiCssBaseline: {
|
||||
'@global': {
|
||||
'@font-face': {
|
||||
fontFamily: 'Unbounded',
|
||||
fontStyle: 'normal',
|
||||
fontWeight: '300 800',
|
||||
fontDisplay: 'swap',
|
||||
src: "url('/fonts/Unbounded-Variable.woff2') format('woff2')",
|
||||
},
|
||||
body: {
|
||||
backgroundColor: colors.background.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiAppBar: {
|
||||
root: {
|
||||
boxShadow: 'none',
|
||||
borderBottom: `1px solid ${colors.ui.separator}`,
|
||||
},
|
||||
colorSecondary: {
|
||||
backgroundColor: colors.background.primary,
|
||||
color: colors.text.primary,
|
||||
},
|
||||
},
|
||||
MuiToolbar: {
|
||||
root: {
|
||||
backgroundColor: colors.background.primary,
|
||||
},
|
||||
},
|
||||
MuiPaper: {
|
||||
root: {
|
||||
backgroundColor: colors.background.primary,
|
||||
},
|
||||
elevation1: {
|
||||
boxShadow: `0 0.0625rem 0.1875rem ${colors.ui.shadow}`,
|
||||
},
|
||||
elevation2: {
|
||||
boxShadow: `0 0.125rem ${spacing.sm} ${colors.ui.shadow}`,
|
||||
},
|
||||
},
|
||||
MuiCard: {
|
||||
root: {
|
||||
backgroundColor: colors.background.primary,
|
||||
borderRadius: radii.xl,
|
||||
boxShadow: `0 0.125rem ${spacing.sm} ${colors.ui.shadow}`,
|
||||
},
|
||||
},
|
||||
MuiButton: {
|
||||
root: {
|
||||
borderRadius: radii.md,
|
||||
textTransform: 'none',
|
||||
fontWeight: 600,
|
||||
},
|
||||
contained: {
|
||||
boxShadow: 'none',
|
||||
'&:hover': { boxShadow: 'none' },
|
||||
},
|
||||
containedPrimary: {
|
||||
backgroundColor: colors.accent.main,
|
||||
'&:hover': {
|
||||
backgroundColor: colors.accent.main,
|
||||
filter: 'brightness(0.9)',
|
||||
},
|
||||
},
|
||||
text: {
|
||||
color: colors.accent.main,
|
||||
},
|
||||
},
|
||||
MuiIconButton: {
|
||||
root: {
|
||||
color: colors.text.primary,
|
||||
'&:hover': {
|
||||
backgroundColor: colors.accent.faded,
|
||||
},
|
||||
},
|
||||
colorPrimary: {
|
||||
color: colors.accent.main,
|
||||
},
|
||||
sizeSmall: {
|
||||
padding: spacing.md,
|
||||
},
|
||||
},
|
||||
MuiSvgIcon: {
|
||||
colorPrimary: {
|
||||
color: colors.accent.main,
|
||||
},
|
||||
},
|
||||
MuiCheckbox: {
|
||||
root: {
|
||||
color: 'rgba(0, 0, 0, 0.15)',
|
||||
'&$checked': {
|
||||
color: colors.accent.main,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiChip: {
|
||||
root: {
|
||||
backgroundColor: colors.background.secondary,
|
||||
color: colors.text.primary,
|
||||
borderRadius: radii.pill,
|
||||
},
|
||||
colorPrimary: {
|
||||
backgroundColor: colors.accent.faded,
|
||||
color: colors.accent.main,
|
||||
},
|
||||
},
|
||||
MuiTableRow: {
|
||||
root: {
|
||||
'&:hover': {
|
||||
backgroundColor: `${colors.accent.faded} !important`,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTableCell: {
|
||||
root: {
|
||||
borderBottomColor: 'rgba(0, 0, 0, 0.04)',
|
||||
},
|
||||
head: {
|
||||
backgroundColor: colors.background.secondary,
|
||||
color: colors.text.secondary,
|
||||
fontWeight: 600,
|
||||
fontSize: '0.75rem',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.05em',
|
||||
},
|
||||
body: {
|
||||
color: colors.text.primary,
|
||||
},
|
||||
},
|
||||
MuiListItem: {
|
||||
root: {
|
||||
color: colors.text.primary,
|
||||
'&:hover': {
|
||||
backgroundColor: colors.accent.faded,
|
||||
},
|
||||
'&$selected': {
|
||||
backgroundColor: colors.accent.faded,
|
||||
color: colors.accent.main,
|
||||
'& .MuiListItemIcon-root': {
|
||||
color: colors.accent.main,
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: colors.accent.faded,
|
||||
},
|
||||
},
|
||||
},
|
||||
button: {
|
||||
color: colors.text.primary,
|
||||
'&:hover': {
|
||||
backgroundColor: colors.accent.faded,
|
||||
color: colors.text.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiListItemIcon: {
|
||||
root: menuIconStyle(),
|
||||
},
|
||||
MuiListItemText: {
|
||||
primary: {
|
||||
color: 'inherit',
|
||||
},
|
||||
},
|
||||
MuiMenuItem: {
|
||||
root: {
|
||||
fontSize: '0.875rem',
|
||||
paddingTop: '4px',
|
||||
paddingBottom: '4px',
|
||||
paddingLeft: '10px',
|
||||
margin: '5px',
|
||||
borderRadius: radii.md,
|
||||
color: colors.text.primary,
|
||||
},
|
||||
},
|
||||
MuiDrawer: {
|
||||
paper: {
|
||||
backgroundColor: colors.background.primary,
|
||||
borderRight: `1px solid ${colors.ui.separator}`,
|
||||
},
|
||||
},
|
||||
MuiSlider: {
|
||||
root: {
|
||||
color: colors.accent.main,
|
||||
},
|
||||
track: {
|
||||
backgroundColor: colors.accent.main,
|
||||
},
|
||||
thumb: {
|
||||
backgroundColor: colors.accent.main,
|
||||
'&:hover': {
|
||||
boxShadow: `0 0 0 ${spacing.sm} ${colors.accent.faded}`,
|
||||
},
|
||||
},
|
||||
rail: {
|
||||
backgroundColor: colors.background.tertiary,
|
||||
},
|
||||
},
|
||||
MuiLinearProgress: {
|
||||
root: {
|
||||
backgroundColor: colors.background.tertiary,
|
||||
borderRadius: radii.sm,
|
||||
},
|
||||
bar: {
|
||||
backgroundColor: colors.accent.main,
|
||||
borderRadius: radii.sm,
|
||||
},
|
||||
},
|
||||
MuiTabs: {
|
||||
root: {
|
||||
borderBottom: `1px solid ${colors.ui.separator}`,
|
||||
},
|
||||
indicator: {
|
||||
backgroundColor: colors.accent.main,
|
||||
height: '0.1875rem',
|
||||
borderRadius: '0.1875rem 0.1875rem 0 0',
|
||||
},
|
||||
},
|
||||
MuiTab: {
|
||||
root: {
|
||||
textTransform: 'none',
|
||||
fontWeight: 500,
|
||||
fontFamily: typography.fontFamily.heading,
|
||||
'&$selected': {
|
||||
color: colors.accent.main,
|
||||
fontWeight: 600,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiInputBase: {
|
||||
root: {
|
||||
backgroundColor: colors.background.secondary,
|
||||
borderRadius: radii.lg,
|
||||
},
|
||||
},
|
||||
MuiOutlinedInput: {
|
||||
root: {
|
||||
borderRadius: radii.lg,
|
||||
'& $notchedOutline': {
|
||||
borderColor: colors.ui.separator,
|
||||
},
|
||||
'&:hover $notchedOutline': {
|
||||
borderColor: colors.text.tertiary,
|
||||
},
|
||||
'&$focused $notchedOutline': {
|
||||
borderColor: colors.accent.main,
|
||||
borderWidth: '0.125rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiFilledInput: {
|
||||
root: {
|
||||
backgroundColor: colors.background.secondary,
|
||||
borderRadius: radii.lg,
|
||||
'&:hover': {
|
||||
backgroundColor: colors.background.tertiary,
|
||||
},
|
||||
'&$focused': {
|
||||
backgroundColor: colors.background.secondary,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiFab: {
|
||||
primary: {
|
||||
backgroundColor: colors.accent.main,
|
||||
'&:hover': {
|
||||
backgroundColor: colors.accent.main,
|
||||
filter: 'brightness(0.9)',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiAvatar: {
|
||||
root: {
|
||||
borderRadius: radii.md,
|
||||
},
|
||||
},
|
||||
MuiRating: {
|
||||
iconFilled: {
|
||||
color: colors.accent.main,
|
||||
},
|
||||
iconHover: {
|
||||
color: colors.accent.main,
|
||||
},
|
||||
},
|
||||
MuiTooltip: {
|
||||
tooltip: {
|
||||
backgroundColor: colors.text.primary,
|
||||
color: colors.background.primary,
|
||||
fontSize: '0.75rem',
|
||||
padding: `${spacing.xs} ${spacing.sm}`,
|
||||
borderRadius: radii.sm,
|
||||
},
|
||||
},
|
||||
MuiBottomNavigation: {
|
||||
root: {
|
||||
backgroundColor: colors.ui.glassBg,
|
||||
backdropFilter: `blur(${tokens.blur})`,
|
||||
borderTop: `1px solid ${colors.ui.separator}`,
|
||||
},
|
||||
},
|
||||
MuiBottomNavigationAction: {
|
||||
root: {
|
||||
color: colors.text.secondary,
|
||||
'&$selected': {
|
||||
color: colors.accent.main,
|
||||
},
|
||||
},
|
||||
label: {
|
||||
fontFamily: typography.fontFamily.heading,
|
||||
fontSize: '0.65rem',
|
||||
'&$selected': {
|
||||
fontSize: '0.65rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
NDAppBar: {
|
||||
root: {
|
||||
color: colors.text.primary,
|
||||
},
|
||||
},
|
||||
NDLogin: {
|
||||
main: {
|
||||
backgroundColor: colors.background.primary,
|
||||
},
|
||||
card: {
|
||||
backgroundColor: colors.background.primary,
|
||||
borderRadius: radii.pill,
|
||||
boxShadow: `0 ${spacing.xs} ${spacing.xl} ${colors.ui.shadow}`,
|
||||
},
|
||||
},
|
||||
NDAlbumGridView: {
|
||||
albumContainer: {
|
||||
borderRadius: radii.md,
|
||||
'& img': {
|
||||
borderRadius: radii.md,
|
||||
},
|
||||
},
|
||||
albumTitle: {
|
||||
fontWeight: 600,
|
||||
color: colors.text.primary,
|
||||
},
|
||||
albumSubtitle: {
|
||||
color: colors.text.secondary,
|
||||
},
|
||||
albumPlayButton: {
|
||||
backgroundColor: colors.accent.main,
|
||||
borderRadius: radii.full,
|
||||
boxShadow: `0 ${spacing.sm} ${spacing.sm} rgba(0, 0, 0, 0.15)`,
|
||||
padding: '0.35rem',
|
||||
transition: 'padding .3s ease',
|
||||
'&:hover': {
|
||||
backgroundColor: `${colors.accent.main} !important`,
|
||||
padding: '0.45rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
NDAlbumDetails: {
|
||||
root: {
|
||||
[`@media (max-width: ${breakpoints.xs}px)`]: {
|
||||
padding: '0.7em',
|
||||
width: '100%',
|
||||
minWidth: 'unset',
|
||||
},
|
||||
},
|
||||
cardContents: {
|
||||
[`@media (max-width: ${breakpoints.xs}px)`]: {
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
},
|
||||
},
|
||||
details: {
|
||||
[`@media (max-width: ${breakpoints.xs}px)`]: {
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
cover: {
|
||||
borderRadius: radii.md,
|
||||
},
|
||||
coverParent: {
|
||||
marginRight: spacing.xl,
|
||||
[`@media (max-width: ${breakpoints.xs}px)`]: {
|
||||
width: '100%',
|
||||
height: 'auto',
|
||||
minWidth: 'unset',
|
||||
aspectRatio: '1',
|
||||
marginRight: 0,
|
||||
marginBottom: spacing.lg,
|
||||
},
|
||||
...coverSizing(),
|
||||
},
|
||||
recordName: {
|
||||
fontSize: '1.75rem',
|
||||
fontWeight: 700,
|
||||
marginBottom: '0.15rem',
|
||||
},
|
||||
recordArtist: {
|
||||
marginBottom: spacing.md,
|
||||
},
|
||||
recordMeta: {
|
||||
marginBottom: spacing.sm,
|
||||
},
|
||||
genreList: {
|
||||
marginTop: spacing.md,
|
||||
},
|
||||
loveButton: {
|
||||
marginLeft: spacing.sm,
|
||||
},
|
||||
},
|
||||
NDAlbumShow: {
|
||||
albumActions: actionButtonsStyle(),
|
||||
},
|
||||
NDPlaylistShow: {
|
||||
playlistActions: actionButtonsStyle(),
|
||||
},
|
||||
NDSubMenu: {
|
||||
icon: menuIconStyle(),
|
||||
menuHeader: {
|
||||
color: colors.text.primary,
|
||||
'& .MuiTypography-root': {
|
||||
color: colors.text.primary,
|
||||
},
|
||||
},
|
||||
actionIcon: {
|
||||
marginLeft: spacing.sm,
|
||||
},
|
||||
},
|
||||
RaMenuItemLink: {
|
||||
root: {
|
||||
color: `${colors.text.primary} !important`,
|
||||
'& .MuiListItemIcon-root': menuIconStyle(),
|
||||
'&[class*="makeStyles-active"]': activeLinkStyle,
|
||||
},
|
||||
active: activeLinkStyle,
|
||||
},
|
||||
NDDesktopArtistDetails: {
|
||||
root: {
|
||||
[`@media (min-width: ${breakpoints.sm}px)`]: {
|
||||
padding: '1em',
|
||||
},
|
||||
[`@media (min-width: ${breakpoints.lg}px)`]: {
|
||||
padding: '1em',
|
||||
},
|
||||
},
|
||||
cover: {
|
||||
borderRadius: radii.md,
|
||||
...coverSizing(),
|
||||
},
|
||||
artistImage: {
|
||||
borderRadius: radii.md,
|
||||
marginRight: spacing.xl,
|
||||
[`@media (min-width: ${breakpoints.sm}px)`]: {
|
||||
height: sizing.cover.sm,
|
||||
width: sizing.cover.sm,
|
||||
minWidth: sizing.cover.sm,
|
||||
maxHeight: sizing.cover.sm,
|
||||
minHeight: sizing.cover.sm,
|
||||
},
|
||||
[`@media (min-width: ${breakpoints.lg}px)`]: {
|
||||
height: sizing.cover.lg,
|
||||
width: sizing.cover.lg,
|
||||
minWidth: sizing.cover.lg,
|
||||
maxHeight: sizing.cover.lg,
|
||||
minHeight: sizing.cover.lg,
|
||||
},
|
||||
},
|
||||
artistName: {
|
||||
fontSize: '1.75rem',
|
||||
fontWeight: 700,
|
||||
marginBottom: spacing.sm,
|
||||
},
|
||||
},
|
||||
NDMobileArtistDetails: {
|
||||
cover: {
|
||||
borderRadius: radii.md,
|
||||
},
|
||||
artistImage: {
|
||||
borderRadius: radii.md,
|
||||
},
|
||||
},
|
||||
RaList: {
|
||||
content: {
|
||||
overflow: 'visible',
|
||||
},
|
||||
},
|
||||
RaBulkActionsToolbar: {
|
||||
topToolbar: {
|
||||
backgroundColor: 'transparent',
|
||||
boxShadow: 'none',
|
||||
padding: spacing.sm,
|
||||
'@global': {
|
||||
button: {
|
||||
border: '1px solid transparent',
|
||||
backgroundColor: colors.background.secondary,
|
||||
color: colors.text.secondary,
|
||||
margin: `0 ${spacing.xs}`,
|
||||
borderRadius: radii.full,
|
||||
minWidth: 0,
|
||||
padding: spacing.sm,
|
||||
position: 'relative',
|
||||
'&:hover': {
|
||||
backgroundColor: `${colors.background.tertiary} !important`,
|
||||
border: '1px solid transparent',
|
||||
},
|
||||
},
|
||||
'button>span:first-child>span': {
|
||||
display: 'none',
|
||||
},
|
||||
'button:hover>span:first-child>span': customTooltipStyle(),
|
||||
'button>span:first-child>svg': {
|
||||
color: colors.text.secondary,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RaPaginationActions: {
|
||||
currentPageButton: {
|
||||
backgroundColor: colors.accent.faded,
|
||||
},
|
||||
},
|
||||
},
|
||||
player: {
|
||||
theme: 'light',
|
||||
stylesheet: `
|
||||
@font-face {
|
||||
font-family: 'Unbounded';
|
||||
font-style: normal;
|
||||
font-weight: 300 800;
|
||||
font-display: swap;
|
||||
src: url('/fonts/Unbounded-Variable.woff2') format('woff2');
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main {
|
||||
background-color: ${colors.background.primary} !important;
|
||||
font-family: ${typography.fontFamily.base} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .music-player-panel {
|
||||
background-color: ${colors.ui.glassBg} !important;
|
||||
backdrop-filter: blur(${tokens.blur}) !important;
|
||||
-webkit-backdrop-filter: blur(${tokens.blur}) !important;
|
||||
border-top: 1px solid ${colors.ui.separator} !important;
|
||||
box-shadow: 0 -0.125rem 1.25rem rgba(0, 0, 0, 0.06) !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main svg {
|
||||
color: ${colors.text.primary} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main svg:hover {
|
||||
color: ${colors.accent.main} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .rc-slider-track,
|
||||
.react-jinke-music-player-main .rc-slider-handle {
|
||||
background-color: ${colors.accent.main} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .rc-slider-handle {
|
||||
border-color: ${colors.accent.main} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .rc-slider-rail {
|
||||
background-color: ${colors.background.secondary} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .rc-slider {
|
||||
height: 4px !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .rc-slider-rail,
|
||||
.react-jinke-music-player-main .rc-slider-track {
|
||||
height: 4px !important;
|
||||
border-radius: 2px !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .rc-slider-handle {
|
||||
width: 12px !important;
|
||||
height: 12px !important;
|
||||
margin-top: -4px !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .audio-lists-panel,
|
||||
.react-jinke-music-player-main .audio-lists-panel-content {
|
||||
background-color: ${colors.background.primary} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .audio-lists-panel-content .audio-item {
|
||||
background-color: transparent !important;
|
||||
color: ${colors.text.primary} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .audio-lists-panel-content .audio-item:hover {
|
||||
background-color: ${colors.accent.faded} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .audio-lists-panel-content .audio-item.playing {
|
||||
background-color: ${colors.accent.faded} !important;
|
||||
color: ${colors.accent.main} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .lyric-btn-active,
|
||||
.react-jinke-music-player-main .play-mode-title {
|
||||
color: ${colors.accent.main} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .music-player-panel .player-content .music-player-controller .music-player-info .music-player-title {
|
||||
color: ${colors.text.primary} !important;
|
||||
font-weight: 600 !important;
|
||||
font-family: ${typography.fontFamily.heading} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main .music-player-panel .player-content .music-player-controller .music-player-info .music-player-artist {
|
||||
color: ${colors.text.secondary} !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main.mini-player {
|
||||
background-color: ${colors.ui.glassBg} !important;
|
||||
backdrop-filter: blur(${tokens.blur}) !important;
|
||||
-webkit-backdrop-filter: blur(${tokens.blur}) !important;
|
||||
border-radius: ${radii.xl} !important;
|
||||
box-shadow: 0 ${spacing.xs} 1.25rem rgba(0, 0, 0, 0.08) !important;
|
||||
}
|
||||
|
||||
|
||||
.MuiTypography-h1,
|
||||
.MuiTypography-h2,
|
||||
.MuiTypography-h3,
|
||||
.MuiTypography-h4,
|
||||
.MuiTypography-h5,
|
||||
.MuiTypography-h6 {
|
||||
font-family: ${typography.fontFamily.heading} !important;
|
||||
}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
export default NautilineTheme
|
||||
Reference in New Issue
Block a user