From d51c97c648883e9c29e7b7c80a2eca77186e11dc Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 29 Apr 2025 13:23:41 +0200 Subject: [PATCH 1/9] Code style: All uppercase acronyms URL, ISRC, ID, HTTP --- internal/auth/auth.go | 2 +- internal/auth/strategy.go | 12 +++--- internal/backends/deezer/auth.go | 6 +-- internal/backends/deezer/client.go | 6 +-- internal/backends/deezer/client_test.go | 6 +-- internal/backends/deezer/deezer.go | 14 +++---- internal/backends/deezer/models.go | 6 +-- internal/backends/funkwhale/client.go | 12 +++--- internal/backends/funkwhale/client_test.go | 22 +++++----- internal/backends/funkwhale/models.go | 12 +++--- internal/backends/jspf/jspf.go | 6 +-- internal/backends/lastfm/auth.go | 10 ++--- internal/backends/lastfm/lastfm.go | 8 ++-- internal/backends/listenbrainz/client.go | 14 +++---- internal/backends/listenbrainz/client_test.go | 14 +++---- internal/backends/listenbrainz/models_test.go | 2 +- internal/backends/maloja/client.go | 12 +++--- internal/backends/maloja/client_test.go | 16 ++++---- internal/backends/spotify/client.go | 8 ++-- internal/backends/spotify/client_test.go | 6 +-- internal/backends/spotify/models.go | 20 +++++----- internal/backends/spotify/spotify.go | 40 +++++++++---------- internal/backends/spotifyhistory/models.go | 4 +- internal/cli/auth.go | 10 ++--- pkg/jspf/extensions.go | 4 +- pkg/jspf/extensions_test.go | 2 +- 26 files changed, 137 insertions(+), 137 deletions(-) diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 5ba05af..84c85b6 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -27,7 +27,7 @@ type OAuth2Authenticator interface { models.Backend // Returns OAuth2 config suitable for this backend - OAuth2Strategy(redirectUrl *url.URL) OAuth2Strategy + OAuth2Strategy(redirectURL *url.URL) OAuth2Strategy // Setup the OAuth2 client OAuth2Setup(token oauth2.TokenSource) error diff --git a/internal/auth/strategy.go b/internal/auth/strategy.go index 3d03fa4..7e3c265 100644 --- a/internal/auth/strategy.go +++ b/internal/auth/strategy.go @@ -24,14 +24,14 @@ import ( type OAuth2Strategy interface { Config() oauth2.Config - AuthCodeURL(verifier string, state string) AuthUrl + AuthCodeURL(verifier string, state string) AuthURL ExchangeToken(code CodeResponse, verifier string) (*oauth2.Token, error) } -type AuthUrl struct { +type AuthURL struct { // The URL the user must visit to approve access - Url string + URL string // Random state string passed on to the callback. // Leave empty if the service does not support state. State string @@ -56,10 +56,10 @@ func (s StandardStrategy) Config() oauth2.Config { return s.conf } -func (s StandardStrategy) AuthCodeURL(verifier string, state string) AuthUrl { +func (s StandardStrategy) AuthCodeURL(verifier string, state string) AuthURL { url := s.conf.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(verifier)) - return AuthUrl{ - Url: url, + return AuthURL{ + URL: url, State: state, Param: "code", } diff --git a/internal/backends/deezer/auth.go b/internal/backends/deezer/auth.go index aa30b04..0304dec 100644 --- a/internal/backends/deezer/auth.go +++ b/internal/backends/deezer/auth.go @@ -33,10 +33,10 @@ func (s deezerStrategy) Config() oauth2.Config { return s.conf } -func (s deezerStrategy) AuthCodeURL(verifier string, state string) auth.AuthUrl { +func (s deezerStrategy) AuthCodeURL(verifier string, state string) auth.AuthURL { url := s.conf.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(verifier)) - return auth.AuthUrl{ - Url: url, + return auth.AuthURL{ + URL: url, State: state, Param: "code", } diff --git a/internal/backends/deezer/client.go b/internal/backends/deezer/client.go index 3c3b740..05264ae 100644 --- a/internal/backends/deezer/client.go +++ b/internal/backends/deezer/client.go @@ -36,7 +36,7 @@ const MaxItemsPerGet = 1000 const DefaultRateLimitWaitSeconds = 5 type Client struct { - HttpClient *resty.Client + HTTPClient *resty.Client token oauth2.TokenSource } @@ -47,7 +47,7 @@ func NewClient(token oauth2.TokenSource) Client { client.SetHeader("User-Agent", version.UserAgent()) client.SetRetryCount(5) return Client{ - HttpClient: client, + HTTPClient: client, token: token, } } @@ -73,7 +73,7 @@ func (c Client) setToken(req *resty.Request) error { } func listRequest[T Result](c Client, path string, offset int, limit int) (result T, err error) { - request := c.HttpClient.R(). + request := c.HTTPClient.R(). SetQueryParams(map[string]string{ "index": strconv.Itoa(offset), "limit": strconv.Itoa(limit), diff --git a/internal/backends/deezer/client_test.go b/internal/backends/deezer/client_test.go index f8240f8..c90b01a 100644 --- a/internal/backends/deezer/client_test.go +++ b/internal/backends/deezer/client_test.go @@ -44,7 +44,7 @@ func TestGetUserHistory(t *testing.T) { token := oauth2.StaticTokenSource(&oauth2.Token{}) client := deezer.NewClient(token) - setupHttpMock(t, client.HttpClient.GetClient(), + setupHTTPMock(t, client.HTTPClient.GetClient(), "https://api.deezer.com/user/me/history", "testdata/user-history.json") @@ -65,7 +65,7 @@ func TestGetUserTracks(t *testing.T) { token := oauth2.StaticTokenSource(&oauth2.Token{}) client := deezer.NewClient(token) - setupHttpMock(t, client.HttpClient.GetClient(), + setupHTTPMock(t, client.HTTPClient.GetClient(), "https://api.deezer.com/user/me/tracks", "testdata/user-tracks.json") @@ -81,7 +81,7 @@ func TestGetUserTracks(t *testing.T) { assert.Equal("Outland", track1.Track.Album.Title) } -func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) { +func setupHTTPMock(t *testing.T, client *http.Client, url string, testDataPath string) { httpmock.ActivateNonDefault(client) responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath)) diff --git a/internal/backends/deezer/deezer.go b/internal/backends/deezer/deezer.go index e7d9762..7b6e1ad 100644 --- a/internal/backends/deezer/deezer.go +++ b/internal/backends/deezer/deezer.go @@ -31,7 +31,7 @@ import ( type DeezerApiBackend struct { client Client - clientId string + clientID string clientSecret string } @@ -50,19 +50,19 @@ func (b *DeezerApiBackend) Options() []models.BackendOption { } func (b *DeezerApiBackend) InitConfig(config *config.ServiceConfig) error { - b.clientId = config.GetString("client-id") + b.clientID = config.GetString("client-id") b.clientSecret = config.GetString("client-secret") return nil } -func (b *DeezerApiBackend) OAuth2Strategy(redirectUrl *url.URL) auth.OAuth2Strategy { +func (b *DeezerApiBackend) OAuth2Strategy(redirectURL *url.URL) auth.OAuth2Strategy { conf := oauth2.Config{ - ClientID: b.clientId, + ClientID: b.clientID, ClientSecret: b.clientSecret, Scopes: []string{ "offline_access,basic_access,listening_history", }, - RedirectURL: redirectUrl.String(), + RedirectURL: redirectURL.String(), Endpoint: oauth2.Endpoint{ AuthURL: "https://connect.deezer.com/oauth/auth.php", TokenURL: "https://connect.deezer.com/oauth/access_token.php", @@ -244,8 +244,8 @@ func (t Track) AsTrack() models.Track { info["music_service"] = "deezer.com" info["origin_url"] = t.Link info["deezer_id"] = t.Link - info["deezer_album_id"] = fmt.Sprintf("https://www.deezer.com/album/%v", t.Album.Id) - info["deezer_artist_id"] = fmt.Sprintf("https://www.deezer.com/artist/%v", t.Artist.Id) + info["deezer_album_id"] = fmt.Sprintf("https://www.deezer.com/album/%v", t.Album.ID) + info["deezer_artist_id"] = fmt.Sprintf("https://www.deezer.com/artist/%v", t.Artist.ID) return track } diff --git a/internal/backends/deezer/models.go b/internal/backends/deezer/models.go index 712cd73..85b569c 100644 --- a/internal/backends/deezer/models.go +++ b/internal/backends/deezer/models.go @@ -51,7 +51,7 @@ type HistoryResult struct { } type Track struct { - Id int `json:"id"` + ID int `json:"id"` Type string `json:"type"` Link string `json:"link"` Title string `json:"title"` @@ -75,7 +75,7 @@ type LovedTrack struct { } type Album struct { - Id int `json:"id"` + ID int `json:"id"` Type string `json:"type"` Link string `json:"link"` Title string `json:"title"` @@ -83,7 +83,7 @@ type Album struct { } type Artist struct { - Id int `json:"id"` + ID int `json:"id"` Type string `json:"type"` Link string `json:"link"` Name string `json:"name"` diff --git a/internal/backends/funkwhale/client.go b/internal/backends/funkwhale/client.go index 8f2848b..c231c94 100644 --- a/internal/backends/funkwhale/client.go +++ b/internal/backends/funkwhale/client.go @@ -33,13 +33,13 @@ import ( const MaxItemsPerGet = 50 type Client struct { - HttpClient *resty.Client + HTTPClient *resty.Client token string } -func NewClient(serverUrl string, token string) Client { +func NewClient(serverURL string, token string) Client { client := resty.New() - client.SetBaseURL(serverUrl) + client.SetBaseURL(serverURL) client.SetAuthScheme("Bearer") client.SetAuthToken(token) client.SetHeader("Accept", "application/json") @@ -49,14 +49,14 @@ func NewClient(serverUrl string, token string) Client { ratelimit.EnableHTTPHeaderRateLimit(client, "Retry-After") return Client{ - HttpClient: client, + HTTPClient: client, token: token, } } func (c Client) GetHistoryListenings(user string, page int, perPage int) (result ListeningsResult, err error) { const path = "/api/v1/history/listenings" - response, err := c.HttpClient.R(). + response, err := c.HTTPClient.R(). SetQueryParams(map[string]string{ "username": user, "page": strconv.Itoa(page), @@ -75,7 +75,7 @@ func (c Client) GetHistoryListenings(user string, page int, perPage int) (result func (c Client) GetFavoriteTracks(page int, perPage int) (result FavoriteTracksResult, err error) { const path = "/api/v1/favorites/tracks" - response, err := c.HttpClient.R(). + response, err := c.HTTPClient.R(). SetQueryParams(map[string]string{ "page": strconv.Itoa(page), "page_size": strconv.Itoa(perPage), diff --git a/internal/backends/funkwhale/client_test.go b/internal/backends/funkwhale/client_test.go index 89325cd..e850a4d 100644 --- a/internal/backends/funkwhale/client_test.go +++ b/internal/backends/funkwhale/client_test.go @@ -32,20 +32,20 @@ import ( ) func TestNewClient(t *testing.T) { - serverUrl := "https://funkwhale.example.com" + serverURL := "https://funkwhale.example.com" token := "foobar123" - client := funkwhale.NewClient(serverUrl, token) - assert.Equal(t, serverUrl, client.HttpClient.BaseURL) - assert.Equal(t, token, client.HttpClient.Token) + client := funkwhale.NewClient(serverURL, token) + assert.Equal(t, serverURL, client.HTTPClient.BaseURL) + assert.Equal(t, token, client.HTTPClient.Token) } func TestGetHistoryListenings(t *testing.T) { defer httpmock.DeactivateAndReset() - serverUrl := "https://funkwhale.example.com" + serverURL := "https://funkwhale.example.com" token := "thetoken" - client := funkwhale.NewClient(serverUrl, token) - setupHttpMock(t, client.HttpClient.GetClient(), + client := funkwhale.NewClient(serverURL, token) + setupHTTPMock(t, client.HTTPClient.GetClient(), "https://funkwhale.example.com/api/v1/history/listenings", "testdata/listenings.json") @@ -67,9 +67,9 @@ func TestGetFavoriteTracks(t *testing.T) { defer httpmock.DeactivateAndReset() token := "thetoken" - serverUrl := "https://funkwhale.example.com" - client := funkwhale.NewClient(serverUrl, token) - setupHttpMock(t, client.HttpClient.GetClient(), + serverURL := "https://funkwhale.example.com" + client := funkwhale.NewClient(serverURL, token) + setupHTTPMock(t, client.HTTPClient.GetClient(), "https://funkwhale.example.com/api/v1/favorites/tracks", "testdata/favorite-tracks.json") @@ -87,7 +87,7 @@ func TestGetFavoriteTracks(t *testing.T) { assert.Equal("phw", fav1.User.UserName) } -func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) { +func setupHTTPMock(t *testing.T, client *http.Client, url string, testDataPath string) { httpmock.ActivateNonDefault(client) responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath)) diff --git a/internal/backends/funkwhale/models.go b/internal/backends/funkwhale/models.go index 10d57d0..faaae12 100644 --- a/internal/backends/funkwhale/models.go +++ b/internal/backends/funkwhale/models.go @@ -31,7 +31,7 @@ type ListeningsResult struct { } type Listening struct { - Id int `json:"int"` + ID int `json:"int"` User User `json:"user"` Track Track `json:"track"` CreationDate string `json:"creation_date"` @@ -45,14 +45,14 @@ type FavoriteTracksResult struct { } type FavoriteTrack struct { - Id int `json:"int"` + ID int `json:"int"` User User `json:"user"` Track Track `json:"track"` CreationDate string `json:"creation_date"` } type Track struct { - Id int `json:"int"` + ID int `json:"int"` Artist Artist `json:"artist"` Album Album `json:"album"` Title string `json:"title"` @@ -64,13 +64,13 @@ type Track struct { } type Artist struct { - Id int `json:"int"` + ID int `json:"int"` Name string `json:"name"` ArtistMBID mbtypes.MBID `json:"mbid"` } type Album struct { - Id int `json:"int"` + ID int `json:"int"` Title string `json:"title"` AlbumArtist Artist `json:"artist"` ReleaseDate string `json:"release_date"` @@ -79,7 +79,7 @@ type Album struct { } type User struct { - Id int `json:"int"` + ID int `json:"int"` UserName string `json:"username"` } diff --git a/internal/backends/jspf/jspf.go b/internal/backends/jspf/jspf.go index 152c810..3e6866d 100644 --- a/internal/backends/jspf/jspf.go +++ b/internal/backends/jspf/jspf.go @@ -69,7 +69,7 @@ func (b *JSPFBackend) InitConfig(config *config.ServiceConfig) error { Identifier: config.GetString("identifier"), Tracks: make([]jspf.Track, 0), Extension: map[string]any{ - jspf.MusicBrainzPlaylistExtensionId: jspf.MusicBrainzPlaylistExtension{ + jspf.MusicBrainzPlaylistExtensionID: jspf.MusicBrainzPlaylistExtension{ LastModifiedAt: time.Now(), Public: true, }, @@ -116,7 +116,7 @@ func listenAsTrack(l models.Listen) jspf.Track { extension := makeMusicBrainzExtension(l.Track) extension.AddedAt = l.ListenedAt extension.AddedBy = l.UserName - track.Extension[jspf.MusicBrainzTrackExtensionId] = extension + track.Extension[jspf.MusicBrainzTrackExtensionID] = extension if l.RecordingMBID != "" { track.Identifier = append(track.Identifier, "https://musicbrainz.org/recording/"+string(l.RecordingMBID)) @@ -131,7 +131,7 @@ func loveAsTrack(l models.Love) jspf.Track { extension := makeMusicBrainzExtension(l.Track) extension.AddedAt = l.Created extension.AddedBy = l.UserName - track.Extension[jspf.MusicBrainzTrackExtensionId] = extension + track.Extension[jspf.MusicBrainzTrackExtensionID] = extension recordingMBID := l.Track.RecordingMBID if l.RecordingMBID != "" { diff --git a/internal/backends/lastfm/auth.go b/internal/backends/lastfm/auth.go index bbc65bc..9d43e0c 100644 --- a/internal/backends/lastfm/auth.go +++ b/internal/backends/lastfm/auth.go @@ -25,21 +25,21 @@ import ( type lastfmStrategy struct { client *lastfm.Api - redirectUrl *url.URL + redirectURL *url.URL } func (s lastfmStrategy) Config() oauth2.Config { return oauth2.Config{} } -func (s lastfmStrategy) AuthCodeURL(verifier string, state string) auth.AuthUrl { +func (s lastfmStrategy) AuthCodeURL(verifier string, state string) auth.AuthURL { // Last.fm does not use OAuth2, but the provided authorization flow with // callback URL is close enough we can shoehorn it into the existing // authentication strategy. // TODO: Investigate and use callback-less flow with api.GetAuthTokenUrl(token) - url := s.client.GetAuthRequestUrl(s.redirectUrl.String()) - return auth.AuthUrl{ - Url: url, + url := s.client.GetAuthRequestUrl(s.redirectURL.String()) + return auth.AuthURL{ + URL: url, State: "", // last.fm does not use state Param: "token", } diff --git a/internal/backends/lastfm/lastfm.go b/internal/backends/lastfm/lastfm.go index 2d4a9d5..76fe9c7 100644 --- a/internal/backends/lastfm/lastfm.go +++ b/internal/backends/lastfm/lastfm.go @@ -62,9 +62,9 @@ func (b *LastfmApiBackend) Options() []models.BackendOption { } func (b *LastfmApiBackend) InitConfig(config *config.ServiceConfig) error { - clientId := config.GetString("client-id") + clientID := config.GetString("client-id") clientSecret := config.GetString("client-secret") - b.client = lastfm.New(clientId, clientSecret) + b.client = lastfm.New(clientID, clientSecret) b.username = config.GetString("username") return nil } @@ -72,10 +72,10 @@ func (b *LastfmApiBackend) InitConfig(config *config.ServiceConfig) error { func (b *LastfmApiBackend) StartImport() error { return nil } func (b *LastfmApiBackend) FinishImport() error { return nil } -func (b *LastfmApiBackend) OAuth2Strategy(redirectUrl *url.URL) auth.OAuth2Strategy { +func (b *LastfmApiBackend) OAuth2Strategy(redirectURL *url.URL) auth.OAuth2Strategy { return lastfmStrategy{ client: b.client, - redirectUrl: redirectUrl, + redirectURL: redirectURL, } } diff --git a/internal/backends/listenbrainz/client.go b/internal/backends/listenbrainz/client.go index 1917bd4..fff476c 100644 --- a/internal/backends/listenbrainz/client.go +++ b/internal/backends/listenbrainz/client.go @@ -39,7 +39,7 @@ const ( ) type Client struct { - HttpClient *resty.Client + HTTPClient *resty.Client MaxResults int } @@ -55,7 +55,7 @@ func NewClient(token string) Client { ratelimit.EnableHTTPHeaderRateLimit(client, "X-RateLimit-Reset-In") return Client{ - HttpClient: client, + HTTPClient: client, MaxResults: DefaultItemsPerGet, } } @@ -63,7 +63,7 @@ func NewClient(token string) Client { func (c Client) GetListens(user string, maxTime time.Time, minTime time.Time) (result GetListensResult, err error) { const path = "/user/{username}/listens" errorResult := ErrorResult{} - response, err := c.HttpClient.R(). + response, err := c.HTTPClient.R(). SetPathParam("username", user). SetQueryParams(map[string]string{ "max_ts": strconv.FormatInt(maxTime.Unix(), 10), @@ -84,7 +84,7 @@ func (c Client) GetListens(user string, maxTime time.Time, minTime time.Time) (r func (c Client) SubmitListens(listens ListenSubmission) (result StatusResult, err error) { const path = "/submit-listens" errorResult := ErrorResult{} - response, err := c.HttpClient.R(). + response, err := c.HTTPClient.R(). SetBody(listens). SetResult(&result). SetError(&errorResult). @@ -100,7 +100,7 @@ func (c Client) SubmitListens(listens ListenSubmission) (result StatusResult, er func (c Client) GetFeedback(user string, status int, offset int) (result GetFeedbackResult, err error) { const path = "/feedback/user/{username}/get-feedback" errorResult := ErrorResult{} - response, err := c.HttpClient.R(). + response, err := c.HTTPClient.R(). SetPathParam("username", user). SetQueryParams(map[string]string{ "status": strconv.Itoa(status), @@ -122,7 +122,7 @@ func (c Client) GetFeedback(user string, status int, offset int) (result GetFeed func (c Client) SendFeedback(feedback Feedback) (result StatusResult, err error) { const path = "/feedback/recording-feedback" errorResult := ErrorResult{} - response, err := c.HttpClient.R(). + response, err := c.HTTPClient.R(). SetBody(feedback). SetResult(&result). SetError(&errorResult). @@ -138,7 +138,7 @@ func (c Client) SendFeedback(feedback Feedback) (result StatusResult, err error) func (c Client) Lookup(recordingName string, artistName string) (result LookupResult, err error) { const path = "/metadata/lookup" errorResult := ErrorResult{} - response, err := c.HttpClient.R(). + response, err := c.HTTPClient.R(). SetQueryParams(map[string]string{ "recording_name": recordingName, "artist_name": artistName, diff --git a/internal/backends/listenbrainz/client_test.go b/internal/backends/listenbrainz/client_test.go index 4e72756..2e841ae 100644 --- a/internal/backends/listenbrainz/client_test.go +++ b/internal/backends/listenbrainz/client_test.go @@ -36,7 +36,7 @@ import ( func TestNewClient(t *testing.T) { token := "foobar123" client := listenbrainz.NewClient(token) - assert.Equal(t, token, client.HttpClient.Token) + assert.Equal(t, token, client.HTTPClient.Token) assert.Equal(t, listenbrainz.DefaultItemsPerGet, client.MaxResults) } @@ -45,7 +45,7 @@ func TestGetListens(t *testing.T) { client := listenbrainz.NewClient("thetoken") client.MaxResults = 2 - setupHttpMock(t, client.HttpClient.GetClient(), + setupHTTPMock(t, client.HTTPClient.GetClient(), "https://api.listenbrainz.org/1/user/outsidecontext/listens", "testdata/listens.json") @@ -62,7 +62,7 @@ func TestGetListens(t *testing.T) { func TestSubmitListens(t *testing.T) { client := listenbrainz.NewClient("thetoken") - httpmock.ActivateNonDefault(client.HttpClient.GetClient()) + httpmock.ActivateNonDefault(client.HTTPClient.GetClient()) responder, err := httpmock.NewJsonResponder(200, listenbrainz.StatusResult{ Status: "ok", @@ -103,7 +103,7 @@ func TestGetFeedback(t *testing.T) { client := listenbrainz.NewClient("thetoken") client.MaxResults = 2 - setupHttpMock(t, client.HttpClient.GetClient(), + setupHTTPMock(t, client.HTTPClient.GetClient(), "https://api.listenbrainz.org/1/feedback/user/outsidecontext/get-feedback", "testdata/feedback.json") @@ -120,7 +120,7 @@ func TestGetFeedback(t *testing.T) { func TestSendFeedback(t *testing.T) { client := listenbrainz.NewClient("thetoken") - httpmock.ActivateNonDefault(client.HttpClient.GetClient()) + httpmock.ActivateNonDefault(client.HTTPClient.GetClient()) responder, err := httpmock.NewJsonResponder(200, listenbrainz.StatusResult{ Status: "ok", @@ -145,7 +145,7 @@ func TestLookup(t *testing.T) { defer httpmock.DeactivateAndReset() client := listenbrainz.NewClient("thetoken") - setupHttpMock(t, client.HttpClient.GetClient(), + setupHTTPMock(t, client.HTTPClient.GetClient(), "https://api.listenbrainz.org/1/metadata/lookup", "testdata/lookup.json") @@ -158,7 +158,7 @@ func TestLookup(t *testing.T) { assert.Equal(mbtypes.MBID("569436a1-234a-44bc-a370-8f4d252bef21"), result.RecordingMBID) } -func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) { +func setupHTTPMock(t *testing.T, client *http.Client, url string, testDataPath string) { httpmock.ActivateNonDefault(client) responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath)) diff --git a/internal/backends/listenbrainz/models_test.go b/internal/backends/listenbrainz/models_test.go index 9f5b14a..02cbe98 100644 --- a/internal/backends/listenbrainz/models_test.go +++ b/internal/backends/listenbrainz/models_test.go @@ -131,7 +131,7 @@ func TestTrackTrackNumberString(t *testing.T) { assert.Equal(t, 12, track.TrackNumber()) } -func TestTrackIsrc(t *testing.T) { +func TestTrackISRC(t *testing.T) { expected := mbtypes.ISRC("TCAEJ1934417") track := listenbrainz.Track{ AdditionalInfo: map[string]any{ diff --git a/internal/backends/maloja/client.go b/internal/backends/maloja/client.go index f373f93..249819a 100644 --- a/internal/backends/maloja/client.go +++ b/internal/backends/maloja/client.go @@ -32,25 +32,25 @@ import ( const MaxItemsPerGet = 1000 type Client struct { - HttpClient *resty.Client + HTTPClient *resty.Client token string } -func NewClient(serverUrl string, token string) Client { +func NewClient(serverURL string, token string) Client { client := resty.New() - client.SetBaseURL(serverUrl) + client.SetBaseURL(serverURL) client.SetHeader("Accept", "application/json") client.SetHeader("User-Agent", version.UserAgent()) client.SetRetryCount(5) return Client{ - HttpClient: client, + HTTPClient: client, token: token, } } func (c Client) GetScrobbles(page int, perPage int) (result GetScrobblesResult, err error) { const path = "/apis/mlj_1/scrobbles" - response, err := c.HttpClient.R(). + response, err := c.HTTPClient.R(). SetQueryParams(map[string]string{ "page": strconv.Itoa(page), "perpage": strconv.Itoa(perPage), @@ -68,7 +68,7 @@ func (c Client) GetScrobbles(page int, perPage int) (result GetScrobblesResult, func (c Client) NewScrobble(scrobble NewScrobble) (result NewScrobbleResult, err error) { const path = "/apis/mlj_1/newscrobble" scrobble.Key = c.token - response, err := c.HttpClient.R(). + response, err := c.HTTPClient.R(). SetBody(scrobble). SetResult(&result). Post(path) diff --git a/internal/backends/maloja/client_test.go b/internal/backends/maloja/client_test.go index 6a07adb..54316a8 100644 --- a/internal/backends/maloja/client_test.go +++ b/internal/backends/maloja/client_test.go @@ -32,19 +32,19 @@ import ( ) func TestNewClient(t *testing.T) { - serverUrl := "https://maloja.example.com" + serverURL := "https://maloja.example.com" token := "foobar123" - client := maloja.NewClient(serverUrl, token) - assert.Equal(t, serverUrl, client.HttpClient.BaseURL) + client := maloja.NewClient(serverURL, token) + assert.Equal(t, serverURL, client.HTTPClient.BaseURL) } func TestGetScrobbles(t *testing.T) { defer httpmock.DeactivateAndReset() - serverUrl := "https://maloja.example.com" + serverURL := "https://maloja.example.com" token := "thetoken" - client := maloja.NewClient(serverUrl, token) - setupHttpMock(t, client.HttpClient.GetClient(), + client := maloja.NewClient(serverURL, token) + setupHTTPMock(t, client.HTTPClient.GetClient(), "https://maloja.example.com/apis/mlj_1/scrobbles", "testdata/scrobbles.json") @@ -60,7 +60,7 @@ func TestGetScrobbles(t *testing.T) { func TestNewScrobble(t *testing.T) { server := "https://maloja.example.com" client := maloja.NewClient(server, "thetoken") - httpmock.ActivateNonDefault(client.HttpClient.GetClient()) + httpmock.ActivateNonDefault(client.HTTPClient.GetClient()) responder, err := httpmock.NewJsonResponder(200, httpmock.File("testdata/newscrobble-result.json")) if err != nil { @@ -80,7 +80,7 @@ func TestNewScrobble(t *testing.T) { assert.Equal(t, "success", result.Status) } -func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) { +func setupHTTPMock(t *testing.T, client *http.Client, url string, testDataPath string) { httpmock.ActivateNonDefault(client) responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath)) diff --git a/internal/backends/spotify/client.go b/internal/backends/spotify/client.go index 1c002c0..ff2b0a3 100644 --- a/internal/backends/spotify/client.go +++ b/internal/backends/spotify/client.go @@ -40,7 +40,7 @@ const ( ) type Client struct { - HttpClient *resty.Client + HTTPClient *resty.Client } func NewClient(token oauth2.TokenSource) Client { @@ -55,7 +55,7 @@ func NewClient(token oauth2.TokenSource) Client { ratelimit.EnableHTTPHeaderRateLimit(client, "Retry-After") return Client{ - HttpClient: client, + HTTPClient: client, } } @@ -69,7 +69,7 @@ func (c Client) RecentlyPlayedBefore(before time.Time, limit int) (RecentlyPlaye func (c Client) recentlyPlayed(after *time.Time, before *time.Time, limit int) (result RecentlyPlayedResult, err error) { const path = "/me/player/recently-played" - request := c.HttpClient.R(). + request := c.HTTPClient.R(). SetQueryParam("limit", strconv.Itoa(limit)). SetResult(&result) if after != nil { @@ -87,7 +87,7 @@ func (c Client) recentlyPlayed(after *time.Time, before *time.Time, limit int) ( func (c Client) UserTracks(offset int, limit int) (result TracksResult, err error) { const path = "/me/tracks" - response, err := c.HttpClient.R(). + response, err := c.HTTPClient.R(). SetQueryParams(map[string]string{ "offset": strconv.Itoa(offset), "limit": strconv.Itoa(limit), diff --git a/internal/backends/spotify/client_test.go b/internal/backends/spotify/client_test.go index 7d738bf..78ff063 100644 --- a/internal/backends/spotify/client_test.go +++ b/internal/backends/spotify/client_test.go @@ -43,7 +43,7 @@ func TestRecentlyPlayedAfter(t *testing.T) { defer httpmock.DeactivateAndReset() client := spotify.NewClient(nil) - setupHttpMock(t, client.HttpClient.GetClient(), + setupHTTPMock(t, client.HTTPClient.GetClient(), "https://api.spotify.com/v1/me/player/recently-played", "testdata/recently-played.json") @@ -63,7 +63,7 @@ func TestGetUserTracks(t *testing.T) { defer httpmock.DeactivateAndReset() client := spotify.NewClient(nil) - setupHttpMock(t, client.HttpClient.GetClient(), + setupHTTPMock(t, client.HTTPClient.GetClient(), "https://api.spotify.com/v1/me/tracks", "testdata/user-tracks.json") @@ -79,7 +79,7 @@ func TestGetUserTracks(t *testing.T) { assert.Equal("Zeal & Ardor", track1.Track.Album.Name) } -func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) { +func setupHTTPMock(t *testing.T, client *http.Client, url string, testDataPath string) { httpmock.ActivateNonDefault(client) responder, err := httpmock.NewJsonResponder(200, httpmock.File(testDataPath)) diff --git a/internal/backends/spotify/models.go b/internal/backends/spotify/models.go index a22de21..e279e15 100644 --- a/internal/backends/spotify/models.go +++ b/internal/backends/spotify/models.go @@ -58,7 +58,7 @@ type Listen struct { } type Track struct { - Id string `json:"id"` + ID string `json:"id"` Name string `json:"name"` Href string `json:"href"` Uri string `json:"uri"` @@ -69,14 +69,14 @@ type Track struct { Explicit bool `json:"explicit"` IsLocal bool `json:"is_local"` Popularity int `json:"popularity"` - ExternalIds ExternalIds `json:"external_ids"` - ExternalUrls ExternalUrls `json:"external_urls"` + ExternalIDs ExternalIDs `json:"external_ids"` + ExternalURLs ExternalURLs `json:"external_urls"` Album Album `json:"album"` Artists []Artist `json:"artists"` } type Album struct { - Id string `json:"id"` + ID string `json:"id"` Name string `json:"name"` Href string `json:"href"` Uri string `json:"uri"` @@ -85,32 +85,32 @@ type Album struct { ReleaseDate string `json:"release_date"` ReleaseDatePrecision string `json:"release_date_precision"` AlbumType string `json:"album_type"` - ExternalUrls ExternalUrls `json:"external_urls"` + ExternalURLs ExternalURLs `json:"external_urls"` Artists []Artist `json:"artists"` Images []Image `json:"images"` } type Artist struct { - Id string `json:"id"` + ID string `json:"id"` Name string `json:"name"` Href string `json:"href"` Uri string `json:"uri"` Type string `json:"type"` - ExternalUrls ExternalUrls `json:"external_urls"` + ExternalURLs ExternalURLs `json:"external_urls"` } -type ExternalIds struct { +type ExternalIDs struct { ISRC mbtypes.ISRC `json:"isrc"` EAN string `json:"ean"` UPC string `json:"upc"` } -type ExternalUrls struct { +type ExternalURLs struct { Spotify string `json:"spotify"` } type Image struct { - Url string `json:"url"` + URL string `json:"url"` Height int `json:"height"` Width int `json:"width"` } diff --git a/internal/backends/spotify/spotify.go b/internal/backends/spotify/spotify.go index ae2fc25..1827769 100644 --- a/internal/backends/spotify/spotify.go +++ b/internal/backends/spotify/spotify.go @@ -34,7 +34,7 @@ import ( type SpotifyApiBackend struct { client Client - clientId string + clientID string clientSecret string } @@ -53,14 +53,14 @@ func (b *SpotifyApiBackend) Options() []models.BackendOption { } func (b *SpotifyApiBackend) InitConfig(config *config.ServiceConfig) error { - b.clientId = config.GetString("client-id") + b.clientID = config.GetString("client-id") b.clientSecret = config.GetString("client-secret") return nil } -func (b *SpotifyApiBackend) OAuth2Strategy(redirectUrl *url.URL) auth.OAuth2Strategy { +func (b *SpotifyApiBackend) OAuth2Strategy(redirectURL *url.URL) auth.OAuth2Strategy { conf := oauth2.Config{ - ClientID: b.clientId, + ClientID: b.clientID, ClientSecret: b.clientSecret, Scopes: []string{ "user-read-currently-playing", @@ -68,16 +68,16 @@ func (b *SpotifyApiBackend) OAuth2Strategy(redirectUrl *url.URL) auth.OAuth2Stra "user-library-read", "user-library-modify", }, - RedirectURL: redirectUrl.String(), + RedirectURL: redirectURL.String(), Endpoint: spotify.Endpoint, } return auth.NewStandardStrategy(conf) } -func (b *SpotifyApiBackend) OAuth2Config(redirectUrl *url.URL) oauth2.Config { +func (b *SpotifyApiBackend) OAuth2Config(redirectURL *url.URL) oauth2.Config { return oauth2.Config{ - ClientID: b.clientId, + ClientID: b.clientID, ClientSecret: b.clientSecret, Scopes: []string{ "user-read-currently-playing", @@ -85,7 +85,7 @@ func (b *SpotifyApiBackend) OAuth2Config(redirectUrl *url.URL) oauth2.Config { "user-library-read", "user-library-modify", }, - RedirectURL: redirectUrl.String(), + RedirectURL: redirectURL.String(), Endpoint: spotify.Endpoint, } } @@ -251,7 +251,7 @@ func (t Track) AsTrack() models.Track { Duration: time.Duration(t.DurationMs * int(time.Millisecond)), TrackNumber: t.TrackNumber, DiscNumber: t.DiscNumber, - ISRC: t.ExternalIds.ISRC, + ISRC: t.ExternalIDs.ISRC, AdditionalInfo: map[string]any{}, } @@ -264,30 +264,30 @@ func (t Track) AsTrack() models.Track { info["music_service"] = "spotify.com" } - if t.ExternalUrls.Spotify != "" { - info["origin_url"] = t.ExternalUrls.Spotify - info["spotify_id"] = t.ExternalUrls.Spotify + if t.ExternalURLs.Spotify != "" { + info["origin_url"] = t.ExternalURLs.Spotify + info["spotify_id"] = t.ExternalURLs.Spotify } - if t.Album.ExternalUrls.Spotify != "" { - info["spotify_album_id"] = t.Album.ExternalUrls.Spotify + if t.Album.ExternalURLs.Spotify != "" { + info["spotify_album_id"] = t.Album.ExternalURLs.Spotify } if len(t.Artists) > 0 { - info["spotify_artist_ids"] = extractArtistIds(t.Artists) + info["spotify_artist_ids"] = extractArtistIDs(t.Artists) } if len(t.Album.Artists) > 0 { - info["spotify_album_artist_ids"] = extractArtistIds(t.Album.Artists) + info["spotify_album_artist_ids"] = extractArtistIDs(t.Album.Artists) } return track } -func extractArtistIds(artists []Artist) []string { - artistIds := make([]string, len(artists)) +func extractArtistIDs(artists []Artist) []string { + artistIDs := make([]string, len(artists)) for i, artist := range artists { - artistIds[i] = artist.ExternalUrls.Spotify + artistIDs[i] = artist.ExternalURLs.Spotify } - return artistIds + return artistIDs } diff --git a/internal/backends/spotifyhistory/models.go b/internal/backends/spotifyhistory/models.go index fad4fb1..a2eba23 100644 --- a/internal/backends/spotifyhistory/models.go +++ b/internal/backends/spotifyhistory/models.go @@ -92,8 +92,8 @@ func (i HistoryItem) AsListen() models.Listen { PlaybackDuration: time.Duration(i.MillisecondsPlayed * int(time.Millisecond)), UserName: i.UserName, } - if trackUrl, err := formatSpotifyUri(i.SpotifyTrackUri); err != nil { - listen.AdditionalInfo["spotify_id"] = trackUrl + if trackURL, err := formatSpotifyUri(i.SpotifyTrackUri); err != nil { + listen.AdditionalInfo["spotify_id"] = trackURL } return listen } diff --git a/internal/cli/auth.go b/internal/cli/auth.go index 828651a..ff14573 100644 --- a/internal/cli/auth.go +++ b/internal/cli/auth.go @@ -43,20 +43,20 @@ func AuthenticationFlow(service config.ServiceConfig, backend auth.OAuth2Authent state := auth.RandomState() // Redirect user to consent page to ask for permission specified scopes. - authUrl := strategy.AuthCodeURL(verifier, state) + authURL := strategy.AuthCodeURL(verifier, state) // Start an HTTP server to listen for the response responseChan := make(chan auth.CodeResponse) - auth.RunOauth2CallbackServer(*redirectURL, authUrl.Param, responseChan) + auth.RunOauth2CallbackServer(*redirectURL, authURL.Param, responseChan) // Open the URL - fmt.Println(i18n.Tr("Visit the URL for authorization: %v", authUrl.Url)) - err = browser.OpenURL(authUrl.Url) + fmt.Println(i18n.Tr("Visit the URL for authorization: %v", authURL.URL)) + err = browser.OpenURL(authURL.URL) cobra.CheckErr(err) // Retrieve the code from the authentication callback code := <-responseChan - if code.State != authUrl.State { + if code.State != authURL.State { cobra.CompErrorln(i18n.Tr("Error: OAuth state mismatch")) os.Exit(1) } diff --git a/pkg/jspf/extensions.go b/pkg/jspf/extensions.go index 07cd3c1..0f521c4 100644 --- a/pkg/jspf/extensions.go +++ b/pkg/jspf/extensions.go @@ -26,9 +26,9 @@ import "time" const ( // The identifier for the MusicBrainz / ListenBrainz JSPF playlist extension - MusicBrainzPlaylistExtensionId = "https://musicbrainz.org/doc/jspf#playlist" + MusicBrainzPlaylistExtensionID = "https://musicbrainz.org/doc/jspf#playlist" // The identifier for the MusicBrainz / ListenBrainz JSPF track extension - MusicBrainzTrackExtensionId = "https://musicbrainz.org/doc/jspf#track" + MusicBrainzTrackExtensionID = "https://musicbrainz.org/doc/jspf#track" ) // MusicBrainz / ListenBrainz JSPF track extension diff --git a/pkg/jspf/extensions_test.go b/pkg/jspf/extensions_test.go index 8d8653d..883301d 100644 --- a/pkg/jspf/extensions_test.go +++ b/pkg/jspf/extensions_test.go @@ -39,7 +39,7 @@ func ExampleMusicBrainzTrackExtension() { { Title: "Oweynagat", Extension: map[string]any{ - jspf.MusicBrainzTrackExtensionId: jspf.MusicBrainzTrackExtension{ + jspf.MusicBrainzTrackExtensionID: jspf.MusicBrainzTrackExtension{ AddedAt: time.Date(2023, 11, 24, 07, 47, 50, 0, time.UTC), AddedBy: "scotty", }, From bcb183499449e3fe9572895c8b8a1734b346c7d2 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 29 Apr 2025 13:29:00 +0200 Subject: [PATCH 2/9] scrobblerlog: use camelcase for constants --- internal/backends/scrobblerlog/scrobblerlog.go | 4 ++-- pkg/scrobblerlog/parser.go | 14 +++++++------- pkg/scrobblerlog/parser_test.go | 14 +++++++------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/internal/backends/scrobblerlog/scrobblerlog.go b/internal/backends/scrobblerlog/scrobblerlog.go index 26d417a..19ed30b 100644 --- a/internal/backends/scrobblerlog/scrobblerlog.go +++ b/internal/backends/scrobblerlog/scrobblerlog.go @@ -76,7 +76,7 @@ func (b *ScrobblerLogBackend) InitConfig(config *config.ServiceConfig) error { b.log.FallbackTimezone = location } b.log = scrobblerlog.ScrobblerLog{ - TZ: scrobblerlog.TZ_UTC, + TZ: scrobblerlog.TimezoneUTC, Client: "Rockbox unknown $Revision$", } return nil @@ -197,7 +197,7 @@ func listenToRecord(listen models.Listen) scrobblerlog.Record { var rating scrobblerlog.Rating rockboxRating, ok := listen.AdditionalInfo["rockbox_rating"].(string) if !ok || rockboxRating == "" { - rating = scrobblerlog.RATING_LISTENED + rating = scrobblerlog.RatingListened } else { rating = scrobblerlog.Rating(rating) } diff --git a/pkg/scrobblerlog/parser.go b/pkg/scrobblerlog/parser.go index 892f6e8..9c6471c 100644 --- a/pkg/scrobblerlog/parser.go +++ b/pkg/scrobblerlog/parser.go @@ -45,16 +45,16 @@ import ( type TZInfo string const ( - TZ_UNKNOWN TZInfo = "UNKNOWN" - TZ_UTC TZInfo = "UTC" + TimezoneUnknown TZInfo = "UNKNOWN" + TimezoneUTC TZInfo = "UTC" ) // L if listened at least 50% or S if skipped type Rating string const ( - RATING_LISTENED Rating = "L" - RATING_SKIPPED Rating = "S" + RatingListened Rating = "L" + RatingSkipped Rating = "S" ) // A single entry of a track in the scrobbler log file. @@ -75,7 +75,7 @@ type ScrobblerLog struct { Client string Records []Record // Timezone to be used for timestamps in the log file, - // if TZ is set to [TZ_UNKNOWN]. + // if TZ is set to [TimezoneUnknown]. FallbackTimezone *time.Location } @@ -116,7 +116,7 @@ func (l *ScrobblerLog) Parse(data io.Reader, ignoreSkipped bool) error { return err } - if ignoreSkipped && record.Rating == RATING_SKIPPED { + if ignoreSkipped && record.Rating == RatingSkipped { continue } @@ -224,7 +224,7 @@ func (l ScrobblerLog) rowToRecord(row []string) (Record, error) { } var timezone *time.Location = nil - if l.TZ == TZ_UNKNOWN { + if l.TZ == TimezoneUnknown { timezone = l.FallbackTimezone } diff --git a/pkg/scrobblerlog/parser_test.go b/pkg/scrobblerlog/parser_test.go index 7fd57c3..f4527cc 100644 --- a/pkg/scrobblerlog/parser_test.go +++ b/pkg/scrobblerlog/parser_test.go @@ -50,7 +50,7 @@ func TestParser(t *testing.T) { result := scrobblerlog.ScrobblerLog{} err := result.Parse(data, false) require.NoError(t, err) - assert.Equal(scrobblerlog.TZ_UNKNOWN, result.TZ) + assert.Equal(scrobblerlog.TimezoneUnknown, result.TZ) assert.Equal("Rockbox sansaclipplus $Revision$", result.Client) assert.Len(result.Records, 5) record1 := result.Records[0] @@ -59,11 +59,11 @@ func TestParser(t *testing.T) { assert.Equal("Sevdanin rengi (sipacik) byMrTurkey", record1.TrackName) assert.Equal(5, record1.TrackNumber) assert.Equal(time.Duration(306*time.Second), record1.Duration) - assert.Equal(scrobblerlog.RATING_LISTENED, record1.Rating) + assert.Equal(scrobblerlog.RatingListened, record1.Rating) assert.Equal(time.Unix(1260342084, 0), record1.Timestamp) assert.Equal(mbtypes.MBID(""), record1.MusicBrainzRecordingID) record4 := result.Records[3] - assert.Equal(scrobblerlog.RATING_SKIPPED, record4.Rating) + assert.Equal(scrobblerlog.RatingSkipped, record4.Rating) assert.Equal(mbtypes.MBID("385ba9e9-626d-4750-a607-58e541dca78e"), record4.MusicBrainzRecordingID) } @@ -76,7 +76,7 @@ func TestParserIgnoreSkipped(t *testing.T) { require.NoError(t, err) assert.Len(result.Records, 4) record4 := result.Records[3] - assert.Equal(scrobblerlog.RATING_LISTENED, record4.Rating) + assert.Equal(scrobblerlog.RatingListened, record4.Rating) assert.Equal(mbtypes.MBID("1262beaf-19f8-4534-b9ed-7eef9ca8e83f"), record4.MusicBrainzRecordingID) } @@ -101,7 +101,7 @@ func TestAppend(t *testing.T) { data := make([]byte, 0, 10) buffer := bytes.NewBuffer(data) log := scrobblerlog.ScrobblerLog{ - TZ: scrobblerlog.TZ_UNKNOWN, + TZ: scrobblerlog.TimezoneUnknown, Client: "Rockbox foo $Revision$", } records := []scrobblerlog.Record{ @@ -111,7 +111,7 @@ func TestAppend(t *testing.T) { TrackName: "Reign", TrackNumber: 1, Duration: 271 * time.Second, - Rating: scrobblerlog.RATING_LISTENED, + Rating: scrobblerlog.RatingListened, Timestamp: time.Unix(1699572072, 0), MusicBrainzRecordingID: mbtypes.MBID("b59cf4e7-caee-4019-a844-79d2c58d4dff"), }, @@ -139,7 +139,7 @@ func TestReadHeader(t *testing.T) { log := scrobblerlog.ScrobblerLog{} err := log.ReadHeader(reader) assert.NoError(t, err) - assert.Equal(t, log.TZ, scrobblerlog.TZ_UNKNOWN) + assert.Equal(t, log.TZ, scrobblerlog.TimezoneUnknown) assert.Equal(t, log.Client, "Rockbox sansaclipplus $Revision$") assert.Empty(t, log.Records) } From dff34b249c29916848ef5b700563126bd59a3eef Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 29 Apr 2025 15:46:14 +0200 Subject: [PATCH 3/9] Updated translation files --- internal/translations/catalog.go | 123 +++++++++--------- .../translations/locales/de/out.gotext.json | 26 ++-- .../translations/locales/en/out.gotext.json | 30 ++--- 3 files changed, 89 insertions(+), 90 deletions(-) diff --git a/internal/translations/catalog.go b/internal/translations/catalog.go index 987612a..c4a7937 100644 --- a/internal/translations/catalog.go +++ b/internal/translations/catalog.go @@ -42,56 +42,56 @@ var messageKeyToIndex = map[string]int{ "\tbackend: %v": 11, "\texport: %s": 0, "\timport: %s\n": 1, - "%v: %v": 47, + "%v: %v": 45, "Aborted": 8, "Access token": 19, - "Access token received, you can use %v now.\n": 33, + "Access token received, you can use %v now.\n": 31, "Append to file": 21, - "Backend": 41, + "Backend": 39, "Check for duplicate listens on import (slower)": 24, "Client ID": 15, "Client secret": 16, "Delete the service configuration \"%v\"?": 7, "Directory path": 27, "Disable auto correction of submitted listens": 25, - "Error: OAuth state mismatch": 32, + "Error: OAuth state mismatch": 30, "Failed reading config: %v": 2, "File path": 20, - "From timestamp: %v (%v)": 43, + "From timestamp: %v (%v)": 41, "Ignore listens in incognito mode": 28, - "Ignore skipped listens": 29, - "Ignored duplicate listen %v: \"%v\" by %v (%v)": 53, - "Import failed, last reported timestamp was %v (%s)": 44, - "Import log:": 46, - "Imported %v of %v %s into %v.": 45, - "Include skipped listens": 26, - "Latest timestamp: %v (%v)": 49, - "Minimum playback duration for skipped tracks (seconds)": 30, - "No": 38, + "Ignore skipped listens": 26, + "Ignored duplicate listen %v: \"%v\" by %v (%v)": 51, + "Import failed, last reported timestamp was %v (%s)": 42, + "Import log:": 44, + "Imported %v of %v %s into %v.": 43, + "Latest timestamp: %v (%v)": 47, + "Minimum playback duration for skipped tracks (seconds)": 29, + "No": 36, "Playlist title": 22, "Saved service %v using backend %v": 5, "Server URL": 17, - "Service": 40, + "Service": 38, "Service \"%v\" deleted\n": 9, "Service name": 3, + "Specify a time zone for the listen timestamps": 52, "The backend %v requires authentication. Authenticate now?": 6, "Token received, you can close this window now.": 12, - "Transferring %s from %s to %s...": 42, + "Transferring %s from %s to %s...": 40, "Unique playlist identifier": 23, "Updated service %v using backend %v\n": 10, "User name": 18, - "Visit the URL for authorization: %v": 31, - "Yes": 37, + "Visit the URL for authorization: %v": 53, + "Yes": 35, "a service with this name already exists": 4, "backend %s does not implement %s": 13, - "done": 36, - "exporting": 34, - "importing": 35, - "invalid timestamp string \"%v\"": 48, - "key must only consist of A-Za-z0-9_-": 51, - "no configuration file defined, cannot write config": 50, - "no existing service configurations": 39, - "no service configuration \"%v\"": 52, + "done": 34, + "exporting": 32, + "importing": 33, + "invalid timestamp string \"%v\"": 46, + "key must only consist of A-Za-z0-9_-": 49, + "no configuration file defined, cannot write config": 48, + "no existing service configurations": 37, + "no service configuration \"%v\"": 50, "unknown backend \"%s\"": 14, } @@ -103,18 +103,18 @@ var deIndex = []uint32{ // 55 elements 0x000001ac, 0x000001e7, 0x00000213, 0x00000233, 0x0000023d, 0x0000024b, 0x00000256, 0x00000263, 0x00000271, 0x0000027b, 0x0000028e, 0x000002a1, - 0x000002b8, 0x000002ed, 0x00000321, 0x00000342, - 0x00000352, 0x00000378, 0x0000039a, 0x000003d8, + 0x000002b8, 0x000002ed, 0x00000321, 0x00000343, + 0x00000353, 0x00000379, 0x000003b7, 0x000003e1, // Entry 20 - 3F - 0x000003fe, 0x00000428, 0x00000468, 0x00000473, - 0x0000047e, 0x00000485, 0x00000488, 0x0000048d, - 0x000004b6, 0x000004be, 0x000004c6, 0x000004ef, - 0x0000050d, 0x0000054a, 0x00000575, 0x00000580, - 0x0000058d, 0x000005b1, 0x000005d4, 0x00000625, - 0x0000065c, 0x00000683, 0x00000683, + 0x00000421, 0x0000042c, 0x00000437, 0x0000043e, + 0x00000441, 0x00000446, 0x0000046f, 0x00000477, + 0x0000047f, 0x000004a8, 0x000004c6, 0x00000503, + 0x0000052e, 0x00000539, 0x00000546, 0x0000056a, + 0x0000058d, 0x000005de, 0x00000615, 0x0000063c, + 0x0000063c, 0x0000063c, 0x0000063c, } // Size: 244 bytes -const deData string = "" + // Size: 1667 bytes +const deData string = "" + // Size: 1596 bytes "\x04\x01\x09\x00\x0e\x02Export: %[1]s\x04\x01\x09\x01\x0a\x0e\x02Import:" + " %[1]s\x02Fehler beim Lesen der Konfiguration: %[1]v\x02Servicename\x02e" + "in Service mit diesem Namen existiert bereits\x02Service %[1]v mit dem B" + @@ -128,10 +128,9 @@ const deData string = "" + // Size: 1667 bytes "\x02Benutzername\x02Zugriffstoken\x02Dateipfad\x02An Datei anhängen\x02T" + "itel der Playlist\x02Eindeutige Playlist-ID\x02Beim Import auf Listen-Du" + "plikate prüfen (langsamer)\x02Autokorrektur für übermittelte Titel deakt" + - "ivieren\x02Übersprungene Titel einbeziehen\x02Verzeichnispfad\x02Listens" + - " im Inkognito-Modus ignorieren\x02Übersprungene Listens ignorieren\x02Mi" + - "nimale Wiedergabedauer für übersprungene Titel (Sekunden)\x02URL für Aut" + - "orisierung öffnen: %[1]v\x02Fehler: OAuth-State stimmt nicht überein\x04" + + "ivieren\x02Übersprungene Listens ignorieren\x02Verzeichnispfad\x02Listen" + + "s im Inkognito-Modus ignorieren\x02Minimale Wiedergabedauer für überspru" + + "ngene Titel (Sekunden)\x02Fehler: OAuth-State stimmt nicht überein\x04" + "\x00\x01\x0a;\x02Zugriffstoken erhalten, %[1]v kann jetzt verwendet werd" + "en.\x02exportiere\x02importiere\x02fertig\x02Ja\x02Nein\x02keine bestehe" + "nden Servicekonfigurationen\x02Service\x02Backend\x02Übertrage %[1]s von" + @@ -151,18 +150,18 @@ var enIndex = []uint32{ // 55 elements 0x00000170, 0x0000019f, 0x000001c6, 0x000001de, 0x000001e8, 0x000001f6, 0x00000201, 0x0000020b, 0x00000218, 0x00000222, 0x00000231, 0x00000240, - 0x0000025b, 0x0000028a, 0x000002b7, 0x000002cf, - 0x000002de, 0x000002ff, 0x00000316, 0x0000034d, + 0x0000025b, 0x0000028a, 0x000002b7, 0x000002ce, + 0x000002dd, 0x000002fe, 0x00000335, 0x00000351, // Entry 20 - 3F - 0x00000374, 0x00000390, 0x000003c3, 0x000003cd, - 0x000003d7, 0x000003dc, 0x000003e0, 0x000003e3, - 0x00000406, 0x0000040e, 0x00000416, 0x00000440, - 0x0000045e, 0x00000497, 0x000004c1, 0x000004cd, - 0x000004da, 0x000004fb, 0x0000051b, 0x0000054e, - 0x00000573, 0x00000594, 0x000005cd, + 0x00000384, 0x0000038e, 0x00000398, 0x0000039d, + 0x000003a1, 0x000003a4, 0x000003c7, 0x000003cf, + 0x000003d7, 0x00000401, 0x0000041f, 0x00000458, + 0x00000482, 0x0000048e, 0x0000049b, 0x000004bc, + 0x000004dc, 0x0000050f, 0x00000534, 0x00000555, + 0x0000058e, 0x000005bc, 0x000005e3, } // Size: 244 bytes -const enData string = "" + // Size: 1485 bytes +const enData string = "" + // Size: 1507 bytes "\x04\x01\x09\x00\x0e\x02export: %[1]s\x04\x01\x09\x01\x0a\x0e\x02import:" + " %[1]s\x02Failed reading config: %[1]v\x02Service name\x02a service with" + " this name already exists\x02Saved service %[1]v using backend %[2]v\x02" + @@ -175,18 +174,18 @@ const enData string = "" + // Size: 1485 bytes "\x02Server URL\x02User name\x02Access token\x02File path\x02Append to fi" + "le\x02Playlist title\x02Unique playlist identifier\x02Check for duplicat" + "e listens on import (slower)\x02Disable auto correction of submitted lis" + - "tens\x02Include skipped listens\x02Directory path\x02Ignore listens in i" + - "ncognito mode\x02Ignore skipped listens\x02Minimum playback duration for" + - " skipped tracks (seconds)\x02Visit the URL for authorization: %[1]v\x02E" + - "rror: OAuth state mismatch\x04\x00\x01\x0a.\x02Access token received, yo" + - "u can use %[1]v now.\x02exporting\x02importing\x02done\x02Yes\x02No\x02n" + - "o existing service configurations\x02Service\x02Backend\x02Transferring " + - "%[1]s from %[2]s to %[3]s...\x02From timestamp: %[1]v (%[2]v)\x02Import " + - "failed, last reported timestamp was %[1]v (%[2]s)\x02Imported %[1]v of %" + - "[2]v %[3]s into %[4]v.\x02Import log:\x02%[1]v: %[2]v\x02invalid timesta" + - "mp string \x22%[1]v\x22\x02Latest timestamp: %[1]v (%[2]v)\x02no configu" + - "ration file defined, cannot write config\x02key must only consist of A-Z" + - "a-z0-9_-\x02no service configuration \x22%[1]v\x22\x02Ignored duplicate " + - "listen %[1]v: \x22%[2]v\x22 by %[3]v (%[4]v)" + "tens\x02Ignore skipped listens\x02Directory path\x02Ignore listens in in" + + "cognito mode\x02Minimum playback duration for skipped tracks (seconds)" + + "\x02Error: OAuth state mismatch\x04\x00\x01\x0a.\x02Access token receive" + + "d, you can use %[1]v now.\x02exporting\x02importing\x02done\x02Yes\x02No" + + "\x02no existing service configurations\x02Service\x02Backend\x02Transfer" + + "ring %[1]s from %[2]s to %[3]s...\x02From timestamp: %[1]v (%[2]v)\x02Im" + + "port failed, last reported timestamp was %[1]v (%[2]s)\x02Imported %[1]v" + + " of %[2]v %[3]s into %[4]v.\x02Import log:\x02%[1]v: %[2]v\x02invalid ti" + + "mestamp string \x22%[1]v\x22\x02Latest timestamp: %[1]v (%[2]v)\x02no co" + + "nfiguration file defined, cannot write config\x02key must only consist o" + + "f A-Za-z0-9_-\x02no service configuration \x22%[1]v\x22\x02Ignored dupli" + + "cate listen %[1]v: \x22%[2]v\x22 by %[3]v (%[4]v)\x02Specify a time zone" + + " for the listen timestamps\x02Visit the URL for authorization: %[1]v" - // Total table size 3640 bytes (3KiB); checksum: 719A868A + // Total table size 3591 bytes (3KiB); checksum: 6C862242 diff --git a/internal/translations/locales/de/out.gotext.json b/internal/translations/locales/de/out.gotext.json index 18333c6..65abfdd 100644 --- a/internal/translations/locales/de/out.gotext.json +++ b/internal/translations/locales/de/out.gotext.json @@ -305,9 +305,14 @@ "translation": "Autokorrektur für übermittelte Titel deaktivieren" }, { - "id": "Include skipped listens", - "message": "Include skipped listens", - "translation": "Übersprungene Titel einbeziehen" + "id": "Ignore skipped listens", + "message": "Ignore skipped listens", + "translation": "Übersprungene Listens ignorieren" + }, + { + "id": "Specify a time zone for the listen timestamps", + "message": "Specify a time zone for the listen timestamps", + "translation": "" }, { "id": "Directory path", @@ -319,28 +324,23 @@ "message": "Ignore listens in incognito mode", "translation": "Listens im Inkognito-Modus ignorieren" }, - { - "id": "Ignore skipped listens", - "message": "Ignore skipped listens", - "translation": "Übersprungene Listens ignorieren" - }, { "id": "Minimum playback duration for skipped tracks (seconds)", "message": "Minimum playback duration for skipped tracks (seconds)", "translation": "Minimale Wiedergabedauer für übersprungene Titel (Sekunden)" }, { - "id": "Visit the URL for authorization: {Url}", - "message": "Visit the URL for authorization: {Url}", - "translation": "URL für Autorisierung öffnen: {Url}", + "id": "Visit the URL for authorization: {URL}", + "message": "Visit the URL for authorization: {URL}", + "translation": "", "placeholders": [ { - "id": "Url", + "id": "URL", "string": "%[1]v", "type": "string", "underlyingType": "string", "argNum": 1, - "expr": "authUrl.Url" + "expr": "authURL.URL" } ] }, diff --git a/internal/translations/locales/en/out.gotext.json b/internal/translations/locales/en/out.gotext.json index 54c6719..de7d4d9 100644 --- a/internal/translations/locales/en/out.gotext.json +++ b/internal/translations/locales/en/out.gotext.json @@ -359,9 +359,16 @@ "fuzzy": true }, { - "id": "Include skipped listens", - "message": "Include skipped listens", - "translation": "Include skipped listens", + "id": "Ignore skipped listens", + "message": "Ignore skipped listens", + "translation": "Ignore skipped listens", + "translatorComment": "Copied from source.", + "fuzzy": true + }, + { + "id": "Specify a time zone for the listen timestamps", + "message": "Specify a time zone for the listen timestamps", + "translation": "Specify a time zone for the listen timestamps", "translatorComment": "Copied from source.", "fuzzy": true }, @@ -379,13 +386,6 @@ "translatorComment": "Copied from source.", "fuzzy": true }, - { - "id": "Ignore skipped listens", - "message": "Ignore skipped listens", - "translation": "Ignore skipped listens", - "translatorComment": "Copied from source.", - "fuzzy": true - }, { "id": "Minimum playback duration for skipped tracks (seconds)", "message": "Minimum playback duration for skipped tracks (seconds)", @@ -394,18 +394,18 @@ "fuzzy": true }, { - "id": "Visit the URL for authorization: {Url}", - "message": "Visit the URL for authorization: {Url}", - "translation": "Visit the URL for authorization: {Url}", + "id": "Visit the URL for authorization: {URL}", + "message": "Visit the URL for authorization: {URL}", + "translation": "Visit the URL for authorization: {URL}", "translatorComment": "Copied from source.", "placeholders": [ { - "id": "Url", + "id": "URL", "string": "%[1]v", "type": "string", "underlyingType": "string", "argNum": 1, - "expr": "authUrl.Url" + "expr": "authURL.URL" } ], "fuzzy": true From 90e101080f707311bd539474cb2c7d2cea6920fa Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 29 Apr 2025 13:51:09 +0000 Subject: [PATCH 4/9] Translated using Weblate (German) Currently translated at 100.0% (54 of 54 strings) Co-authored-by: Philipp Wolfer Translate-URL: https://translate.uploadedlobster.com/projects/scotty/app/de/ Translation: Scotty/app --- internal/translations/locales/de/messages.gotext.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/translations/locales/de/messages.gotext.json b/internal/translations/locales/de/messages.gotext.json index afa4129..19a7a25 100644 --- a/internal/translations/locales/de/messages.gotext.json +++ b/internal/translations/locales/de/messages.gotext.json @@ -175,7 +175,7 @@ { "id": "backend {Backend} does not implement {InterfaceName}", "message": "backend {Backend} does not implement {InterfaceName}", - "translation": "das backend {Backend} implementiert {InterfaceName} nicht", + "translation": "das Backend {Backend} implementiert {InterfaceName} nicht", "placeholders": [ { "id": "Backend", @@ -413,7 +413,7 @@ { "id": "Transferring {Entity} from {SourceName} to {TargetName}...", "message": "Transferring {Entity} from {SourceName} to {TargetName}...", - "translation": "Übertrage {Entity} von {SourceName} nach {TargetName}...", + "translation": "Übertrage {Entity} von {SourceName} nach {TargetName}…", "placeholders": [ { "id": "Entity", From a5442b477e3669ca8c3dda7808d8c308d08368e9 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 29 Apr 2025 16:06:13 +0200 Subject: [PATCH 5/9] Sync translations with new strings --- internal/cli/transfer.go | 2 +- internal/translations/catalog.go | 36 ++++++------- .../locales/de/messages.gotext.json | 54 +++++++++---------- .../translations/locales/de/out.gotext.json | 8 +-- .../locales/en/messages.gotext.json | 50 ++++++++--------- .../translations/locales/en/out.gotext.json | 6 +-- 6 files changed, 78 insertions(+), 78 deletions(-) diff --git a/internal/cli/transfer.go b/internal/cli/transfer.go index 427af06..ade7ece 100644 --- a/internal/cli/transfer.go +++ b/internal/cli/transfer.go @@ -88,7 +88,7 @@ func (c *TransferCmd[E, I, R]) resolveBackends(source string, target string) err } func (c *TransferCmd[E, I, R]) Transfer(exp backends.ExportProcessor[R], imp backends.ImportProcessor[R]) error { - fmt.Println(i18n.Tr("Transferring %s from %s to %s...", c.entity, c.sourceName, c.targetName)) + fmt.Println(i18n.Tr("Transferring %s from %s to %s…", c.entity, c.sourceName, c.targetName)) // Authenticate backends, if needed config := viper.GetViper() diff --git a/internal/translations/catalog.go b/internal/translations/catalog.go index c4a7937..374179f 100644 --- a/internal/translations/catalog.go +++ b/internal/translations/catalog.go @@ -76,7 +76,7 @@ var messageKeyToIndex = map[string]int{ "Specify a time zone for the listen timestamps": 52, "The backend %v requires authentication. Authenticate now?": 6, "Token received, you can close this window now.": 12, - "Transferring %s from %s to %s...": 40, + "Transferring %s from %s to %s…": 40, "Unique playlist identifier": 23, "Updated service %v using backend %v\n": 10, "User name": 18, @@ -123,7 +123,7 @@ const deData string = "" + // Size: 1596 bytes "\x02Abgebrochen\x04\x00\x01\x0a\x1e\x02Service „%[1]v“ gelöscht\x04\x00" + "\x01\x0a1\x02Service %[1]v mit dem Backend %[2]v aktualisiert\x04\x01" + "\x09\x00\x0f\x02Backend: %[1]v\x02Token erhalten, das Fenster kann jetzt" + - " geschlossen werden.\x02das backend %[1]s implementiert %[2]s nicht\x02u" + + " geschlossen werden.\x02das Backend %[1]s implementiert %[2]s nicht\x02u" + "nbekanntes Backend „%[1]s“\x02Client-ID\x02Client-Secret\x02Server-URL" + "\x02Benutzername\x02Zugriffstoken\x02Dateipfad\x02An Datei anhängen\x02T" + "itel der Playlist\x02Eindeutige Playlist-ID\x02Beim Import auf Listen-Du" + @@ -134,13 +134,13 @@ const deData string = "" + // Size: 1596 bytes "\x00\x01\x0a;\x02Zugriffstoken erhalten, %[1]v kann jetzt verwendet werd" + "en.\x02exportiere\x02importiere\x02fertig\x02Ja\x02Nein\x02keine bestehe" + "nden Servicekonfigurationen\x02Service\x02Backend\x02Übertrage %[1]s von" + - " %[2]s nach %[3]s...\x02Ab Zeitstempel: %[1]v (%[2]v)\x02Import fehlgesc" + - "hlagen, letzter Zeitstempel war %[1]v (%[2]s)\x02%[1]v von %[2]v %[3]s i" + - "n %[4]v importiert.\x02Importlog:\x02%[1]v: %[2]v\x02ungültiger Zeitstem" + - "pel „%[1]v“\x02Letzter Zeitstempel: %[1]v (%[2]v)\x02keine Konfiguration" + - "sdatei definiert, Konfiguration kann nicht geschrieben werden\x02Schlüss" + - "el darf nur die Zeichen A-Za-z0-9_- beinhalten\x02keine Servicekonfigura" + - "tion „%[1]v“" + " %[2]s nach %[3]s…\x02Ab Zeitstempel: %[1]v (%[2]v)\x02Import fehlgeschl" + + "agen, letzter Zeitstempel war %[1]v (%[2]s)\x02%[1]v von %[2]v %[3]s in " + + "%[4]v importiert.\x02Importlog:\x02%[1]v: %[2]v\x02ungültiger Zeitstempe" + + "l „%[1]v“\x02Letzter Zeitstempel: %[1]v (%[2]v)\x02keine Konfigurationsd" + + "atei definiert, Konfiguration kann nicht geschrieben werden\x02Schlüssel" + + " darf nur die Zeichen A-Za-z0-9_- beinhalten\x02keine Servicekonfigurati" + + "on „%[1]v“" var enIndex = []uint32{ // 55 elements // Entry 0 - 1F @@ -179,13 +179,13 @@ const enData string = "" + // Size: 1507 bytes "\x02Error: OAuth state mismatch\x04\x00\x01\x0a.\x02Access token receive" + "d, you can use %[1]v now.\x02exporting\x02importing\x02done\x02Yes\x02No" + "\x02no existing service configurations\x02Service\x02Backend\x02Transfer" + - "ring %[1]s from %[2]s to %[3]s...\x02From timestamp: %[1]v (%[2]v)\x02Im" + - "port failed, last reported timestamp was %[1]v (%[2]s)\x02Imported %[1]v" + - " of %[2]v %[3]s into %[4]v.\x02Import log:\x02%[1]v: %[2]v\x02invalid ti" + - "mestamp string \x22%[1]v\x22\x02Latest timestamp: %[1]v (%[2]v)\x02no co" + - "nfiguration file defined, cannot write config\x02key must only consist o" + - "f A-Za-z0-9_-\x02no service configuration \x22%[1]v\x22\x02Ignored dupli" + - "cate listen %[1]v: \x22%[2]v\x22 by %[3]v (%[4]v)\x02Specify a time zone" + - " for the listen timestamps\x02Visit the URL for authorization: %[1]v" + "ring %[1]s from %[2]s to %[3]s…\x02From timestamp: %[1]v (%[2]v)\x02Impo" + + "rt failed, last reported timestamp was %[1]v (%[2]s)\x02Imported %[1]v o" + + "f %[2]v %[3]s into %[4]v.\x02Import log:\x02%[1]v: %[2]v\x02invalid time" + + "stamp string \x22%[1]v\x22\x02Latest timestamp: %[1]v (%[2]v)\x02no conf" + + "iguration file defined, cannot write config\x02key must only consist of " + + "A-Za-z0-9_-\x02no service configuration \x22%[1]v\x22\x02Ignored duplica" + + "te listen %[1]v: \x22%[2]v\x22 by %[3]v (%[4]v)\x02Specify a time zone f" + + "or the listen timestamps\x02Visit the URL for authorization: %[1]v" - // Total table size 3591 bytes (3KiB); checksum: 6C862242 + // Total table size 3591 bytes (3KiB); checksum: 2A4B9572 diff --git a/internal/translations/locales/de/messages.gotext.json b/internal/translations/locales/de/messages.gotext.json index 19a7a25..dfa808b 100644 --- a/internal/translations/locales/de/messages.gotext.json +++ b/internal/translations/locales/de/messages.gotext.json @@ -261,9 +261,9 @@ "translation": "Beim Import auf Listen-Duplikate prüfen (langsamer)" }, { - "id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMbid})", - "message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMbid})", - "translation": "Listen-Duplikat ignoriert {ListenedAt}: „{TrackName}“ von {ArtistName} ({RecordingMbid})", + "id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})", + "message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})", + "translation": "", "placeholders": [ { "id": "ListenedAt", @@ -290,12 +290,12 @@ "expr": "l.ArtistName()" }, { - "id": "RecordingMbid", + "id": "RecordingMBID", "string": "%[4]v", - "type": "go.uploadedlobster.com/scotty/internal/models.MBID", + "type": "go.uploadedlobster.com/mbtypes.MBID", "underlyingType": "string", "argNum": 4, - "expr": "l.RecordingMbid" + "expr": "l.RecordingMBID" } ] }, @@ -305,9 +305,14 @@ "translation": "Autokorrektur für übermittelte Titel deaktivieren" }, { - "id": "Include skipped listens", - "message": "Include skipped listens", - "translation": "Übersprungene Titel einbeziehen" + "id": "Ignore skipped listens", + "message": "Ignore skipped listens", + "translation": "Übersprungene Listens ignorieren" + }, + { + "id": "Specify a time zone for the listen timestamps", + "message": "Specify a time zone for the listen timestamps", + "translation": "" }, { "id": "Directory path", @@ -319,28 +324,23 @@ "message": "Ignore listens in incognito mode", "translation": "Listens im Inkognito-Modus ignorieren" }, - { - "id": "Ignore skipped listens", - "message": "Ignore skipped listens", - "translation": "Übersprungene Listens ignorieren" - }, { "id": "Minimum playback duration for skipped tracks (seconds)", "message": "Minimum playback duration for skipped tracks (seconds)", "translation": "Minimale Wiedergabedauer für übersprungene Titel (Sekunden)" }, { - "id": "Visit the URL for authorization: {Url}", - "message": "Visit the URL for authorization: {Url}", - "translation": "URL für Autorisierung öffnen: {Url}", + "id": "Visit the URL for authorization: {URL}", + "message": "Visit the URL for authorization: {URL}", + "translation": "", "placeholders": [ { - "id": "Url", + "id": "URL", "string": "%[1]v", "type": "string", "underlyingType": "string", "argNum": 1, - "expr": "authUrl.Url" + "expr": "authURL.URL" } ] }, @@ -367,23 +367,23 @@ { "id": "exporting", "message": "exporting", + "translation": "exportiere", "translatorComment": "Copied from source.", - "fuzzy": true, - "translation": "exportiere" + "fuzzy": true }, { "id": "importing", "message": "importing", + "translation": "importiere", "translatorComment": "Copied from source.", - "fuzzy": true, - "translation": "importiere" + "fuzzy": true }, { "id": "done", "message": "done", + "translation": "fertig", "translatorComment": "Copied from source.", - "fuzzy": true, - "translation": "fertig" + "fuzzy": true }, { "id": "Yes", @@ -411,8 +411,8 @@ "translation": "Backend" }, { - "id": "Transferring {Entity} from {SourceName} to {TargetName}...", - "message": "Transferring {Entity} from {SourceName} to {TargetName}...", + "id": "Transferring {Entity} from {SourceName} to {TargetName}…", + "message": "Transferring {Entity} from {SourceName} to {TargetName}…", "translation": "Übertrage {Entity} von {SourceName} nach {TargetName}…", "placeholders": [ { diff --git a/internal/translations/locales/de/out.gotext.json b/internal/translations/locales/de/out.gotext.json index 65abfdd..7a13af8 100644 --- a/internal/translations/locales/de/out.gotext.json +++ b/internal/translations/locales/de/out.gotext.json @@ -175,7 +175,7 @@ { "id": "backend {Backend} does not implement {InterfaceName}", "message": "backend {Backend} does not implement {InterfaceName}", - "translation": "das backend {Backend} implementiert {InterfaceName} nicht", + "translation": "das Backend {Backend} implementiert {InterfaceName} nicht", "placeholders": [ { "id": "Backend", @@ -411,9 +411,9 @@ "translation": "Backend" }, { - "id": "Transferring {Entity} from {SourceName} to {TargetName}...", - "message": "Transferring {Entity} from {SourceName} to {TargetName}...", - "translation": "Übertrage {Entity} von {SourceName} nach {TargetName}...", + "id": "Transferring {Entity} from {SourceName} to {TargetName}…", + "message": "Transferring {Entity} from {SourceName} to {TargetName}…", + "translation": "Übertrage {Entity} von {SourceName} nach {TargetName}…", "placeholders": [ { "id": "Entity", diff --git a/internal/translations/locales/en/messages.gotext.json b/internal/translations/locales/en/messages.gotext.json index 7687276..ed62636 100644 --- a/internal/translations/locales/en/messages.gotext.json +++ b/internal/translations/locales/en/messages.gotext.json @@ -311,9 +311,9 @@ "fuzzy": true }, { - "id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMbid})", - "message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMbid})", - "translation": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMbid})", + "id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})", + "message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})", + "translation": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})", "translatorComment": "Copied from source.", "placeholders": [ { @@ -341,12 +341,12 @@ "expr": "l.ArtistName()" }, { - "id": "RecordingMbid", + "id": "RecordingMBID", "string": "%[4]v", - "type": "go.uploadedlobster.com/scotty/internal/models.MBID", + "type": "go.uploadedlobster.com/mbtypes.MBID", "underlyingType": "string", "argNum": 4, - "expr": "l.RecordingMbid" + "expr": "l.RecordingMBID" } ], "fuzzy": true @@ -359,9 +359,16 @@ "fuzzy": true }, { - "id": "Include skipped listens", - "message": "Include skipped listens", - "translation": "Include skipped listens", + "id": "Ignore skipped listens", + "message": "Ignore skipped listens", + "translation": "Ignore skipped listens", + "translatorComment": "Copied from source.", + "fuzzy": true + }, + { + "id": "Specify a time zone for the listen timestamps", + "message": "Specify a time zone for the listen timestamps", + "translation": "Specify a time zone for the listen timestamps", "translatorComment": "Copied from source.", "fuzzy": true }, @@ -379,13 +386,6 @@ "translatorComment": "Copied from source.", "fuzzy": true }, - { - "id": "Ignore skipped listens", - "message": "Ignore skipped listens", - "translation": "Ignore skipped listens", - "translatorComment": "Copied from source.", - "fuzzy": true - }, { "id": "Minimum playback duration for skipped tracks (seconds)", "message": "Minimum playback duration for skipped tracks (seconds)", @@ -394,18 +394,18 @@ "fuzzy": true }, { - "id": "Visit the URL for authorization: {Url}", - "message": "Visit the URL for authorization: {Url}", - "translation": "Visit the URL for authorization: {Url}", + "id": "Visit the URL for authorization: {URL}", + "message": "Visit the URL for authorization: {URL}", + "translation": "Visit the URL for authorization: {URL}", "translatorComment": "Copied from source.", "placeholders": [ { - "id": "Url", + "id": "URL", "string": "%[1]v", "type": "string", "underlyingType": "string", "argNum": 1, - "expr": "authUrl.Url" + "expr": "authURL.URL" } ], "fuzzy": true @@ -491,9 +491,9 @@ "fuzzy": true }, { - "id": "Transferring {Entity} from {SourceName} to {TargetName}...", - "message": "Transferring {Entity} from {SourceName} to {TargetName}...", - "translation": "Transferring {Entity} from {SourceName} to {TargetName}...", + "id": "Transferring {Entity} from {SourceName} to {TargetName}…", + "message": "Transferring {Entity} from {SourceName} to {TargetName}…", + "translation": "Transferring {Entity} from {SourceName} to {TargetName}…", "translatorComment": "Copied from source.", "placeholders": [ { @@ -714,4 +714,4 @@ "fuzzy": true } ] -} \ No newline at end of file +} diff --git a/internal/translations/locales/en/out.gotext.json b/internal/translations/locales/en/out.gotext.json index de7d4d9..eecf359 100644 --- a/internal/translations/locales/en/out.gotext.json +++ b/internal/translations/locales/en/out.gotext.json @@ -491,9 +491,9 @@ "fuzzy": true }, { - "id": "Transferring {Entity} from {SourceName} to {TargetName}...", - "message": "Transferring {Entity} from {SourceName} to {TargetName}...", - "translation": "Transferring {Entity} from {SourceName} to {TargetName}...", + "id": "Transferring {Entity} from {SourceName} to {TargetName}…", + "message": "Transferring {Entity} from {SourceName} to {TargetName}…", + "translation": "Transferring {Entity} from {SourceName} to {TargetName}…", "translatorComment": "Copied from source.", "placeholders": [ { From a6cc8d49ac278694e840d41091bab82ba056e0f3 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 29 Apr 2025 14:11:31 +0000 Subject: [PATCH 6/9] Translated using Weblate (German) Currently translated at 100.0% (54 of 54 strings) Co-authored-by: Philipp Wolfer Translate-URL: https://translate.uploadedlobster.com/projects/scotty/app/de/ Translation: Scotty/app --- .../locales/de/messages.gotext.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/translations/locales/de/messages.gotext.json b/internal/translations/locales/de/messages.gotext.json index dfa808b..8cbe44a 100644 --- a/internal/translations/locales/de/messages.gotext.json +++ b/internal/translations/locales/de/messages.gotext.json @@ -263,7 +263,7 @@ { "id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})", "message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})", - "translation": "", + "translation": "Listen-Duplikat ignoriert {ListenedAt}: \"{TrackName}\" von {ArtistName} ({RecordingMBID})", "placeholders": [ { "id": "ListenedAt", @@ -312,7 +312,7 @@ { "id": "Specify a time zone for the listen timestamps", "message": "Specify a time zone for the listen timestamps", - "translation": "" + "translation": "Zeitzone für den Abspiel-Zeitstempel" }, { "id": "Directory path", @@ -332,7 +332,7 @@ { "id": "Visit the URL for authorization: {URL}", "message": "Visit the URL for authorization: {URL}", - "translation": "", + "translation": "Zur Anmeldung folgende URL aufrufen: {URL}", "placeholders": [ { "id": "URL", @@ -367,23 +367,23 @@ { "id": "exporting", "message": "exporting", - "translation": "exportiere", "translatorComment": "Copied from source.", - "fuzzy": true + "fuzzy": true, + "translation": "exportiere" }, { "id": "importing", "message": "importing", - "translation": "importiere", "translatorComment": "Copied from source.", - "fuzzy": true + "fuzzy": true, + "translation": "importiere" }, { "id": "done", "message": "done", - "translation": "fertig", "translatorComment": "Copied from source.", - "fuzzy": true + "fuzzy": true, + "translation": "fertig" }, { "id": "Yes", From 19852be68b6003c03cd45b1d80db54251954b82b Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 29 Apr 2025 16:12:42 +0200 Subject: [PATCH 7/9] Updated translations --- internal/translations/catalog.go | 152 +++++++++--------- .../translations/locales/de/out.gotext.json | 6 +- 2 files changed, 80 insertions(+), 78 deletions(-) diff --git a/internal/translations/catalog.go b/internal/translations/catalog.go index 374179f..3eb2f7e 100644 --- a/internal/translations/catalog.go +++ b/internal/translations/catalog.go @@ -42,56 +42,56 @@ var messageKeyToIndex = map[string]int{ "\tbackend: %v": 11, "\texport: %s": 0, "\timport: %s\n": 1, - "%v: %v": 45, + "%v: %v": 48, "Aborted": 8, "Access token": 19, - "Access token received, you can use %v now.\n": 31, + "Access token received, you can use %v now.\n": 34, "Append to file": 21, - "Backend": 39, + "Backend": 42, "Check for duplicate listens on import (slower)": 24, "Client ID": 15, "Client secret": 16, "Delete the service configuration \"%v\"?": 7, - "Directory path": 27, - "Disable auto correction of submitted listens": 25, - "Error: OAuth state mismatch": 30, + "Directory path": 29, + "Disable auto correction of submitted listens": 26, + "Error: OAuth state mismatch": 33, "Failed reading config: %v": 2, "File path": 20, - "From timestamp: %v (%v)": 41, - "Ignore listens in incognito mode": 28, - "Ignore skipped listens": 26, - "Ignored duplicate listen %v: \"%v\" by %v (%v)": 51, - "Import failed, last reported timestamp was %v (%s)": 42, - "Import log:": 44, - "Imported %v of %v %s into %v.": 43, - "Latest timestamp: %v (%v)": 47, - "Minimum playback duration for skipped tracks (seconds)": 29, - "No": 36, + "From timestamp: %v (%v)": 44, + "Ignore listens in incognito mode": 30, + "Ignore skipped listens": 27, + "Ignored duplicate listen %v: \"%v\" by %v (%v)": 25, + "Import failed, last reported timestamp was %v (%s)": 45, + "Import log:": 47, + "Imported %v of %v %s into %v.": 46, + "Latest timestamp: %v (%v)": 50, + "Minimum playback duration for skipped tracks (seconds)": 31, + "No": 39, "Playlist title": 22, "Saved service %v using backend %v": 5, "Server URL": 17, - "Service": 38, + "Service": 41, "Service \"%v\" deleted\n": 9, "Service name": 3, - "Specify a time zone for the listen timestamps": 52, + "Specify a time zone for the listen timestamps": 28, "The backend %v requires authentication. Authenticate now?": 6, "Token received, you can close this window now.": 12, - "Transferring %s from %s to %s…": 40, + "Transferring %s from %s to %s…": 43, "Unique playlist identifier": 23, "Updated service %v using backend %v\n": 10, "User name": 18, - "Visit the URL for authorization: %v": 53, - "Yes": 35, + "Visit the URL for authorization: %v": 32, + "Yes": 38, "a service with this name already exists": 4, "backend %s does not implement %s": 13, - "done": 34, - "exporting": 32, - "importing": 33, - "invalid timestamp string \"%v\"": 46, - "key must only consist of A-Za-z0-9_-": 49, - "no configuration file defined, cannot write config": 48, - "no existing service configurations": 37, - "no service configuration \"%v\"": 50, + "done": 37, + "exporting": 35, + "importing": 36, + "invalid timestamp string \"%v\"": 49, + "key must only consist of A-Za-z0-9_-": 52, + "no configuration file defined, cannot write config": 51, + "no existing service configurations": 40, + "no service configuration \"%v\"": 53, "unknown backend \"%s\"": 14, } @@ -103,18 +103,18 @@ var deIndex = []uint32{ // 55 elements 0x000001ac, 0x000001e7, 0x00000213, 0x00000233, 0x0000023d, 0x0000024b, 0x00000256, 0x00000263, 0x00000271, 0x0000027b, 0x0000028e, 0x000002a1, - 0x000002b8, 0x000002ed, 0x00000321, 0x00000343, - 0x00000353, 0x00000379, 0x000003b7, 0x000003e1, + 0x000002b8, 0x000002ed, 0x00000328, 0x0000035c, + 0x0000037e, 0x000003a4, 0x000003b4, 0x000003da, // Entry 20 - 3F - 0x00000421, 0x0000042c, 0x00000437, 0x0000043e, - 0x00000441, 0x00000446, 0x0000046f, 0x00000477, - 0x0000047f, 0x000004a8, 0x000004c6, 0x00000503, - 0x0000052e, 0x00000539, 0x00000546, 0x0000056a, - 0x0000058d, 0x000005de, 0x00000615, 0x0000063c, - 0x0000063c, 0x0000063c, 0x0000063c, + 0x00000418, 0x00000443, 0x0000046d, 0x000004ad, + 0x000004b8, 0x000004c3, 0x000004ca, 0x000004cd, + 0x000004d2, 0x000004fb, 0x00000503, 0x0000050b, + 0x00000534, 0x00000552, 0x0000058f, 0x000005ba, + 0x000005c5, 0x000005d2, 0x000005f6, 0x00000619, + 0x0000066a, 0x000006a1, 0x000006c8, } // Size: 244 bytes -const deData string = "" + // Size: 1596 bytes +const deData string = "" + // Size: 1736 bytes "\x04\x01\x09\x00\x0e\x02Export: %[1]s\x04\x01\x09\x01\x0a\x0e\x02Import:" + " %[1]s\x02Fehler beim Lesen der Konfiguration: %[1]v\x02Servicename\x02e" + "in Service mit diesem Namen existiert bereits\x02Service %[1]v mit dem B" + @@ -127,20 +127,22 @@ const deData string = "" + // Size: 1596 bytes "nbekanntes Backend „%[1]s“\x02Client-ID\x02Client-Secret\x02Server-URL" + "\x02Benutzername\x02Zugriffstoken\x02Dateipfad\x02An Datei anhängen\x02T" + "itel der Playlist\x02Eindeutige Playlist-ID\x02Beim Import auf Listen-Du" + - "plikate prüfen (langsamer)\x02Autokorrektur für übermittelte Titel deakt" + - "ivieren\x02Übersprungene Listens ignorieren\x02Verzeichnispfad\x02Listen" + - "s im Inkognito-Modus ignorieren\x02Minimale Wiedergabedauer für überspru" + - "ngene Titel (Sekunden)\x02Fehler: OAuth-State stimmt nicht überein\x04" + - "\x00\x01\x0a;\x02Zugriffstoken erhalten, %[1]v kann jetzt verwendet werd" + - "en.\x02exportiere\x02importiere\x02fertig\x02Ja\x02Nein\x02keine bestehe" + - "nden Servicekonfigurationen\x02Service\x02Backend\x02Übertrage %[1]s von" + - " %[2]s nach %[3]s…\x02Ab Zeitstempel: %[1]v (%[2]v)\x02Import fehlgeschl" + - "agen, letzter Zeitstempel war %[1]v (%[2]s)\x02%[1]v von %[2]v %[3]s in " + - "%[4]v importiert.\x02Importlog:\x02%[1]v: %[2]v\x02ungültiger Zeitstempe" + - "l „%[1]v“\x02Letzter Zeitstempel: %[1]v (%[2]v)\x02keine Konfigurationsd" + - "atei definiert, Konfiguration kann nicht geschrieben werden\x02Schlüssel" + - " darf nur die Zeichen A-Za-z0-9_- beinhalten\x02keine Servicekonfigurati" + - "on „%[1]v“" + "plikate prüfen (langsamer)\x02Listen-Duplikat ignoriert %[1]v: \x22%[2]v" + + "\x22 von %[3]v (%[4]v)\x02Autokorrektur für übermittelte Titel deaktivie" + + "ren\x02Übersprungene Listens ignorieren\x02Zeitzone für den Abspiel-Zeit" + + "stempel\x02Verzeichnispfad\x02Listens im Inkognito-Modus ignorieren\x02M" + + "inimale Wiedergabedauer für übersprungene Titel (Sekunden)\x02Zur Anmeld" + + "ung folgende URL aufrufen: %[1]v\x02Fehler: OAuth-State stimmt nicht übe" + + "rein\x04\x00\x01\x0a;\x02Zugriffstoken erhalten, %[1]v kann jetzt verwen" + + "det werden.\x02exportiere\x02importiere\x02fertig\x02Ja\x02Nein\x02keine" + + " bestehenden Servicekonfigurationen\x02Service\x02Backend\x02Übertrage %" + + "[1]s von %[2]s nach %[3]s…\x02Ab Zeitstempel: %[1]v (%[2]v)\x02Import fe" + + "hlgeschlagen, letzter Zeitstempel war %[1]v (%[2]s)\x02%[1]v von %[2]v %" + + "[3]s in %[4]v importiert.\x02Importlog:\x02%[1]v: %[2]v\x02ungültiger Ze" + + "itstempel „%[1]v“\x02Letzter Zeitstempel: %[1]v (%[2]v)\x02keine Konfigu" + + "rationsdatei definiert, Konfiguration kann nicht geschrieben werden\x02S" + + "chlüssel darf nur die Zeichen A-Za-z0-9_- beinhalten\x02keine Servicekon" + + "figuration „%[1]v“" var enIndex = []uint32{ // 55 elements // Entry 0 - 1F @@ -150,15 +152,15 @@ var enIndex = []uint32{ // 55 elements 0x00000170, 0x0000019f, 0x000001c6, 0x000001de, 0x000001e8, 0x000001f6, 0x00000201, 0x0000020b, 0x00000218, 0x00000222, 0x00000231, 0x00000240, - 0x0000025b, 0x0000028a, 0x000002b7, 0x000002ce, - 0x000002dd, 0x000002fe, 0x00000335, 0x00000351, + 0x0000025b, 0x0000028a, 0x000002c3, 0x000002f0, + 0x00000307, 0x00000335, 0x00000344, 0x00000365, // Entry 20 - 3F - 0x00000384, 0x0000038e, 0x00000398, 0x0000039d, - 0x000003a1, 0x000003a4, 0x000003c7, 0x000003cf, - 0x000003d7, 0x00000401, 0x0000041f, 0x00000458, - 0x00000482, 0x0000048e, 0x0000049b, 0x000004bc, - 0x000004dc, 0x0000050f, 0x00000534, 0x00000555, - 0x0000058e, 0x000005bc, 0x000005e3, + 0x0000039c, 0x000003c3, 0x000003df, 0x00000412, + 0x0000041c, 0x00000426, 0x0000042b, 0x0000042f, + 0x00000432, 0x00000455, 0x0000045d, 0x00000465, + 0x0000048f, 0x000004ad, 0x000004e6, 0x00000510, + 0x0000051c, 0x00000529, 0x0000054a, 0x0000056a, + 0x0000059d, 0x000005c2, 0x000005e3, } // Size: 244 bytes const enData string = "" + // Size: 1507 bytes @@ -173,19 +175,19 @@ const enData string = "" + // Size: 1507 bytes "ent %[2]s\x02unknown backend \x22%[1]s\x22\x02Client ID\x02Client secret" + "\x02Server URL\x02User name\x02Access token\x02File path\x02Append to fi" + "le\x02Playlist title\x02Unique playlist identifier\x02Check for duplicat" + - "e listens on import (slower)\x02Disable auto correction of submitted lis" + - "tens\x02Ignore skipped listens\x02Directory path\x02Ignore listens in in" + - "cognito mode\x02Minimum playback duration for skipped tracks (seconds)" + - "\x02Error: OAuth state mismatch\x04\x00\x01\x0a.\x02Access token receive" + - "d, you can use %[1]v now.\x02exporting\x02importing\x02done\x02Yes\x02No" + - "\x02no existing service configurations\x02Service\x02Backend\x02Transfer" + - "ring %[1]s from %[2]s to %[3]s…\x02From timestamp: %[1]v (%[2]v)\x02Impo" + - "rt failed, last reported timestamp was %[1]v (%[2]s)\x02Imported %[1]v o" + - "f %[2]v %[3]s into %[4]v.\x02Import log:\x02%[1]v: %[2]v\x02invalid time" + - "stamp string \x22%[1]v\x22\x02Latest timestamp: %[1]v (%[2]v)\x02no conf" + - "iguration file defined, cannot write config\x02key must only consist of " + - "A-Za-z0-9_-\x02no service configuration \x22%[1]v\x22\x02Ignored duplica" + - "te listen %[1]v: \x22%[2]v\x22 by %[3]v (%[4]v)\x02Specify a time zone f" + - "or the listen timestamps\x02Visit the URL for authorization: %[1]v" + "e listens on import (slower)\x02Ignored duplicate listen %[1]v: \x22%[2]" + + "v\x22 by %[3]v (%[4]v)\x02Disable auto correction of submitted listens" + + "\x02Ignore skipped listens\x02Specify a time zone for the listen timesta" + + "mps\x02Directory path\x02Ignore listens in incognito mode\x02Minimum pla" + + "yback duration for skipped tracks (seconds)\x02Visit the URL for authori" + + "zation: %[1]v\x02Error: OAuth state mismatch\x04\x00\x01\x0a.\x02Access " + + "token received, you can use %[1]v now.\x02exporting\x02importing\x02done" + + "\x02Yes\x02No\x02no existing service configurations\x02Service\x02Backen" + + "d\x02Transferring %[1]s from %[2]s to %[3]s…\x02From timestamp: %[1]v (%" + + "[2]v)\x02Import failed, last reported timestamp was %[1]v (%[2]s)\x02Imp" + + "orted %[1]v of %[2]v %[3]s into %[4]v.\x02Import log:\x02%[1]v: %[2]v" + + "\x02invalid timestamp string \x22%[1]v\x22\x02Latest timestamp: %[1]v (%" + + "[2]v)\x02no configuration file defined, cannot write config\x02key must " + + "only consist of A-Za-z0-9_-\x02no service configuration \x22%[1]v\x22" - // Total table size 3591 bytes (3KiB); checksum: 2A4B9572 + // Total table size 3731 bytes (3KiB); checksum: F7951710 diff --git a/internal/translations/locales/de/out.gotext.json b/internal/translations/locales/de/out.gotext.json index 7a13af8..680505e 100644 --- a/internal/translations/locales/de/out.gotext.json +++ b/internal/translations/locales/de/out.gotext.json @@ -263,7 +263,7 @@ { "id": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})", "message": "Ignored duplicate listen {ListenedAt}: \"{TrackName}\" by {ArtistName} ({RecordingMBID})", - "translation": "", + "translation": "Listen-Duplikat ignoriert {ListenedAt}: \"{TrackName}\" von {ArtistName} ({RecordingMBID})", "placeholders": [ { "id": "ListenedAt", @@ -312,7 +312,7 @@ { "id": "Specify a time zone for the listen timestamps", "message": "Specify a time zone for the listen timestamps", - "translation": "" + "translation": "Zeitzone für den Abspiel-Zeitstempel" }, { "id": "Directory path", @@ -332,7 +332,7 @@ { "id": "Visit the URL for authorization: {URL}", "message": "Visit the URL for authorization: {URL}", - "translation": "", + "translation": "Zur Anmeldung folgende URL aufrufen: {URL}", "placeholders": [ { "id": "URL", From 1e91b684cb547946d9f47a7830fbea0368142f12 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 29 Apr 2025 16:16:43 +0200 Subject: [PATCH 8/9] Release 0.5.0 --- CHANGES.md | 2 +- internal/version/version.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index cda0d79..7324f77 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Scotty Changelog -## 0.5.0 - (not yet released) +## 0.5.0 - 2025-04-29 - ListenBrainz: handle missing loves metadata in case of merged recordings - ListenBrainz: fix loves import loading all existing loves - ListenBrainz: fixed progress for loves import diff --git a/internal/version/version.go b/internal/version/version.go index 818bec1..07d1569 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -1,5 +1,5 @@ /* -Copyright © 2023-2024 Philipp Wolfer +Copyright © 2023-2025 Philipp Wolfer Scotty is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -17,7 +17,7 @@ package version const ( AppName = "scotty" - AppVersion = "0.4.1" + AppVersion = "0.5.0" AppURL = "https://git.sr.ht/~phw/scotty/" ) From 0a411fe2fa90a0db8edc82316f7d2534c88c0c9f Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 29 Apr 2025 17:25:10 +0200 Subject: [PATCH 9/9] If locale detection fails fall back to English --- internal/i18n/i18n.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/internal/i18n/i18n.go b/internal/i18n/i18n.go index cbfd516..a910ca0 100644 --- a/internal/i18n/i18n.go +++ b/internal/i18n/i18n.go @@ -16,11 +16,10 @@ Scotty. If not, see . package i18n import ( - "log" - "github.com/Xuanwo/go-locale" _ "go.uploadedlobster.com/scotty/internal/translations" + "golang.org/x/text/language" "golang.org/x/text/message" ) @@ -29,7 +28,7 @@ var localizer Localizer func init() { tag, err := locale.Detect() if err != nil { - log.Fatal(err) + tag = language.English } localizer = New(tag) }