Compare commits

..

9 Commits

Author SHA1 Message Date
advplyr
99110f587a Localize elapsed duration on sessions tables 2025-07-14 17:17:39 -05:00
advplyr
264ae928a9 Version bump v2.26.0 2025-07-12 11:43:14 -05:00
advplyr
f5248a9f00 Merge pull request #4476 from weblate/weblate-audiobookshelf-abs-web-client
Translations update from Hosted Weblate
2025-07-12 11:41:54 -05:00
FiendFEARing
3473ff594a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-12 18:32:35 +02:00
FiendFEARing
20bb6e13b5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-12 18:32:35 +02:00
FiendFEARing
a05d32b1d7 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/zh_Hans/
2025-07-12 18:32:34 +02:00
Kabika82
c6b3521cb6 Translated using Weblate (Hungarian)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hu/
2025-07-12 18:32:34 +02:00
Kabika82
2444504c6a Translated using Weblate (Hungarian)
Currently translated at 100.0% (1108 of 1108 strings)

Translation: Audiobookshelf/Abs Web Client
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-web-client/hu/
2025-07-12 18:32:33 +02:00
advplyr
d38532c07a Merge pull request #4444 from advplyr/jwt_auth_refactor
Implement new JWT auth
2025-07-12 11:32:22 -05:00
9 changed files with 58 additions and 15 deletions

View File

