diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 186dbcd12c..9f8563f6a5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,6 +1,2 @@ -.ci @dkanada @EraYaN +* @jellyfin/web .github @jellyfin/core -fedora @joshuaboniface -debian @joshuaboniface -.copr @joshuaboniface -deployment @joshuaboniface diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml index a198be0290..84e5e1e755 100644 --- a/.github/workflows/commands.yml +++ b/.github/workflows/commands.yml @@ -26,3 +26,11 @@ jobs: uses: cirrus-actions/rebase@b87d48154a87a85666003575337e27b8cd65f691 # 1.8 env: GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }} + - name: Comment on failure + if: failure() + uses: peter-evans/create-or-update-comment@3383acd359705b10cb1eeef05c0e88c056ea4666 # v3.0.0 + with: + token: ${{ secrets.JF_BOT_TOKEN }} + issue-number: ${{ github.event.issue.number }} + body: | + I'm sorry @${{ github.event.comment.user.login }}, I'm afraid I can't do that. diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js index 7a67d9ffb3..4ae8bebc24 100644 --- a/src/components/remotecontrol/remotecontrol.js +++ b/src/components/remotecontrol/remotecontrol.js @@ -325,10 +325,11 @@ export default function () { if (layoutManager.mobile) { const playingVideo = playbackManager.isPlayingVideo() && item !== null; const playingAudio = !playbackManager.isPlayingVideo() && item !== null; - buttonVisible(context.querySelector('.btnRepeat'), playingAudio); - buttonVisible(context.querySelector('.btnShuffleQueue'), playingAudio); - buttonVisible(context.querySelector('.btnRewind'), playingVideo); - buttonVisible(context.querySelector('.btnFastForward'), playingVideo); + const playingAudioBook = playingAudio && item.Type == 'AudioBook'; + buttonVisible(context.querySelector('.btnRepeat'), playingAudio && !playingAudioBook); + buttonVisible(context.querySelector('.btnShuffleQueue'), playingAudio && !playingAudioBook); + buttonVisible(context.querySelector('.btnRewind'), playingVideo || playingAudioBook); + buttonVisible(context.querySelector('.btnFastForward'), playingVideo || playingAudioBook); buttonVisible(context.querySelector('.nowPlayingSecondaryButtons .btnShuffleQueue'), playingVideo); buttonVisible(context.querySelector('.nowPlayingSecondaryButtons .btnRepeat'), playingVideo); } else { diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index 5c59483291..943b5f74a2 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -113,6 +113,11 @@ function getProgramScheduleHtml(items, action = 'none') { }); } +function getSelectedMediaSource(page, mediaSources) { + const mediaSourceId = page.querySelector('.selectSource').value; + return mediaSources.filter(m => m.Id === mediaSourceId)[0]; +} + function renderSeriesTimerSchedule(page, apiClient, seriesTimerId) { apiClient.getLiveTvTimers({ UserId: apiClient.getCurrentUserId(), @@ -206,10 +211,7 @@ function renderTrackSelections(page, instance, item, forceReload) { } function renderVideoSelections(page, mediaSources) { - const mediaSourceId = page.querySelector('.selectSource').value; - const mediaSource = mediaSources.filter(function (m) { - return m.Id === mediaSourceId; - })[0]; + const mediaSource = getSelectedMediaSource(page, mediaSources); const tracks = mediaSource.MediaStreams.filter(function (m) { return m.Type === 'Video'; @@ -243,10 +245,8 @@ function renderVideoSelections(page, mediaSources) { } function renderAudioSelections(page, mediaSources) { - const mediaSourceId = page.querySelector('.selectSource').value; - const mediaSource = mediaSources.filter(function (m) { - return m.Id === mediaSourceId; - })[0]; + const mediaSource = getSelectedMediaSource(page, mediaSources); + const tracks = mediaSource.MediaStreams.filter(function (m) { return m.Type === 'Audio'; }); @@ -273,10 +273,8 @@ function renderAudioSelections(page, mediaSources) { } function renderSubtitleSelections(page, mediaSources) { - const mediaSourceId = page.querySelector('.selectSource').value; - const mediaSource = mediaSources.filter(function (m) { - return m.Id === mediaSourceId; - })[0]; + const mediaSource = getSelectedMediaSource(page, mediaSources); + const tracks = mediaSource.MediaStreams.filter(function (m) { return m.Type === 'Subtitle'; }); @@ -2029,6 +2027,7 @@ export default function (view, params) { renderVideoSelections(view, self._currentPlaybackMediaSources); renderAudioSelections(view, self._currentPlaybackMediaSources); renderSubtitleSelections(view, self._currentPlaybackMediaSources); + updateMiscInfo(); }); view.addEventListener('viewshow', function (e) { const page = this; @@ -2063,5 +2062,14 @@ export default function (view, params) { }); } + function updateMiscInfo() { + const selectedMediaSource = getSelectedMediaSource(view, self._currentPlaybackMediaSources); + renderMiscInfo(view, { + // patch currentItem (primary item) with details from the selected MediaSource: + ...currentItem, + ...selectedMediaSource + }); + } + init(); } diff --git a/src/routes/appRoutes/asyncRoutes/index.ts b/src/routes/appRoutes/asyncRoutes/index.ts new file mode 100644 index 0000000000..e5abc85650 --- /dev/null +++ b/src/routes/appRoutes/asyncRoutes/index.ts @@ -0,0 +1 @@ +export * from './user'; diff --git a/src/routes/appRoutes/index.tsx b/src/routes/appRoutes/index.tsx index 07736d6fc9..0136dc5531 100644 --- a/src/routes/appRoutes/index.tsx +++ b/src/routes/appRoutes/index.tsx @@ -5,10 +5,8 @@ import ConnectionRequired from '../../components/ConnectionRequired'; import ServerContentPage from '../../components/ServerContentPage'; import { toAsyncPageRoute } from '../AsyncRoute'; import { toViewManagerPageRoute } from '../LegacyRoute'; -import { ASYNC_USER_ROUTES } from './asyncRoutes/user'; -import { LEGACY_ADMIN_ROUTES } from './legacyRoutes/admin'; -import { LEGACY_PUBLIC_ROUTES } from './legacyRoutes/public'; -import { LEGACY_USER_ROUTES } from './legacyRoutes/user'; +import { ASYNC_USER_ROUTES } from './asyncRoutes'; +import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes'; export const AppRoutes = () => ( diff --git a/src/routes/appRoutes/legacyRoutes/index.ts b/src/routes/appRoutes/legacyRoutes/index.ts new file mode 100644 index 0000000000..2931c568e8 --- /dev/null +++ b/src/routes/appRoutes/legacyRoutes/index.ts @@ -0,0 +1,3 @@ +export * from './admin'; +export * from './public'; +export * from './user'; diff --git a/src/routes/experimentalAppRoutes/asyncRoutes/index.ts b/src/routes/experimentalAppRoutes/asyncRoutes/index.ts new file mode 100644 index 0000000000..9dd4fb3c99 --- /dev/null +++ b/src/routes/experimentalAppRoutes/asyncRoutes/index.ts @@ -0,0 +1,2 @@ +export * from './admin'; +export * from './user'; diff --git a/src/routes/experimentalAppRoutes/index.tsx b/src/routes/experimentalAppRoutes/index.tsx index 47b9ec7e54..bd4cf8a19f 100644 --- a/src/routes/experimentalAppRoutes/index.tsx +++ b/src/routes/experimentalAppRoutes/index.tsx @@ -5,11 +5,8 @@ import ConnectionRequired from '../../components/ConnectionRequired'; import ServerContentPage from '../../components/ServerContentPage'; import { toAsyncPageRoute } from '../AsyncRoute'; import { toViewManagerPageRoute } from '../LegacyRoute'; -import { ASYNC_ADMIN_ROUTES } from './asyncRoutes/admin'; -import { ASYNC_USER_ROUTES } from './asyncRoutes/user'; -import { LEGACY_ADMIN_ROUTES } from './legacyRoutes/admin'; -import { LEGACY_PUBLIC_ROUTES } from './legacyRoutes/public'; -import { LEGACY_USER_ROUTES } from './legacyRoutes/user'; +import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from './asyncRoutes'; +import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes'; export const ExperimentalAppRoutes = () => ( diff --git a/src/routes/experimentalAppRoutes/legacyRoutes/index.ts b/src/routes/experimentalAppRoutes/legacyRoutes/index.ts new file mode 100644 index 0000000000..2931c568e8 --- /dev/null +++ b/src/routes/experimentalAppRoutes/legacyRoutes/index.ts @@ -0,0 +1,3 @@ +export * from './admin'; +export * from './public'; +export * from './user'; diff --git a/src/scripts/libraryMenu.js b/src/scripts/libraryMenu.js index 77b38ab46a..6f02280de8 100644 --- a/src/scripts/libraryMenu.js +++ b/src/scripts/libraryMenu.js @@ -19,6 +19,7 @@ import ServerConnections from '../components/ServerConnections'; import { PluginType } from '../types/plugin.ts'; import Events from '../utils/events.ts'; import { getParameterByName } from '../utils/url.ts'; +import datetime from '../scripts/datetime'; import '../elements/emby-button/paper-icon-button-light'; @@ -44,6 +45,7 @@ import '../styles/flexstyles.scss'; html += ''; html += ''; html += ''; + html += '
'; html += ''; html += ''; html += '
'; @@ -61,11 +63,13 @@ import '../styles/flexstyles.scss'; headerAudioPlayerButton = skinHeader.querySelector('.headerAudioPlayerButton'); headerSearchButton = skinHeader.querySelector('.headerSearchButton'); headerSyncButton = skinHeader.querySelector('.headerSyncButton'); + currentTimeText = skinHeader.querySelector('.currentTimeText'); retranslateUi(); lazyLoadViewMenuBarImages(); bindMenuEvents(); updateCastIcon(); + updateClock(); } function getCurrentApiClient() { @@ -189,6 +193,17 @@ import '../styles/flexstyles.scss'; } } + function updateClock() { + if (layoutManager.tv) { + currentTimeText.classList.remove('hide'); + setInterval(function() { + currentTimeText.innerText = datetime.getDisplayTime(new Date()); + }, 1000); + } else { + currentTimeText.classList.add('hide'); + } + } + function showSearch() { inputManager.handleCommand('search'); } @@ -940,6 +955,7 @@ import '../styles/flexstyles.scss'; let headerSearchButton; let headerAudioPlayerButton; let headerSyncButton; + let currentTimeText; const enableLibraryNavDrawer = layoutManager.desktop; const enableLibraryNavDrawerHome = !layoutManager.tv; const skinHeader = document.querySelector('.skinHeader'); diff --git a/src/strings/es.json b/src/strings/es.json index 017300f310..f42116c959 100644 --- a/src/strings/es.json +++ b/src/strings/es.json @@ -736,7 +736,7 @@ "MessageUnsetContentHelp": "El contenido se mostrará como carpetas planas. Para tener mejores resultados utiliza el gestor de metadatos para establecer los tipos de contenidos de las sub-carpetas.", "MessageYouHaveVersionInstalled": "Actualmente tienes la versión {0} instalada.", "Metadata": "Metadatos", - "MetadataManager": "Administrador de metadatos", + "MetadataManager": "Administrador de Metadatos", "MetadataSettingChangeHelp": "Cambiar las Configuraciones de Metadatos, afectará al nuevo contenido que se añada en el futuro. Para actualizar el contenido existente, abre la pantalla de detalles y haz clic en el botón \"Actualizar\". También se pueden actualizar todos los metadatos a la vez utilizando el \"Administrador de Metadatos\".", "MinutesAfter": "minutos después", "MinutesBefore": "minutos antes", @@ -1327,7 +1327,7 @@ "EnableDetailsBanner": "Barra de Detalles", "ShowMore": "Ver más", "ShowLess": "Ver menos", - "ButtonSyncPlay": "SyncPlay", + "ButtonSyncPlay": "Reproducción sincronizada", "ButtonCast": "Transmitir al Dispositivo", "MessageNoGenresAvailable": "Permitir a algunos proveedores de metadatos extraer géneros de Internet.", "EnableDecodingColorDepth10Vp9": "Habilitar la decodificación por hardware de 10 bits para VP9", @@ -1357,7 +1357,7 @@ "SubtitleVerticalPositionHelp": "Número de línea donde aparece el texto. Los números positivos indican de arriba hacia abajo. Los números negativos indican de abajo hacia arriba.", "Preview": "Vista previa", "Video": "Video", - "Subtitle": "Subtitulo", + "Subtitle": "Subtítulo", "SpecialFeatures": "Características Especiales", "SelectServer": "Seleccionar Servidor", "Restart": "Reiniciar", @@ -1698,7 +1698,7 @@ "LabelDummyChapterDurationHelp": "Intervalo de extracción de imágenes de los capítulos en segundos.", "HeaderDummyChapter": "Imágenes de capítulos", "LabelDummyChapterCount": "Límite", - "Featurette": "Reportaje", + "Featurette": "Reportaje extra", "SubtitleBlack": "Negro", "SubtitleGreen": "Verde", "SecondarySubtitles": "Subtítulos secundarios", @@ -1715,7 +1715,7 @@ "LabelChapterImageResolution": "Resolución", "PreferEmbeddedExtrasTitlesOverFileNamesHelp": "Los extras a menudo tienen el mismo nombre agregado que el origen, marque esto para usar títulos incrustados para ellos de todos modos.", "SubtitleBlue": "Azul", - "SubtitleCyan": "Cyan", + "SubtitleCyan": "Cian", "SubtitleGray": "Gris", "SubtitleLightGray": "Gris claro", "SubtitleRed": "Rojo", diff --git a/src/strings/ru.json b/src/strings/ru.json index 95831161c4..eb37854aae 100644 --- a/src/strings/ru.json +++ b/src/strings/ru.json @@ -1694,5 +1694,13 @@ "HeaderDummyChapter": "Изображения глав", "LabelDummyChapterCount": "Лимит", "HeaderRecordingMetadataSaving": "Метаданные записей", - "LabelDummyChapterCountHelp": "Максимальное количество изображений глав, которые будут извлечены для каждого медиафайла." + "LabelDummyChapterCountHelp": "Максимальное количество изображений глав, которые будут извлечены для каждого медиафайла.", + "PreferEmbeddedExtrasTitlesOverFileNames": "Предпочитать встроенные заголовки именам файлов для дополнительных целей", + "LabelEnableAudioVbr": "Включить кодировку звука VBR", + "LabelEnableAudioVbrHelp": "Переменный битрейт обеспечивает лучшее соотношение качества к среднему, но в некоторых редких случаях может вызвать проблемы с буферизацией и совместимостью.", + "LabelParallelImageEncodingLimit": "Ограничение на параллельное кодирование изображений", + "LabelParallelImageEncodingLimitHelp": "Максимальное количество кодировок изображений, которые разрешено выполнять параллельно. Установив это значение равным 0, вы выберете ограничение, основанное на характеристиках вашей системы.", + "HeaderPerformance": "Производительность", + "LabelDummyChapterDurationHelp": "Интервал извлечения изображения главы в секундах.", + "LabelChapterImageResolutionHelp": "Разрешение извлеченных изображений глав." } diff --git a/src/strings/zh-hk.json b/src/strings/zh-hk.json index e18a8f2b48..433cc84822 100644 --- a/src/strings/zh-hk.json +++ b/src/strings/zh-hk.json @@ -20,7 +20,7 @@ "DeviceAccessHelp": "只適用於能夠被獨立識別的裝置(獨一無二),而且並不能阻擋透過瀏覽器的連接。用戶的新裝置在得到批准前將不能夠連接及使用。", "Edit": "編輯", "EditSubtitles": "編輯字幕", - "Ended": "完結", + "Ended": "已完結", "Friday": "星期五", "HeaderActiveDevices": "生效裝置", "HeaderActiveRecordings": "正在錄影的節目", @@ -305,7 +305,7 @@ "DeleteMedia": "刪除媒體", "DeleteImageConfirmation": "您確定要刪除此圖片嗎?", "DeleteImage": "刪除圖片", - "ErrorDefault": "處理此請求時發生錯誤,請稍後再試。", + "ErrorDefault": "處理此指令時發生錯誤,請稍後再試。", "Default": "預設", "DateAdded": "新增日期", "CopyStreamURLSuccess": "成功複製 URL。", @@ -401,47 +401,47 @@ "ExitFullscreen": "結束全螢幕", "EveryXMinutes": "每 {0} 分鐘", "EveryXHours": "每 {0} 小時", - "EveryNDays": "每 {0} 天", + "EveryNDays": "每 {0} 日", "EveryHour": "每小時", "ErrorStartHourGreaterThanEnd": "結束時間必須在開始時間後。", - "ErrorSavingTvProvider": "儲存電視供應商時發生錯誤,請確認是否可存取並重試。", - "ErrorPleaseSelectLineup": "請選擇節目表,然後重試。若無可用的節目表,請檢查您的使用者名稱、密碼和郵政編碼是否正確。", - "ErrorGettingTvLineups": "下載電視節目表時發生錯誤,請確認你的資訊是否正確並重試。", - "ErrorDeletingItem": "從伺服器刪除項目時發生錯誤,請確認伺服器對該位址有寫入權限並重試。", - "ErrorAddingXmlTvFile": "存取 XMLTV 檔案時發生錯誤,請確認該檔案是否存在後重試。", - "ErrorAddingTunerDevice": "新增調諧器設備時發生錯誤,請確認它是否可被存取後重試。", - "ErrorAddingMediaPathToVirtualFolder": "新增媒體路徑時發生錯誤,請確認路徑是否有效,且 Jellyfin 具該位置的存取權。", - "ErrorAddingListingsToSchedulesDirect": "在將電視節目時間表新增到您的 Schedules Direct 帳號時出現錯誤。每個 Schedules Direct 帳號只允許有限的時間表。在繼續前你可能需要登入 Schedules Direct 網站並刪除帳號中的其他清單。", + "ErrorSavingTvProvider": "儲存電視供應商/電視台時發生錯誤,請檢查是否可以存取後重試。", + "ErrorPleaseSelectLineup": "請選擇節目表後再重試。如果沒有可用的節目表,請檢查您的使用者名稱、密碼和郵政編碼是否正確。", + "ErrorGettingTvLineups": "下載電視節目表時發生錯誤,請檢查你的資料是否正確後再重試。", + "ErrorDeletingItem": "刪除項目時發生錯誤,請確保伺服器具有該資料夾的寫入權限後重試。", + "ErrorAddingXmlTvFile": "開啟 XMLTV 檔案時出錯錯誤,請檢查該檔案是否存在後重試。", + "ErrorAddingTunerDevice": "新增調諧器設備時出現錯誤,請檢查設備是否運作正常後重試。", + "ErrorAddingMediaPathToVirtualFolder": "新增媒體路徑時出現錯誤,請檢查路徑是否有效及 Jellyfin 是否具有存取該位置的權限。", + "ErrorAddingListingsToSchedulesDirect": "在將電視節目時間表新增到您的 Schedules Direct 帳號時出現錯誤。每個 Schedules Direct 帳號只允許少量時間表,你可能需要登入 Schedules Direct 網站並刪除帳號中的其他清單。", "Episodes": "劇集", "Episode": "劇集", - "EndsAtValue": "於 {0} 結束", - "EncoderPresetHelp": "速度越慢品質愈好,速度越快效率愈高。", - "EnableTonemapping": "啟用色調映射", - "EnableThemeVideosHelp": "瀏覽媒體庫時播放主題影片將作為背景。", - "EnableThemeSongsHelp": "瀏覽媒體庫時播放主題曲作為背景音樂播放。", - "EnableStreamLoopingHelp": "如果直播僅包含了幾秒鐘的數據並且需要被不斷的請求,請啟用此項。如果在沒有相關問題的情況下啟動此項,可能會導致一些問題。", - "EnableStreamLooping": "自動循環播放直播", - "EnableQuickConnect": "在此伺服器上啟用 Quick Connect", - "EnablePhotosHelp": "圖片將被偵測並和其他媒體檔案一起顯示。", + "EndsAtValue": "在 {0} 結束", + "EncoderPresetHelp": "速度越慢品質越好;速度越快效率越高。", + "EnableTonemapping": "啟用色調映射(Tone Mapping)", + "EnableThemeVideosHelp": "瀏覽媒體庫時,在背景播放主題影片。", + "EnableThemeSongsHelp": "瀏覽媒體庫時,在背景播放主題曲。", + "EnableStreamLoopingHelp": "如果直播影片只有幾秒鐘的長度而且不斷有人播放的話,您或可以考慮啟用此功能。在沒有相關的需求下啟用此功能,可能會導致其他問題。", + "EnableStreamLooping": "循環播放直播", + "EnableQuickConnect": "啟用 Quick Connect", + "EnablePhotosHelp": "圖片將會與其他媒體檔案一起顯示。", "EnablePhotos": "顯示圖片", - "EnableNextVideoInfoOverlayHelp": "在影片結束時,顯示當前播放清單中下一個影片的資訊。", - "EnableNextVideoInfoOverlay": "在播放時顯示下一個影片的資訊", - "EnableHardwareEncoding": "啟用硬體編碼", - "EnableFasterAnimationsHelp": "使用快速的動畫與過渡效果。", - "EnableFasterAnimations": "快速動畫", + "EnableNextVideoInfoOverlayHelp": "在影片結束時,顯示下一條在目前的播放清單中的影片的資訊。", + "EnableNextVideoInfoOverlay": "顯示下一條影片的資訊", + "EnableHardwareEncoding": "啟用硬件編碼", + "EnableFasterAnimationsHelp": "加快動畫及過渡效果的顯示速度。", + "EnableFasterAnimations": "更快的動畫效果", "EnableExternalVideoPlayersHelp": "當你開始播放影片時,將會顯示外部播放器選單。", "EnableExternalVideoPlayers": "外部影片播放器", - "EnableDisplayMirroring": "鏡像顯示器", - "EnableDetailsBannerHelp": "在項目詳細訊息頁面的頂部顯示橫幅。", + "EnableDisplayMirroring": "螢幕鏡射", + "EnableDetailsBannerHelp": "在項目詳細資訊頁面的頂部顯示橫額。", "EnableDetailsBanner": "詳情橫幅", - "EnableDecodingColorDepth10Vp9": "啟用 VP9 10-bit 硬體解碼", - "EnableDecodingColorDepth10Hevc": "啟用 HEVC 10-bit 硬體解碼", + "EnableDecodingColorDepth10Vp9": "啟用 VP9 10-bit 硬件解碼", + "EnableDecodingColorDepth10Hevc": "啟用 HEVC 10-bit 硬件解碼", "EnableColorCodedBackgrounds": "色彩背景", - "EnableBlurHashHelp": "尚未讀取完畢的圖片會先顯示模糊的版本。", - "EnableBlurHash": "啟用模糊的佔位圖片", - "EnableBackdropsHelp": "瀏覽媒體庫時以背景圖作為頁面的背景。", - "EditMetadata": "編輯metadata", - "EasyPasswordHelp": "你的簡易 PIN 碼將會用於在支援的 Jellyfin 程式上進行離線存取,同時也可用於區域網路的登入。", + "EnableBlurHashHelp": "在圖片被完全載入前,先以模糊化的版本顯示。", + "EnableBlurHash": "啟用圖片模糊載入(BlurHash)", + "EnableBackdropsHelp": "瀏覽媒體庫時以「背景圖」作為頁面的背景。", + "EditMetadata": "編輯元數據", + "EasyPasswordHelp": "您可以在支援簡易 PIN 碼的程式上使用 PIN 碼作離線認證,亦可以用於區域網路內的登入認證。", "DropShadow": "陰影", "DrmChannelsNotImported": "受 DMR 保護的頻道將不會被導入。", "Down": "下", @@ -930,7 +930,7 @@ "LabelSyncPlayAccess": "SyncPlay 存取控制", "LabelSupportedMediaTypes": "支援的媒體類型:", "LabelSubtitleVerticalPosition": "垂直位置:", - "LabelSubtitlePlaybackMode": "字幕載入:", + "LabelSubtitlePlaybackMode": "字幕播放模式", "LabelSubtitleFormatHelp": "如:SRT", "LabelSubtitleDownloaders": "字幕下載器:", "LabelStreamType": "串流類型:", @@ -1043,7 +1043,7 @@ "FastForward": "快轉", "Extras": "額外", "ExtraLarge": "特大", - "ExtractChapterImagesHelp": "擷取章節圖片將允許 Jellyfin 顯示圖片形式的章節選單,過程可能會非常緩慢、佔用大量 CPU 資源,並且可能需要幾 GB 的硬碟空間。擷取會在影片被偵測到時啟動,同時也可作為一個夜間計劃任務運行,這個任務可以在「計劃任務」選項中進行設定,不建議在尖峰使用時間進行這個任務。", + "ExtractChapterImagesHelp": "擷取章節圖片將允許 Jellyfin 顯示圖片形式顯示章節選單。但擷取工作可能會非常緩慢、佔用大量系統資源,並且可能需要幾 GB 的儲存空間。擷取工作會在影片被偵測到時或每晚自動執行。您以在「工作排程器」中設定。不建議在使用高峰時間執行這個工作。", "MusicVideos": "MV", "AgeValue": "({0}歲)", "MediaInfoLanguage": "語言", @@ -1061,9 +1061,9 @@ "MarkPlayed": "標示為已觀看", "ManageRecording": "管理錄影", "LabelAccessDay": "星期:", - "HeaderSyncPlayPlaybackSettings": "重播", + "HeaderSyncPlayPlaybackSettings": "播放", "HeaderSyncPlaySettings": "同步播放設定", - "ErrorPlayerNotFound": "找不到相關人員。", + "ErrorPlayerNotFound": "找不到這個媒體所需的播放器。", "Engineer": "聲音工程師", "Arranger": "編曲", "LabelAutomaticallyAddToCollectionHelp": "當至少有 2 部電影具有相同的名稱時,它們將自動加入到合輯中。", @@ -1087,8 +1087,8 @@ "LabelMaxDaysForNextUp": "在「按下來」中顯示日數上限:", "ItemDetails": "項目詳細資料", "GoogleCastUnsupported": "不支援 Google Cast", - "EnableRewatchingNextUp": "允許重新觀看「接下來」", - "EnableRewatchingNextUpHelp": "允許在「接下來」中顯示已觀看的集數。", + "EnableRewatchingNextUp": "允許「接下來」顯示重看的影片", + "EnableRewatchingNextUpHelp": "允許在「接下來」的分區中顯示已在之前看過的集數。", "Conductor": "指揮", "Casual": "隨意", "LabelSyncPlaySettingsDescription": "更改 SyncPlay 設定", @@ -1140,5 +1140,8 @@ "LabelChapterImageResolutionHelp": "章節圖片擷取的解像度。", "HeaderRecordingMetadataSaving": "錄影節目元數據", "UseEpisodeImagesInNextUp": "在「接下來」及「繼續觀看」區中,以相關集數的圖片作顯示", - "UseEpisodeImagesInNextUpHelp": "在「接下來」及「繼續觀看」區中,以相關集數的圖片取代該劇集的縮圖作顯示。" + "UseEpisodeImagesInNextUpHelp": "在「接下來」及「繼續觀看」區中,以相關集數的圖片取代該劇集的縮圖作顯示。", + "TabScheduledTasks": "工作排程器", + "LabelPlaybackInfo": "播放資訊", + "EnableCardLayout": "顯示 visual CardBox" } diff --git a/src/styles/librarybrowser.scss b/src/styles/librarybrowser.scss index 66e9aad7d8..75a6cc53cf 100644 --- a/src/styles/librarybrowser.scss +++ b/src/styles/librarybrowser.scss @@ -1515,3 +1515,8 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards { line-clamp: 6; } } + +.currentTimeText { + padding-left: 0.8em; + padding-right: 0.8em; +}