Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions android/app/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,16 @@
<string name="m_settings_theme_system">Système</string>
<string name="m_settings_theme_system_hint">Suit ton téléphone</string>
<string name="m_settings_title">Réglages</string>
<string name="m_stats_n_available">%1$s disponible | %1$s disponibles</string>
<string name="m_stats_n_declined">%1$s refusée | %1$s refusées</string>
<string name="m_stats_n_episodes">%1$s épisode regardé | %1$s épisodes regardés</string>
<string name="m_stats_n_movies">%1$s film | %1$s films</string>
<string name="m_stats_n_plays">%1$s lecture | %1$s lectures</string>
<string name="m_stats_n_shows">%1$s série | %1$s séries</string>
<string name="m_stats_n_titles">%1$s titre | %1$s titres</string>
<string name="m_stats_never_hint">%1$s titre de la bibliothèque que personne n’a jamais lu, les plus anciens d’abord (admins uniquement). | %1$s titres de la bibliothèque que personne n’a jamais lus, les plus anciens d’abord (admins uniquement).</string>
<string name="m_stats_open">Statistiques</string>
<string name="m_stats_unwatched_more">et %1$s autre | et %1$s autres</string>
<string name="m_sync_counts">%1$s films et %2$s séries connus dans la bibliothèque.</string>
<string name="m_sync_every">Toutes les %s</string>
<string name="m_sync_last">Dernier lancement %s</string>
Expand Down
9 changes: 9 additions & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,16 @@
<string name="m_settings_theme_system">System</string>
<string name="m_settings_theme_system_hint">Follows your phone</string>
<string name="m_settings_title">Settings</string>
<string name="m_stats_n_available">%1$s available | %1$s available</string>
<string name="m_stats_n_declined">%1$s declined | %1$s declined</string>
<string name="m_stats_n_episodes">%1$s episode watched | %1$s episodes watched</string>
<string name="m_stats_n_movies">%1$s movie | %1$s movies</string>
<string name="m_stats_n_plays">%1$s play | %1$s plays</string>
<string name="m_stats_n_shows">%1$s TV show | %1$s TV shows</string>
<string name="m_stats_n_titles">%1$s title | %1$s titles</string>
<string name="m_stats_never_hint">%1$s title in the library that nobody ever played, oldest first (admins only). | %1$s titles in the library that nobody ever played, oldest first (admins only).</string>
<string name="m_stats_open">Statistics</string>
<string name="m_stats_unwatched_more">and %1$s more | and %1$s more</string>
<string name="m_sync_counts">%1$s movies and %2$s TV shows known in the library.</string>
<string name="m_sync_every">Runs every %s</string>
<string name="m_sync_last">Last run %s</string>
Expand Down
7 changes: 6 additions & 1 deletion backend/internal/api/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api
import (
"context"
"github.com/Rombond/tipsarr/backend/internal/teasers"
"log/slog"
"net/http"
"regexp"

Expand Down Expand Up @@ -102,7 +103,11 @@ func registerUsers(api huma.API, d Deps) {
return nil, err
}
if u.Language != before && d.Suggestions != nil {
d.Suggestions.QueueRefresh(u.ID) // stored suggestion rows hold titles in the old language
// stored suggestion rows hold titles in the old language: drop them, the next read builds them in the new one
if err := d.Suggestions.Forget(ctx, u.ID); err != nil {
slog.Warn("suggestions: forget after a language change", "user", u.ID, "err", err)
d.Suggestions.QueueRefresh(u.ID)
}
}
return &meOutput{Body: u}, nil
})
Expand Down
13 changes: 13 additions & 0 deletions backend/internal/server/suggestions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,19 @@ func TestSuggestions(t *testing.T) {
t.Fatal("reading stored suggestions must not call TMDB")
}

// a new language drops the stored rows (they hold titles in the old one): the next read builds them again at once
if resp, body := call(t, e.app, "PATCH", "/api/v1/me", `{"language":"fr"}`, admin); resp.StatusCode != 200 {
t.Fatalf("language change = %d %s", resp.StatusCode, body)
}
if stored, _, _ := e.st.SuggestionRows(ctx, alice); len(stored) != 0 {
t.Fatalf("rows kept after a language change: %d", len(stored))
}
if again, _ := getSuggestions(t, e, admin); len(again.Rows) != 3 || again.Generating {
t.Fatalf("read after a language change = %+v", again)
}
call(t, e.app, "PATCH", "/api/v1/me", `{"language":""}`, admin)
getSuggestions(t, e, admin)