@@ -1,12 +1,12 @@
{
"name": "audiobookshelf-client",
"version": "2.25.1",
"version": "2.26.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "audiobookshelf-client",
"version": "2.25.1",
"version": "2.26.0",
"license": "ISC",
"dependencies": {
"@nuxtjs/axios": "^5.13.6",

View File

@@ -1,6 +1,6 @@
{
"name": "audiobookshelf-client",
"version": "2.25.1",
"version": "2.26.0",
"buildNumber": 1,
"description": "Self-hosted audiobook and podcast client",
"main": "index.js",

View File

@@ -68,7 +68,7 @@
<p class="text-xs truncate" v-html="getDeviceInfoString(session.deviceInfo)" />
</td>
<td class="text-center w-24 min-w-24 sm:w-32 sm:min-w-32">
<p class="text-xs font-mono">{{ $elapsedPretty(session.timeListening) }}</p>
<p class="text-xs font-mono">{{ $elapsedPrettyLocalized(session.timeListening) }}</p>
</td>
<td class="text-center hover:underline w-24 min-w-24" @click.stop="clickCurrentTime(session)">
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>

View File

@@ -40,7 +40,7 @@
<p class="text-xs truncate" v-html="getDeviceInfoString(session.deviceInfo)" />
</td>
<td class="text-center">
<p class="text-xs font-mono">{{ $elapsedPretty(session.timeListening) }}</p>
<p class="text-xs font-mono">{{ $elapsedPrettyLocalized(session.timeListening) }}</p>
</td>
<td class="text-center hover:underline" @click.stop="clickCurrentTime(session)">
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>

View File

@@ -37,6 +37,48 @@ Vue.prototype.$elapsedPretty = (seconds, useFullNames = false, useMilliseconds =
return `${hours} ${useFullNames ? `hour${hours === 1 ? '' : 's'}` : 'hr'} ${minutes} ${useFullNames ? `minute${minutes === 1 ? '' : 's'}` : 'min'}`
}
Vue.prototype.$elapsedPrettyLocalized = (seconds, useFullNames = false, useMilliseconds = false) => {
if (isNaN(seconds) || seconds === null) return ''
try {
const df = new Intl.DurationFormat(Vue.prototype.$languageCodes.current, {
style: useFullNames ? 'long' : 'short'
})
const duration = {}
if (seconds < 60) {
if (useMilliseconds && seconds < 1) {
duration.milliseconds = Math.floor(seconds * 1000)
} else {
duration.seconds = Math.floor(seconds)
}
} else if (seconds < 3600) {
// 1 hour
duration.minutes = Math.floor(seconds / 60)
} else if (seconds < 86400) {
// 1 day
duration.hours = Math.floor(seconds / 3600)
const minutes = Math.floor((seconds % 3600) / 60)
if (minutes > 0) {
duration.minutes = minutes
}
} else {
duration.days = Math.floor(seconds / 86400)
const hours = Math.floor((seconds % 86400) / 3600)
if (hours > 0) {
duration.hours = hours
}
}
return df.format(duration)
} catch (error) {
// Handle not supported
console.warn('Intl.DurationFormat not supported, not localizing duration')
return Vue.prototype.$elapsedPretty(seconds, useFullNames, useMilliseconds)
}
}
Vue.prototype.$secondsToTimestamp = (seconds, includeMs = false, alwaysIncludeHours = false) => {
if (!seconds) {
return alwaysIncludeHours ? '00:00:00' : '0:00'

View File

@@ -278,7 +278,7 @@
"LabelCollapseSeries": "Sorozat összecsukása",
"LabelCollapseSubSeries": "Alszéria összecsukása",
"LabelCollection": "Gyűjtemény",
"LabelCollections": "Gyűjtemény",
"LabelCollections": "Gyűjtemények",
"LabelComplete": "Kész",
"LabelConfirmPassword": "Jelszó megerősítése",
"LabelContinueListening": "Hallgatás folytatása",
@@ -757,6 +757,7 @@
"MessageConfirmRemoveAuthor": "Biztosan eltávolítja a(z) \"{0}\" szerzőt?",
"MessageConfirmRemoveCollection": "Biztosan eltávolítja a(z) \"{0}\" gyűjteményt?",
"MessageConfirmRemoveEpisode": "Biztosan eltávolítja a(z) \"{0}\" epizódot?",
"MessageConfirmRemoveEpisodeNote": "Megjegyzés: Ez nem törli a hangfájlt, kivéve, ha a \"Hangfájl végleges törlése\" be van kapcsolva",
"MessageConfirmRemoveEpisodes": "Biztosan eltávolítja a(z) {0} epizódot?",
"MessageConfirmRemoveListeningSessions": "Biztosan eltávolítja a(z) {0} hallgatási munkamenetet?",
"MessageConfirmRemoveMetadataFiles": "Biztos, hogy az összes metaadatot el akarja távolítani {0} fájl van könyvtár mappáiban?",

View File

@@ -11,7 +11,7 @@
"ButtonAuthors": "作者",
"ButtonBack": "返回",
"ButtonBatchEditPopulateFromExisting": "用现有内容填充",
"ButtonBatchEditPopulateMapDetails": "填充地图详细信息",
"ButtonBatchEditPopulateMapDetails": "填入此项详情",
"ButtonBrowseForFolder": "浏览文件夹",
"ButtonCancel": "取消",
"ButtonCancelEncode": "取消编码",
@@ -73,7 +73,7 @@
"ButtonQuickMatch": "快速匹配",
"ButtonReScan": "重新扫描",
"ButtonRead": "读取",
"ButtonReadLess": "阅读较少",
"ButtonReadLess": "收起",
"ButtonReadMore": "阅读更多",
"ButtonRefresh": "刷新",
"ButtonRemove": "移除",
@@ -714,7 +714,7 @@
"MessageBackupsLocationNoEditNote": "注意: 备份位置是通过环境变量设置的, 不能在此处更改.",
"MessageBackupsLocationPathEmpty": "备份位置路径不能为空",
"MessageBatchEditPopulateMapDetailsAllHelp": "使用所有项目的数据填充已启用的字段. 具有多个值的字段将被合并",
"MessageBatchEditPopulateMapDetailsItemHelp": "使用此项目的数据填充已启用的地图详细信息字段",
"MessageBatchEditPopulateMapDetailsItemHelp": "提取此项目的信息,填入上方所有勾选的编辑框中",
"MessageBatchQuickMatchDescription": "快速匹配将尝试为所选项目添加缺少的封面和元数据. 启用以下选项以允许快速匹配覆盖现有封面和或元数据.",
"MessageBookshelfNoCollections": "你尚未进行任何收藏",
"MessageBookshelfNoCollectionsHelp": "收藏是公开的. 所有有权访问图书馆的用户都可以看到它们.",
@@ -757,7 +757,7 @@
"MessageConfirmRemoveAuthor": "你确定要删除作者 \"{0}\"?",
"MessageConfirmRemoveCollection": "你确定要移除收藏 \"{0}\"?",
"MessageConfirmRemoveEpisode": "你确定要移除剧集 \"{0}\"?",
"MessageConfirmRemoveEpisodeNote": "注意: 除非切换 \"硬删除文件\", 否则不会删除音频文件",
"MessageConfirmRemoveEpisodeNote": "注意:此操作不会删除音频文件,除非勾选“完全删除文件”选项",
"MessageConfirmRemoveEpisodes": "你确定要移除 {0} 剧集?",
"MessageConfirmRemoveListeningSessions": "你确定要移除 {0} 收听会话吗?",
"MessageConfirmRemoveMetadataFiles": "你确实要删除库项目文件夹中的所有 metadata.{0} 文件吗?",
@@ -918,9 +918,9 @@
"NoteUploaderUnsupportedFiles": "不支持的文件将被忽略. 选择或删除文件夹时, 将忽略不在项目文件夹中的其他文件.",
"NotificationOnBackupCompletedDescription": "备份完成时触发",
"NotificationOnBackupFailedDescription": "备份失败时触发",
"NotificationOnEpisodeDownloadedDescription": "当播客节目自动下载时触发",
"NotificationOnEpisodeDownloadedDescription": "当播客节目自动下载完成时触发",
"NotificationOnRSSFeedDisabledDescription": "由于尝试失败次数过多而导致剧集自动下载被禁用时触发",
"NotificationOnRSSFeedFailedDescription": "当 RSS 源请求自动下载剧集失败时触发",
"NotificationOnRSSFeedFailedDescription": "当用于自动下载剧集的 RSS 源请求失败时触发",
"NotificationOnTestDescription": "测试通知系统的事件",
"PlaceholderNewCollection": "输入收藏夹名称",
"PlaceholderNewFolderPath": "输入文件夹路径",

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "audiobookshelf",
"version": "2.25.1",
"version": "2.26.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "audiobookshelf",
"version": "2.25.1",
"version": "2.26.0",
"license": "GPL-3.0",
"dependencies": {
"axios": "^0.27.2",

View File

@@ -1,6 +1,6 @@
{
"name": "audiobookshelf",
"version": "2.25.1",
"version": "2.26.0",
"buildNumber": 1,
"description": "Self-hosted audiobook and podcast server",
"main": "index.js",