Compare commits

..
Author SHA1 Message Date
advplyr bee88c43e5 Add play button to book library list view 2025-07-04 18:07:05 -05:00
advplyr ba4e9ab7e3 Add explicit library filters 2025-07-03 17:40:02 -05:00
advplyrandGitHub 1b4fa5e44a Merge pull request #1610 from weblate/weblate-audiobookshelf-abs-mobile-app
Translations update from Hosted Weblate
2025-07-03 17:32:02 -05:00
FiendFEARingandHosted Weblate e92c9b2990 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (352 of 352 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/zh_Hans/
2025-07-02 20:16:41 +02:00
FiendFEARingandHosted Weblate f23f8e9ade Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (352 of 352 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/zh_Hans/
2025-07-02 20:16:39 +02:00
DavevanIerselandHosted Weblate dc00aeece4 Translated using Weblate (Dutch)
Currently translated at 100.0% (352 of 352 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/nl/
2025-07-02 20:16:37 +02:00
Vito0912andHosted Weblate 4fdea9b0ec Translated using Weblate (German)
Currently translated at 99.7% (351 of 352 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/de/
2025-06-30 00:32:39 +02:00
Vito0912andHosted Weblate 3ded7687f7 Translated using Weblate (German)
Currently translated at 99.7% (351 of 352 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/de/
2025-06-30 00:32:38 +02:00
Eigen_artandHosted Weblate 42119425af Translated using Weblate (Ukrainian)
Currently translated at 100.0% (352 of 352 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/uk/
2025-06-30 00:32:38 +02:00
Dan JohansenandHosted Weblate 93c7e1c44a Translated using Weblate (Danish)
Currently translated at 100.0% (352 of 352 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/da/
2025-06-30 00:32:37 +02:00
Michael FörsterandHosted Weblate 381fd84839 Translated using Weblate (German)
Currently translated at 99.7% (351 of 352 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/de/
2025-06-30 00:32:36 +02:00
advplyr 67bab72783 Update podcast library latest page number of episodes to 50 #1615 2025-06-29 17:32:29 -05:00
advplyrandGitHub b9c084a442 Merge pull request #1612 from advplyr/create_bookmarks_focus
Update create bookmark to not autofocus input and use placeholder
2025-06-22 17:51:26 -05:00
10 changed files with 150 additions and 71 deletions
+45 -6
View File
@@ -14,7 +14,7 @@
<!-- No progress shown for collapsed series or podcasts in library -->
<div v-if="!isPodcast && !collapsedSeries" class="absolute bottom-0 left-0 h-1 shadow-sm max-w-full z-10 rounded-b" :class="itemIsFinished ? 'bg-success' : 'bg-yellow-400'" :style="{ width: coverWidth * userProgressPercent + 'px' }"></div>
</div>
<div class="flex-grow px-2">
<div class="flex-grow pl-2" :class="showPlayButton ? 'pr-12' : 'pr-2'">
<p class="whitespace-normal line-clamp-2" :style="{ fontSize: 0.8 * sizeMultiplier + 'rem' }">
<span v-if="seriesSequence">#{{ seriesSequence }}&nbsp;</span>{{ displayTitle }}
</p>
@@ -29,6 +29,11 @@
{{ $getString('LabelNumEpisodes', [numEpisodes]) }}
</p>
</div>
<div v-if="showPlayButton" class="absolute top-0 bottom-0 right-0 h-full flex items-center justify-center z-20 pr-1">
<button type="button" class="p-2 rounded-full bg-fg-muted/50" @click.stop.prevent="play">
<span class="material-symbols text-2xl fill text-white">{{ playerIsPlaying ? 'pause' : 'play_arrow' }}</span>
</button>
</div>
<div v-if="localLibraryItem || isLocal" class="absolute top-0 right-0 z-20" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }">
<span class="material-symbols text-2xl text-success">download_done</span>
@@ -129,6 +134,9 @@ export default {
libraryItemId() {
return this._libraryItem.id
},
localLibraryItemId() {
return this.localLibraryItem?.id
},
series() {
return this.mediaMetadata.series
},
@@ -217,13 +225,23 @@ export default {
return this.isMissing || this.isInvalid
},
isStreaming() {
return this.store.getters['getlibraryItemIdStreaming'] === this.libraryItemId
return this.isPlaying && !this.store.getters['getIsCurrentSessionLocal']
},
isPlaying() {
if (this.localLibraryItemId && this.store.getters['getIsMediaStreaming'](this.localLibraryItemId)) return true
return this.store.getters['getIsMediaStreaming'](this.libraryItemId)
},
playerIsPlaying() {
return this.store.state.playerIsPlaying && (this.isStreaming || this.isPlaying)
},
isCasting() {
return this.store.state.isCasting
},
showReadButton() {
return !this.isSelectionMode && !this.showPlayButton && this.hasEbook
},
showPlayButton() {
return !this.isSelectionMode && !this.isMissing && !this.isInvalid && this.numTracks && !this.isStreaming
return !this.isSelectionMode && !this.isMissing && !this.isInvalid && this.numTracks && !this.isPodcast
},
showSmallEBookIcon() {
return !this.isSelectionMode && this.hasEbook
@@ -293,9 +311,30 @@ export default {
this.selected = !this.selected
this.$emit('select', this.libraryItem)
},
play() {
var eventBus = this.$eventBus || this.$nuxt.$eventBus
eventBus.$emit('play-item', { libraryItemId: this.libraryItemId })
async play() {
const hapticsImpact = this.$hapticsImpact || this.$nuxt.$hapticsImpact
if (hapticsImpact) {
await hapticsImpact()
}
const eventBus = this.$eventBus || this.$nuxt.$eventBus
if (this.playerIsPlaying) {
eventBus.$emit('pause-item')
} else {
// Audiobook
let libraryItemId = this.libraryItemId
// When casting use server library item
if (this.localLibraryItem && !this.isCasting) {
libraryItemId = this.localLibraryItem.id
} else if (this.hasLocal) {
libraryItemId = this.localLibraryItem.id
}
this.store.commit('setPlayerIsStartingPlayback', libraryItemId)
eventBus.$emit('play-item', { libraryItemId, serverLibraryItemId: this.libraryItemId })
}
},
destroy() {
// destroy the vue listeners, etc
+56 -29
View File
@@ -54,8 +54,39 @@ export default {
},
data() {
return {
sublist: null,
bookItems: [
sublist: null
}
},
watch: {
show(newVal) {
if (!newVal) {
if (this.sublist && !this.selectedItemSublist) this.sublist = null
if (!this.sublist && this.selectedItemSublist) this.sublist = this.selectedItemSublist
}
}
},
computed: {
show: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
selected: {
get() {
return this.filterBy
},
set(val) {
this.$emit('update:filterBy', val)
}
},
userCanAccessExplicitContent() {
return this.$store.getters['user/getUserCanAccessExplicitContent']
},
bookItems() {
const items = [
{
text: this.$strings.LabelAll,
value: 'all'
@@ -110,8 +141,20 @@ export default {
value: 'feed-open',
sublist: false
}
],
podcastItems: [
]
if (this.userCanAccessExplicitContent) {
items.push({
text: this.$strings.LabelExplicit,
value: 'explicit',
sublist: false
})
}
return items
},
podcastItems() {
const items = [
{
text: this.$strings.LabelAll,
value: 'all'
@@ -132,32 +175,16 @@ export default {
sublist: false
}
]
}
},
watch: {
show(newVal) {
if (!newVal) {
if (this.sublist && !this.selectedItemSublist) this.sublist = null
if (!this.sublist && this.selectedItemSublist) this.sublist = this.selectedItemSublist
}
}
},
computed: {
show: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
selected: {
get() {
return this.filterBy
},
set(val) {
this.$emit('update:filterBy', val)
if (this.userCanAccessExplicitContent) {
items.push({
text: this.$strings.LabelExplicit,
value: 'explicit',
sublist: false
})
}
return items
},
isPodcast() {
return this.$store.getters['libraries/getCurrentLibraryMediaType'] === 'podcast'
+1 -1
View File
@@ -62,7 +62,7 @@ export default {
async loadRecentEpisodes(page = 0) {
this.loadedLibraryId = this.currentLibraryId
this.processing = true
const episodePayload = await this.$nativeHttp.get(`/api/libraries/${this.currentLibraryId}/recent-episodes?limit=25&page=${page}`).catch((error) => {
const episodePayload = await this.$nativeHttp.get(`/api/libraries/${this.currentLibraryId}/recent-episodes?limit=50&page=${page}`).catch((error) => {
console.error('Failed to get recent episodes', error)
this.$toast.error('Failed to get recent episodes')
return null
+17 -12
View File
@@ -31,16 +31,18 @@ export const getters = {
getCustomHeaders: (state) => {
return state.serverConnectionConfig?.customHeaders || null
},
getUserMediaProgress: (state) => (libraryItemId, episodeId = null) => {
if (!state.user?.mediaProgress) return null
return state.user.mediaProgress.find(li => {
if (episodeId && li.episodeId !== episodeId) return false
return li.libraryItemId == libraryItemId
})
},
getUserMediaProgress:
(state) =>
(libraryItemId, episodeId = null) => {
if (!state.user?.mediaProgress) return null
return state.user.mediaProgress.find((li) => {
if (episodeId && li.episodeId !== episodeId) return false
return li.libraryItemId == libraryItemId
})
},
getUserBookmarksForItem: (state) => (libraryItemId) => {
if (!state?.user?.bookmarks) return []
return state.user.bookmarks.filter(bm => bm.libraryItemId === libraryItemId)
return state.user.bookmarks.filter((bm) => bm.libraryItemId === libraryItemId)
},
getUserSetting: (state) => (key) => {
return state.settings?.[key] || null
@@ -53,6 +55,9 @@ export const getters = {
},
getUserCanDownload: (state) => {
return !!state.user?.permissions?.download
},
getUserCanAccessExplicitContent: (state) => {
return !!state.user?.permissions?.accessExplicitContent
}
}
@@ -145,11 +150,11 @@ export const mutations = {
},
removeMediaProgress(state, id) {
if (!state.user) return
state.user.mediaProgress = state.user.mediaProgress.filter(mp => mp.id != id)
state.user.mediaProgress = state.user.mediaProgress.filter((mp) => mp.id != id)
},
updateUserMediaProgress(state, data) {
if (!data || !state.user) return
const mediaProgressIndex = state.user.mediaProgress.findIndex(mp => mp.id === data.id)
const mediaProgressIndex = state.user.mediaProgress.findIndex((mp) => mp.id === data.id)
if (mediaProgressIndex >= 0) {
state.user.mediaProgress.splice(mediaProgressIndex, 1, data)
} else {
@@ -174,9 +179,9 @@ export const mutations = {
},
deleteBookmark(state, { libraryItemId, time }) {
if (!state.user?.bookmarks) return
state.user.bookmarks = state.user.bookmarks.filter(bm => {
state.user.bookmarks = state.user.bookmarks.filter((bm) => {
if (bm.libraryItemId === libraryItemId && bm.time === time) return false
return true
})
}
}
}
+7
View File
@@ -6,6 +6,7 @@
"ButtonCancel": "Annuller",
"ButtonCancelTimer": "Stop timer",
"ButtonClearFilter": "Ryd filter",
"ButtonClearLogs": "Rens Logfiler",
"ButtonCloseFeed": "Luk feed",
"ButtonCollections": "Samlinger",
"ButtonConnect": "Forbind",
@@ -26,7 +27,9 @@
"ButtonLatest": "Seneste",
"ButtonLibrary": "Bibliotek",
"ButtonLocalMedia": "Lokalt medie",
"ButtonLogs": "Logfiler",
"ButtonManageLocalFiles": "Administrér Lokale Filer",
"ButtonMaskServerAddress": "Maskér server adresse",
"ButtonNewFolder": "Ny Folder",
"ButtonNextEpisode": "Næste Afsnit",
"ButtonOk": "Ok",
@@ -50,6 +53,7 @@
"ButtonStream": "Stream",
"ButtonSubmit": "Send",
"ButtonSwitchServerUser": "Skift Server/Bruger",
"ButtonUnmaskServerAddress": "Afmaskér server adresse",
"ButtonUserStats": "Bruger statitstik",
"ButtonYes": "Ja",
"HeaderAccount": "Konto",
@@ -238,6 +242,8 @@
"LabelShowAll": "Vis alle",
"LabelSize": "Størrelse",
"LabelSleepTimer": "Søvntimer",
"LabelSleepTimerAlmostDoneChime": "Afspil lyd når snart færdig",
"LabelSleepTimerAlmostDoneChimeHelp": "Afspil lyd når sove timeren har 30 sekunder tilbage",
"LabelStart": "Start",
"LabelStartTime": "Starttid",
"LabelStatsBestDay": "Bedste dag",
@@ -311,6 +317,7 @@
"MessageNoItems": "Ingen elementer",
"MessageNoItemsFound": "Ingen elementer fundet",
"MessageNoListeningSessions": "Ingen lyttesessioner",
"MessageNoLogs": "Ingen logfiler",
"MessageNoMediaFolders": "Ingen Mediemapper",
"MessageNoNetworkConnection": "Ingen Internetforbindelse",
"MessageNoPodcastsFound": "Ingen podcasts fundet",
+2 -2
View File
@@ -32,7 +32,7 @@
"ButtonMaskServerAddress": "Server Adresse verstecken",
"ButtonNewFolder": "Neuer Ordner",
"ButtonNextEpisode": "Nächste Episode",
"ButtonOk": "Einverstanden",
"ButtonOk": "Ok",
"ButtonOpenFeed": "Feed öffnen",
"ButtonOverride": "Überschreiben",
"ButtonPause": "Pausieren",
@@ -220,7 +220,7 @@
"LabelPublishedDate": "Veröffentlicht {0}",
"LabelRSSFeedCustomOwnerEmail": "Benutzerdefinierte Eigentümer-E-Mail",
"LabelRSSFeedCustomOwnerName": "Benutzerdefinierter Name des Eigentümers",
"LabelRSSFeedOpen": "RSS Feed öffnen",
"LabelRSSFeedOpen": "RSS Feed offen",
"LabelRSSFeedPreventIndexing": "Indizierung verhindern",
"LabelRSSFeedSlug": "RSS-Feed-Schlagwort",
"LabelRandomly": "Zufällig",
+1
View File
@@ -146,6 +146,7 @@
"LabelEndOfChapter": "End of Chapter",
"LabelEndTime": "End time",
"LabelEpisode": "Episode",
"LabelExplicit": "Explicit",
"LabelFeedURL": "Feed URL",
"LabelFile": "File",
"LabelFileBirthtime": "File Birthtime",
+6 -6
View File
@@ -6,12 +6,12 @@
"ButtonCancel": "Annuleren",
"ButtonCancelTimer": "Timer annuleren",
"ButtonClearFilter": "Filter verwijderen",
"ButtonClearLogs": "Log bestanden verwijderen",
"ButtonClearLogs": "Logbestanden verwijderen",
"ButtonCloseFeed": "Feed sluiten",
"ButtonCollections": "Collecties",
"ButtonConnect": "Verbinden",
"ButtonConnectToServer": "Verbind met server",
"ButtonCreate": "Creëer",
"ButtonCreate": "Aanmaken",
"ButtonCreateBookmark": "Creëer bladwijzer",
"ButtonCreateNewPlaylist": "Maak nieuwe afspeellijst",
"ButtonDelete": "Verwijder",
@@ -27,9 +27,9 @@
"ButtonLatest": "Meest recent",
"ButtonLibrary": "Bibliotheek",
"ButtonLocalMedia": "Lokale Media",
"ButtonLogs": "Log bestanden",
"ButtonLogs": "Logbestanden",
"ButtonManageLocalFiles": "Beheer Lokale Bestanden",
"ButtonMaskServerAddress": "Server adres maskeren",
"ButtonMaskServerAddress": "Serveradres maskeren",
"ButtonNewFolder": "Nieuwe map",
"ButtonNextEpisode": "Volgende aflevering",
"ButtonOk": "Akkoord",
@@ -39,13 +39,13 @@
"ButtonPlay": "Afspelen",
"ButtonPlayEpisode": "Aflevering afspelen",
"ButtonPlaylists": "Afspeellijsten",
"ButtonRead": "Lees",
"ButtonRead": "Lezen",
"ButtonReadLess": "Minder lezen",
"ButtonReadMore": "Meer lezen",
"ButtonRemove": "Verwijder",
"ButtonRemoveFromServer": "Verwijder van server",
"ButtonSave": "Opslaan",
"ButtonSaveOrder": "Volgorde bewaren",
"ButtonSaveOrder": "Volgorde opslaan",
"ButtonSearch": "Zoeken",
"ButtonSendEbookToDevice": "Verzend Ebook naar Apparaat",
"ButtonSeries": "Series",
+12 -12
View File
@@ -36,7 +36,7 @@
"ButtonOpenFeed": "Відкрити стрічку",
"ButtonOverride": "Перевизначити",
"ButtonPause": "Призупинити",
"ButtonPlay": "Слухати",
"ButtonPlay": "Відтворити",
"ButtonPlayEpisode": "Слухати епізод",
"ButtonPlaylists": "Списки відтворення",
"ButtonRead": "Читати",
@@ -112,7 +112,7 @@
"LabelAutoSleepTimerAutoRewind": "Автоперемотування автотаймеру вимкнення",
"LabelAutoSleepTimerAutoRewindHelp": "Коли сплине автотаймер вимкнення, відтворення знову автоматично перемотає доріжку.",
"LabelAutoSleepTimerHelp": "Таймер вимкнення автоматично ввімкнеться при відтворенні медіа між вказаним початковим та кінцевим часом.",
"LabelBooks": "Книги",
"LabelBooks": "Книг",
"LabelChapterTrack": "Прогрес глави",
"LabelChapters": "Глави",
"LabelClosePlayer": "Закрити програвач",
@@ -133,7 +133,7 @@
"LabelDisableVibrateOnReset": "Вимкнути вібрацію при скиданні",
"LabelDisableVibrateOnResetHelp": "Коли таймер вимкнення буде скинуто, ваш пристрій завібрує. Увімкніть цей параметр, щоб не вібрувати при скиданні таймера.",
"LabelDiscover": "Огляд",
"LabelDownload": "Завантажити",
"LabelDownload": "Скачати",
"LabelDownloadUsingCellular": "Завантажувати через мобільний інтернет",
"LabelDownloaded": "Завантажено",
"LabelDuration": "Тривалість",
@@ -148,8 +148,8 @@
"LabelEpisode": "Епізод",
"LabelFeedURL": "Адреса стрічки",
"LabelFile": "Файл",
"LabelFileBirthtime": "Дата створення",
"LabelFileModified": "Дата змінення",
"LabelFileBirthtime": "Дата створення файлу",
"LabelFileModified": "Дата зміни файлу",
"LabelFilename": "Ім'я файлу",
"LabelFinished": "Завершено",
"LabelFolder": "Тека",
@@ -295,8 +295,8 @@
"MessageDiscardProgress": "Скинути прогрес",
"MessageDownloadCompleteProcessing": "Завантаження завершено. Обробка...",
"MessageDownloading": "Завантажується...",
"MessageDownloadingEpisode": "Завантаження епізоду",
"MessageEpisodesQueuedForDownload": "Епізодів у черзі завантаження: {0}",
"MessageDownloadingEpisode": "Скачування епізоду",
"MessageEpisodesQueuedForDownload": "{0} епізод(ів) у черзі на завантаження",
"MessageFeedURLWillBe": "URL-адреса каналу буде {0}",
"MessageFetching": "Отримання...",
"MessageFollowTheProjectOnGithub": "Слідкуйте за проєктом на GitHub",
@@ -305,7 +305,7 @@
"MessageLoading": "Завантаження...",
"MessageLoadingServerData": "Завантаження даних сервера...",
"MessageLocalFolderDescription": "«Внутрішня пам’ять програми» доступна лише цій програмі. Ця програма підтримує лише мультимедійні файли, завантажені безпосередньо через програму. Спільні папки для зберігання можна використовувати, щоб надати іншим програмам доступ до медіафайлів, завантажених цією програмою.",
"MessageMarkAsFinished": "Позначити завершеним",
"MessageMarkAsFinished": "Позначити як завершене",
"MessageMediaLinkedToADifferentServer": "Медіа пов'язане з Audiobookself-сервером за іншою адресою ({0}). Прогрес буде синхронізовано після підключення до вказаного сервера.",
"MessageMediaLinkedToADifferentUser": "Медіа пов'язане з цим сервером, але було завантажене іншим користувачем. Прогрес буде синхронізовано лише для користувача, що завантажив медіа.",
"MessageMediaLinkedToServer": "Пов'язано з сервером {0}",
@@ -317,12 +317,12 @@
"MessageNoItems": "Елементи відсутні",
"MessageNoItemsFound": "Елементів не знайдено",
"MessageNoListeningSessions": "Сеанси прослуховування відсутні",
"MessageNoLogs": "Без журнал",
"MessageNoLogs": "Без журналу",
"MessageNoMediaFolders": "Теки медіа відсутні",
"MessageNoNetworkConnection": "Немає підключення до мережі",
"MessageNoPodcastsFound": "Подкастів не знайдено",
"MessageNoSeries": "Серії відсутні",
"MessageNoUpdatesWereNecessary": "Оновлень не потрібно",
"MessageNoUpdatesWereNecessary": "Оновлення не потрібні",
"MessageNoUserPlaylists": "У вас немає списків відтворення",
"MessageOldServerConnectionWarning": "Конфігурація підключення до сервера використовує старий ідентифікатор користувача. Видаліть і додайте це підключення до сервера заново.",
"MessageOldServerConnectionWarningHelp": "Ви спочатку налаштували з’єднання з цим сервером перед міграцією бази даних у версії 2.3.0, випущеній у червні 2023 року. Майбутнє оновлення сервера скасує можливість входу за допомогою цього старого з’єднання. Будь ласка, видаліть існуюче підключення до сервера та підключіться знову (використовуючи ту саму адресу сервера та облікові дані). Якщо на цьому пристрої є будь-які завантажені медіафайли, їх потрібно буде завантажити ще раз, щоб синхронізувати із сервером.",
@@ -337,8 +337,8 @@
"MessageSocketConnectedOverUnmeteredCellular": "Сокет під'єднано до безлімітної мобільної мережі",
"MessageSocketConnectedOverUnmeteredWifi": "Сокет під'єднано до безлімітної мережі Wi-Fi",
"MessageSocketNotConnected": "Сокет не під'єднано",
"NoteRSSFeedPodcastAppsHttps": "Попередження: Більшість додатків подкастів вимагатимуть використання протоколу HTTPS від RSS-каналу",
"NoteRSSFeedPodcastAppsPubDate": "Попередження: 1 або більше ваших епізодів не мають дати публікації. Деякі додатки подкастів вимагають це.",
"NoteRSSFeedPodcastAppsHttps": "Попередження: більшість додатків подкастів вимагають використання HTTPS для RSS-каналу",
"NoteRSSFeedPodcastAppsPubDate": "Попередження: один або більше ваших епізодів не мають дати публікації. Деякі додатки подкастів цього вимагають.",
"ToastBookmarkCreateFailed": "Не вдалося створити закладку",
"ToastBookmarkRemoveFailed": "Не вдалося видалити закладку",
"ToastBookmarkUpdateFailed": "Не вдалося оновити закладку",
+3 -3
View File
@@ -246,11 +246,11 @@
"LabelSleepTimerAlmostDoneChimeHelp": "当睡眠定时器还剩30秒时播放铃声",
"LabelStart": "开始",
"LabelStartTime": "开始时间",
"LabelStatsBestDay": "最好的一天",
"LabelStatsBestDay": "单日最高",
"LabelStatsDailyAverage": "每日平均值",
"LabelStatsDays": "",
"LabelStatsDays": "连续收听",
"LabelStatsDaysListened": "收听天数",
"LabelStatsInARow": "在一行",
"LabelStatsInARow": "",
"LabelStatsItemsFinished": "已完成的项目",
"LabelStatsMinutes": "分钟",
"LabelStatsMinutesListening": "收听分钟数",