// bob has no history: seeded from what the server watches, no "because" rows
bres, _ := getSuggestions(t, e, bob)
if len(bres.Rows) != 1 || bres.Rows[0].Title != "Popular on this server" || bres.Rows[0].Personal {
Expand Down
11 changes: 11 additions & 0 deletions backend/internal/suggestions/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,17 @@ func (s *Service) Force(ctx context.Context, userID string) error {
return nil
}

// Forget drops the stored rows of one user, so the next read builds them again (synchronously, like a first visit).
// Used when their language changed: the rows hold titles, posters and overviews in the old one, and a background
// refresh would leave them on screen until a suggestions.updated event reached the app. It waits for a running
// Generate, which would otherwise store rows in the old language after this.
func (s *Service) Forget(ctx context.Context, userID string) error {
lock := s.userLock(userID)
lock.Lock()
defer lock.Unlock()
return s.store.ReplaceSuggestions(ctx, userID, nil, nil)
}

// QueueRefresh schedules a debounced background regeneration (used when history changed), for the person and for
// everyone whose recommendations borrow from them. The version check already refreshes those rows when they are next
// read; this only makes it sooner.
Expand Down
173 changes: 163 additions & 10 deletions design/generated/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -4539,13 +4539,13 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "Signing out removes an account from this iPhone."
"value": "Signing out removes an account from this device."
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Se déconnecter retire un compte de cet iPhone."
"value": "Se déconnecter retire un compte de cet appareil."
}
}
}
Expand Down Expand Up @@ -7123,13 +7123,13 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "Your password is kept in the iPhone’s Keychain, protected by Face ID or your passcode. It is only used to sign you back in when your session ends."
"value": "Your password is kept in the device’s Keychain, protected by Face ID or your passcode. It is only used to sign you back in when your session ends."
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Ton mot de passe est conservé dans le trousseau de l’iPhone, protégé par Face ID ou ton code. Il sert uniquement à te reconnecter quand ta session se termine."
"value": "Ton mot de passe est conservé dans le trousseau de l’appareil, protégé par Face ID ou ton code. Il sert uniquement à te reconnecter quand ta session se termine."
}
}
}
Expand All @@ -7155,13 +7155,13 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "Default (iPhone language)"
"value": "Default (device language)"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Par défaut (langue de l’iPhone)"
"value": "Par défaut (langue de l’appareil)"
}
}
}
Expand Down Expand Up @@ -7459,13 +7459,13 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "Sign out of Tipsarr on this iPhone?"
"value": "Sign out of Tipsarr on this device?"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Se déconnecter de Tipsarr sur cet iPhone ?"
"value": "Se déconnecter de Tipsarr sur cet appareil ?"
}
}
}
Expand Down Expand Up @@ -7507,13 +7507,13 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "Follows your iPhone"
"value": "Follows your device"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Suit ton iPhone"
"value": "Suit ton appareil"
}
}
}
Expand All @@ -7534,6 +7534,142 @@
}
}
},
"m.stats.n_available": {
"comment": "placeholders: count, count",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "%1$@ available | %1$@ available"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "%1$@ disponible | %1$@ disponibles"
}
}
}
},
"m.stats.n_declined": {
"comment": "placeholders: count, count",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "%1$@ declined | %1$@ declined"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "%1$@ refusée | %1$@ refusées"
}
}
}
},
"m.stats.n_episodes": {
"comment": "placeholders: count, count",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "%1$@ episode watched | %1$@ episodes watched"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "%1$@ épisode regardé | %1$@ épisodes regardés"
}
}
}
},
"m.stats.n_movies": {
"comment": "placeholders: count, count",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "%1$@ movie | %1$@ movies"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "%1$@ film | %1$@ films"
}
}
}
},
"m.stats.n_plays": {
"comment": "placeholders: count, count",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "%1$@ play | %1$@ plays"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "%1$@ lecture | %1$@ lectures"
}
}
}
},
"m.stats.n_shows": {
"comment": "placeholders: count, count",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "%1$@ TV show | %1$@ TV shows"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "%1$@ série | %1$@ séries"
}
}
}
},
"m.stats.n_titles": {
"comment": "placeholders: count, count",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "%1$@ title | %1$@ titles"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "%1$@ titre | %1$@ titres"
}
}
}
},
"m.stats.never_hint": {
"comment": "placeholders: count, count",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "%1$@ title in the library that nobody ever played, oldest first (admins only). | %1$@ titles in the library that nobody ever played, oldest first (admins only)."
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "%1$@ titre de la bibliothèque que personne n’a jamais lu, les plus anciens d’abord (admins uniquement). | %1$@ titres de la bibliothèque que personne n’a jamais lus, les plus anciens d’abord (admins uniquement)."
}
}
}
},
"m.stats.open": {
"localizations": {
"en": {
Expand All @@ -7550,6 +7686,23 @@
}
}
},
"m.stats.unwatched_more": {
"comment": "placeholders: count, count",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "and %1$@ more | and %1$@ more"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "et %1$@ autre | et %1$@ autres"
}
}
}
},
"m.sync.counts": {
"localizations": {
"en": {
Expand Down
9 changes: 9 additions & 0 deletions design/generated/android/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,16 @@
<string name="m_settings_theme_system">Système</string>
<string name="m_settings_theme_system_hint">Suit ton téléphone</string>
<string name="m_settings_title">Réglages</string>
<string name="m_stats_n_available">%1$s disponible | %1$s disponibles</string>
<string name="m_stats_n_declined">%1$s refusée | %1$s refusées</string>
<string name="m_stats_n_episodes">%1$s épisode regardé | %1$s épisodes regardés</string>
<string name="m_stats_n_movies">%1$s film | %1$s films</string>
<string name="m_stats_n_plays">%1$s lecture | %1$s lectures</string>
<string name="m_stats_n_shows">%1$s série | %1$s séries</string>
<string name="m_stats_n_titles">%1$s titre | %1$s titres</string>
<string name="m_stats_never_hint">%1$s titre de la bibliothèque que personne n’a jamais lu, les plus anciens d’abord (admins uniquement). | %1$s titres de la bibliothèque que personne n’a jamais lus, les plus anciens d’abord (admins uniquement).</string>
<string name="m_stats_open">Statistiques</string>
<string name="m_stats_unwatched_more">et %1$s autre | et %1$s autres</string>
<string name="m_sync_counts">%1$s films et %2$s séries connus dans la bibliothèque.</string>
<string name="m_sync_every">Toutes les %s</string>
<string name="m_sync_last">Dernier lancement %s</string>
Expand Down
9 changes: 9 additions & 0 deletions design/generated/android/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,16 @@
<string name="m_settings_theme_system">System</string>
<string name="m_settings_theme_system_hint">Follows your phone</string>
<string name="m_settings_title">Settings</string>
<string name="m_stats_n_available">%1$s available | %1$s available</string>
<string name="m_stats_n_declined">%1$s declined | %1$s declined</string>
<string name="m_stats_n_episodes">%1$s episode watched | %1$s episodes watched</string>
<string name="m_stats_n_movies">%1$s movie | %1$s movies</string>
<string name="m_stats_n_plays">%1$s play | %1$s plays</string>
<string name="m_stats_n_shows">%1$s TV show | %1$s TV shows</string>
<string name="m_stats_n_titles">%1$s title | %1$s titles</string>
<string name="m_stats_never_hint">%1$s title in the library that nobody ever played, oldest first (admins only). | %1$s titles in the library that nobody ever played, oldest first (admins only).</string>
<string name="m_stats_open">Statistics</string>
<string name="m_stats_unwatched_more">and %1$s more | and %1$s more</string>
<string name="m_sync_counts">%1$s movies and %2$s TV shows known in the library.</string>
<string name="m_sync_every">Runs every %s</string>
<string name="m_sync_last">Last run %s</string>
Expand Down
Loading
Loading