Merge pull request #339 from rafaelvieiras/ft/i18next
Internationalization System
This commit is contained in:
commit
b9d6fe9ff1
@ -1,6 +1,6 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
Dockerfile
|
||||
*Dockerfile*
|
||||
.dockerignore
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM node:12.18-alpine3.12
|
||||
FROM node:14-alpine3.14
|
||||
WORKDIR /home/node/app
|
||||
COPY package*.json ./
|
||||
RUN npm install && npm install -g browserify nexe@3.3.7
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM node:12.18-alpine3.12
|
||||
FROM node:14-alpine3.14
|
||||
WORKDIR /home/node/app
|
||||
COPY package*.json ./
|
||||
RUN npm install && npm install -g browserify nexe@3.3.7
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM node:12.18-alpine3.12
|
||||
FROM node:14-alpine3.14
|
||||
WORKDIR /home/node/app
|
||||
COPY package*.json ./
|
||||
RUN npm install && npm install -g browserify nexe@3.3.7
|
||||
|
||||
28
index.js
28
index.js
@ -5,6 +5,9 @@ const path = require('path')
|
||||
const express = require('express')
|
||||
const bodyParser = require('body-parser')
|
||||
const fileUpload = require('express-fileupload');
|
||||
const i18next = require('i18next');
|
||||
const i18nextMiddleware = require('i18next-http-middleware/cjs');
|
||||
const i18nextBackend = require('i18next-fs-backend/cjs');
|
||||
|
||||
const api = require('./src/api')
|
||||
const dbMigration = require('./src/database-migration');
|
||||
@ -92,9 +95,24 @@ eventService = new EventService();
|
||||
initDB(db, channelDB)
|
||||
|
||||
|
||||
const guideService = new TVGuideService(xmltv, db, cacheImageService);
|
||||
i18next
|
||||
.use(i18nextBackend)
|
||||
.use(i18nextMiddleware.LanguageDetector)
|
||||
.init({
|
||||
// debug: true,
|
||||
initImmediate: false,
|
||||
backend: {
|
||||
loadPath: path.join(__dirname, '/locales/server/{{lng}}.json'),
|
||||
addPath: path.join(__dirname, '/locales/server/{{lng}}.json')
|
||||
},
|
||||
lng: 'en',
|
||||
fallbackLng: 'en',
|
||||
preload: ['en'],
|
||||
});
|
||||
|
||||
|
||||
const guideService = new TVGuideService(xmltv, db, cacheImageService, null, i18next);
|
||||
|
||||
|
||||
let xmltvInterval = {
|
||||
interval: null,
|
||||
@ -183,6 +201,10 @@ let hdhr = HDHR(db, channelDB)
|
||||
let app = express()
|
||||
eventService.setup(app);
|
||||
|
||||
app.use(
|
||||
i18nextMiddleware.handle(i18next, {})
|
||||
);
|
||||
|
||||
app.use(fileUpload({
|
||||
createParentPath: true
|
||||
}));
|
||||
@ -279,7 +301,7 @@ async function sendEventAfterTime() {
|
||||
eventService.push(
|
||||
"lifecycle",
|
||||
{
|
||||
"message": `Server Started`,
|
||||
"message": i18next.t("event.server_started"),
|
||||
"detail" : {
|
||||
"time": t,
|
||||
},
|
||||
@ -298,7 +320,7 @@ onShutdown("log" , [], async() => {
|
||||
eventService.push(
|
||||
"lifecycle",
|
||||
{
|
||||
"message": `Initiated Server Shutdown`,
|
||||
"message": i18next.t("event.server_shutdown"),
|
||||
"detail" : {
|
||||
"time": t,
|
||||
},
|
||||
|
||||
15
locales/server/en.json
Normal file
15
locales/server/en.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"event":{
|
||||
"server_started": "Server Started",
|
||||
"server_shutdown": "Initiated Server Shutdown"
|
||||
},
|
||||
"api": {
|
||||
"plex_server_not_found": "Plex server not found.",
|
||||
"missing_name": "Missing name"
|
||||
},
|
||||
"tvGuide": {
|
||||
"no_channels": "No channels configured",
|
||||
"no_channels_summary": "Use the dizqueTV web UI to configure channels.",
|
||||
"xmltv_updated": "XMLTV updated at server time {{t}}"
|
||||
}
|
||||
}
|
||||
1657
package-lock.json
generated
1657
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -19,14 +19,20 @@
|
||||
"dependencies": {
|
||||
"angular": "^1.8.0",
|
||||
"angular-router-browserify": "0.0.2",
|
||||
"angular-sanitize": "^1.8.2",
|
||||
"angular-vs-repeat": "2.0.13",
|
||||
"axios": "^0.21.1",
|
||||
"body-parser": "^1.19.0",
|
||||
"diskdb": "0.1.17",
|
||||
"express": "^4.17.1",
|
||||
"express-fileupload": "^1.2.1",
|
||||
"i18next": "^20.3.2",
|
||||
"i18next-fs-backend": "^1.1.1",
|
||||
"i18next-http-backend": "^1.2.6",
|
||||
"i18next-http-middleware": "^3.1.4",
|
||||
"JSONStream": "1.0.5",
|
||||
"merge": "2.1.1",
|
||||
"ng-i18next": "^1.0.7",
|
||||
"node-graceful-shutdown": "1.1.0",
|
||||
"node-ssdp": "^4.0.0",
|
||||
"random-js": "2.1.0",
|
||||
|
||||
@ -62,7 +62,7 @@ function api(db, channelDB, fillerDB, customShowDB, xmltvInterval, guideService
|
||||
name: req.body.name,
|
||||
});
|
||||
if (servers.length != 1) {
|
||||
return res.status(404).send("Plex server not found.");
|
||||
return res.status(404).send(req.t("api.plex_server_not_found"));
|
||||
}
|
||||
let plex = new Plex(servers[0]);
|
||||
let s = await Promise.race( [
|
||||
|
||||
@ -8,7 +8,7 @@ class TVGuideService
|
||||
/****
|
||||
*
|
||||
**/
|
||||
constructor(xmltv, db, cacheImageService, eventService) {
|
||||
constructor(xmltv, db, cacheImageService, eventService, i18next) {
|
||||
this.cached = null;
|
||||
this.lastUpdate = 0;
|
||||
this.updateTime = 0;
|
||||
@ -20,6 +20,7 @@ class TVGuideService
|
||||
this.cacheImageService = cacheImageService;
|
||||
this.eventService = eventService;
|
||||
this._throttle = throttle;
|
||||
this.i18next = i18next;
|
||||
}
|
||||
|
||||
async get() {
|
||||
@ -333,9 +334,9 @@ class TVGuideService
|
||||
program: {
|
||||
duration: 24*60*60*1000,
|
||||
icon: FALLBACK_ICON,
|
||||
showTitle: "No channels configured",
|
||||
showTitle: this.i18next.t("tvGuide.no_channels"),
|
||||
date: formatDateYYYYMMDD(new Date()),
|
||||
summary : "Use the dizqueTV web UI to configure channels."
|
||||
summary : this.i18next.t("tvGuide.no_channels_summary")
|
||||
}
|
||||
} )
|
||||
]
|
||||
@ -376,7 +377,7 @@ class TVGuideService
|
||||
eventService.push(
|
||||
"xmltv",
|
||||
{
|
||||
"message": `XMLTV updated at server time = ${t}`,
|
||||
"message": this.i18next.t("tvGuide.xmltv_updated", {t}),
|
||||
"module" : "xmltv",
|
||||
"detail" : {
|
||||
"time": new Date(),
|
||||
|
||||
27
web/app.js
27
web/app.js
@ -4,8 +4,33 @@ require('./ext/lazyload')(angular)
|
||||
require('./ext/dragdrop')
|
||||
require('./ext/angularjs-scroll-glue')
|
||||
require('angular-vs-repeat');
|
||||
require('angular-sanitize');
|
||||
const i18next = require('i18next');
|
||||
const i18nextHttpBackend = require('i18next-http-backend');
|
||||
window.i18next = i18next;
|
||||
|
||||
var app = angular.module('myApp', ['ngRoute', 'vs-repeat', 'angularLazyImg', 'dndLists', 'luegg.directives'])
|
||||
window.i18next.use(i18nextHttpBackend);
|
||||
|
||||
window.i18next.init({
|
||||
// debug: true,
|
||||
lng: 'en',
|
||||
fallbackLng: 'en',
|
||||
preload: ['en'],
|
||||
ns: [ 'main' ],
|
||||
defaultNS: [ 'main' ],
|
||||
initImmediate: false,
|
||||
backend: {
|
||||
loadPath: '/locales/{{lng}}/{{ns}}.json'
|
||||
},
|
||||
useCookie: false,
|
||||
useLocalStorage: false,
|
||||
}, function (err, t) {
|
||||
console.log('resources loaded');
|
||||
});
|
||||
|
||||
require('ng-i18next');
|
||||
|
||||
var app = angular.module('myApp', ['ngRoute', 'vs-repeat', 'angularLazyImg', 'dndLists', 'luegg.directives', 'jm.i18next'])
|
||||
|
||||
app.service('plex', require('./services/plex'))
|
||||
app.service('dizquetv', require('./services/dizquetv'))
|
||||
|
||||
@ -83,7 +83,6 @@ module.exports = function ($scope, $timeout, dizquetv) {
|
||||
$scope.t1 = (new Date()).getTime();
|
||||
$scope.t1 = ($scope.t1 - $scope.t1 % MINUTE );
|
||||
$scope.t0 = $scope.t1 - $scope.before + $scope.offset;
|
||||
$scope.title = "TV Guide";
|
||||
$scope.times = [];
|
||||
|
||||
$scope.updateJustNow();
|
||||
|
||||
@ -33,7 +33,12 @@
|
||||
</a>
|
||||
</small>
|
||||
</h1>
|
||||
<a href="#!/guide">Guide</a> - <a href="#!/channels">Channels</a> - <a href="#!/library">Library</a> - <a href="#!/player">Player</a> - <a href="#!/settings">Settings</a> - <a href="#!/version">Version</a>
|
||||
<a href="#!/guide">{{'topMenu.guide' | i18next}}</a> -
|
||||
<a href="#!/channels">{{'topMenu.channels' | i18next}}</a> -
|
||||
<a href="#!/library">{{'topMenu.library' | i18next}}</a> -
|
||||
<a href="#!/player">{{'topMenu.player' | i18next}}</a> -
|
||||
<a href="#!/settings">{{'topMenu.settings' | i18next}}</a> -
|
||||
<a href="#!/version">{{'topMenu.version' | i18next}}</a>
|
||||
<span class="pull-right">
|
||||
<span style="margin-right: 15px;">
|
||||
<a href="/api/xmltv.xml">XMLTV <span class="far fa-file-code"></span></a>
|
||||
|
||||
77
web/public/locales/en/main.json
Normal file
77
web/public/locales/en/main.json
Normal file
@ -0,0 +1,77 @@
|
||||
{
|
||||
"topMenu": {
|
||||
"guide": "Guide",
|
||||
"channels": "Channels",
|
||||
"library": "Library",
|
||||
"player": "Player",
|
||||
"settings": "Settings",
|
||||
"version": "Version"
|
||||
},
|
||||
"guide": {
|
||||
"title": "Tv Guide",
|
||||
"attempt_to_play_channel": "Attempt to play channel: {{title}} in local media player"
|
||||
},
|
||||
"settings_server": {
|
||||
"title": "Plex Settings",
|
||||
"servers": "Plex Servers",
|
||||
"sign_server": "Sign In/Add Servers",
|
||||
"add_server": "Add a Plex Server",
|
||||
"minutes_to_sign_plex": "You have 2 minutes to sign into your Plex Account.",
|
||||
"name": "Name",
|
||||
"uri": "URI",
|
||||
"ui_route": "UI Route",
|
||||
"backend_route": "Backend Route",
|
||||
"ok": "ok",
|
||||
"error": "error",
|
||||
"ui_bad": "If a Plex server configuration has problems with the UI route, the channel editor won't be able to access its content.",
|
||||
"backend_bad": "If a Plex server configuration has problems with the backend route, dizqueTV won't be able to play its content.",
|
||||
"plex_transcoder_settings": "Plex Transcoder Settings",
|
||||
"update": "Update",
|
||||
"reset_options": "Reset Options",
|
||||
"debug_logging": "Debug logging",
|
||||
"paths": "Paths",
|
||||
"send_status_plex": "Send play status to Plex",
|
||||
"send_status_plex_note": "Note: This affects the \"on deck\" for your plex account.",
|
||||
"no_plex_path": "If stream changes video codec, audio codec, or audio channels upon episode change, you will experience playback issues unless ffmpeg transcoding and normalization are also enabled.",
|
||||
|
||||
"video_options": "Video Options",
|
||||
"supported_video_formats": "Supported Video Formats",
|
||||
"max_playable_resolution": "Max Playable Resolution",
|
||||
"max_transcode_resolution": "Max Transcode Resolution",
|
||||
"audio_options": "Audio Options",
|
||||
"supported_audio_formats": "Supported Audio Formats",
|
||||
"supported_audio_formats_note": "Comma separated list. Some possible values are 'ac3,aac,mp3'.",
|
||||
"max_audio_channels": "Maximum Audio Channels",
|
||||
"max_audio_channels_note": "Note: 7.1 audio and on some clients, 6.1, is known to cause playback issues.",
|
||||
"audio_boost": "Audio Boost",
|
||||
"audio_boost_note": "Note: Only applies when downmixing to stereo.",
|
||||
"miscellaneous_options": "Miscellaneous Options",
|
||||
"max_direct_stream_bitrate": "Max Direct Stream Bitrate (Kbps)",
|
||||
"max_transcode_bitrate": "Max Transcode Bitrate (Kbps)",
|
||||
"max_transcode_bitrate_note": "Plex will decide to transcode or direct play based on these settings and if Plex transcodes, it will try to match the transcode bitrate.",
|
||||
"direct_stream_media_buffer": "Direct Stream Media Buffer Size",
|
||||
"transcode_media_buffer": "Transcode Media Buffer Size",
|
||||
"stream_protocol": "Stream Protocol",
|
||||
"force_direct_play": "Force Direct Play",
|
||||
"subtitle_options": "Subtitle Options",
|
||||
"subtitle_size": "Subtitle Size",
|
||||
"enable_subtitle": "Enable Subtitles (Requires Transcoding)",
|
||||
"path_replacements": "Path Replacements",
|
||||
"original_plex_path": "Original Plex path to replace:",
|
||||
"replace_plex_path": "Replace Plex path with:"
|
||||
|
||||
},
|
||||
"settings_xmltv": {
|
||||
"title": "XMLTV Settings",
|
||||
"update": "Update",
|
||||
"reset_options": "Reset Options",
|
||||
"output_path": "Output Path",
|
||||
"output_path_note": "You can edit this location in file xmltv-settings.json.",
|
||||
"epg_hours": "EPG Hours",
|
||||
"epg_hours_note": "How many hours of programming to include in the xmltv file.",
|
||||
"refresh_timer": "Refresh Timer (hours)",
|
||||
"refresh_timer_note": "How often should the xmltv file be updated.",
|
||||
"image_cache": "Image Cache",
|
||||
"image_cache_note": "If enabled the pictures used for Movie and TV Show posters will be cached in dizqueTV's .dizqueTV folder and will be delivered by dizqueTV's server instead of requiring calls to Plex. Note that using fixed xmltv location in Plex (as opposed to url) will not work correctly in this case."
|
||||
}
|
||||
}
|
||||
@ -1,28 +1,28 @@
|
||||
<div>
|
||||
<h5>Plex Settings</h5>
|
||||
<h6>Plex Servers
|
||||
<h5>{{'settings_server.title' | i18next}}</h5>
|
||||
<h6>{{'settings_server.servers' | i18next}}
|
||||
<button class="pull-right btn btn-sm btn-success" style="margin-bottom:10px;" ng-disabled="isProcessing" ng-click="addPlexServer()">
|
||||
Sign In/Add Servers
|
||||
{{'settings_server.sign_server' | i18next}}
|
||||
</button>
|
||||
</h6>
|
||||
<div ng-if="isProcessing">
|
||||
<br>
|
||||
<h6>
|
||||
<span class="pull-right text-info">{{ isProcessing ? 'You have 2 minutes to sign into your Plex Account.' : ''}}</span>
|
||||
<span class="pull-right text-info">{{ isProcessing ? 'settings_server.minutes_to_sign_plex' : '' | i18next}}</span>
|
||||
</h6>
|
||||
<br>
|
||||
</div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>uri</th>
|
||||
<th>UI Route</th>
|
||||
<th>Backend Route</th>
|
||||
<th>{{'settings_server.name' | i18next}}</th>
|
||||
<th>{{'settings_server.uri' | i18next}}</th>
|
||||
<th>{{'settings_server.ui_route' | i18next}}</th>
|
||||
<th>{{'settings_server.backend_route' | i18next}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr ng-if="servers.length === 0">
|
||||
<td colspan="7">
|
||||
<p class="text-center text-danger">Add a Plex Server</p>
|
||||
<p class="text-center text-danger">{{'settings_server.add_server' | i18next}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="serversPending">
|
||||
@ -33,13 +33,13 @@
|
||||
<td><span class='text-secondary text-small'>{{ x.uri }}</span></td>
|
||||
<td>
|
||||
<div class='loader' ng-if="x.uiStatus == 0"></div>
|
||||
<div class='text-success' ng-if="x.uiStatus == 1"><i class='fa fa-check'></i>ok</div>
|
||||
<div class='text-danger' ng-if="x.uiStatus == -1"><i class='fa fa-exclamation-triangle'></i>error</div>
|
||||
<div class='text-success' ng-if="x.uiStatus == 1"><i class='fa fa-check'></i>{{'settings_server.ok' | i18next}}</div>
|
||||
<div class='text-danger' ng-if="x.uiStatus == -1"><i class='fa fa-exclamation-triangle'></i>{{'settings_server.error' | i18next}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class='loader' ng-if="x.backendStatus == 0"></div>
|
||||
<div class='text-success' ng-if="x.backendStatus == 1"><i class='fa fa-check'></i>ok</div>
|
||||
<div class='text-danger' ng-if="x.backendStatus == -1"><i class='fa fa-exclamation-triangle'></i>error</div>
|
||||
<div class='text-success' ng-if="x.backendStatus == 1"><i class='fa fa-check'></i>{{'settings_server.ok' | i18next}}</div>
|
||||
<div class='text-danger' ng-if="x.backendStatus == -1"><i class='fa fa-exclamation-triangle'></i>{{'settings_server.error' | i18next}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-outline-secondary" ng-click="editPlexServer(x)">
|
||||
@ -53,25 +53,25 @@
|
||||
</tr>
|
||||
<tr ng-if="isAnyUIBad()">
|
||||
<td colspan="5">
|
||||
<p class="text-center text-danger small">If a Plex server configuration has problems with the UI route, the channel editor won't be able to access its content.</p>
|
||||
<p class="text-center text-danger small">{{'settings_server.ui_bad' | i18next}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="isAnyBackendBad()">
|
||||
<td colspan="5">
|
||||
<p class="text-center text-danger small">If a Plex server configuration has problems with the backend route, dizqueTV won't be able to play its content.</p>
|
||||
<p class="text-center text-danger small">{{'settings_server.server_bad' | i18next}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
<h6>Plex Transcoder Settings
|
||||
<h6>{{'settings_server.plex_transcoder_settings' | i18next}}
|
||||
|
||||
<button class="pull-right btn btn-sm btn-success" style="margin-left: 5px;" ng-click="updateSettings(settings)">
|
||||
Update
|
||||
{{'settings_server.update' | i18next}}
|
||||
</button>
|
||||
<button class="pull-right btn btn-sm btn-warning" ng-click="resetSettings(settings)">
|
||||
Reset Options
|
||||
{{'settings_server.reset_options' | i18next}}
|
||||
</button>
|
||||
</h6>
|
||||
<hr>
|
||||
@ -79,10 +79,10 @@
|
||||
<div class="col-sm-3">
|
||||
<div class="form-group">
|
||||
<input id="debugLogging" type="checkbox" ng-model="settings.debugLogging"></input>
|
||||
<label for="debugLogging">Debug logging</label>
|
||||
<label for="debugLogging">{{'settings_server.debug_logging' | i18next}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Paths</label>
|
||||
<label>{{'settings_server.paths' | i18next}}</label>
|
||||
<select ng-model="settings.streamPath"
|
||||
ng-options="o.id as o.description for o in pathOptions" ></select>
|
||||
</div>
|
||||
@ -90,110 +90,110 @@
|
||||
<div class="col-sm-3">
|
||||
<div class="form-group">
|
||||
<input id="updatePlayStatus" type="checkbox" ng-model="settings.updatePlayStatus" ria-describedby="updatePlayStatusHelp"></input>
|
||||
<label for="updatePlayStatus">Send play status to Plex</label>
|
||||
<small id="updatePlayStatusHelp" class="form-text text-muted">Note: This affects the "on deck" for your plex account.</small>
|
||||
<label for="updatePlayStatus">{{'settings_server.send_status_plex' | i18next}}</label>
|
||||
<small id="updatePlayStatusHelp" class="form-text text-muted">{{'settings_server.send_status_plex_note' | i18next}}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-hide="hideIfNotPlexPath()">
|
||||
<div class="col-sm-12">
|
||||
<p class="text-center text-info small">If stream changes video codec, audio codec, or audio channels upon episode change, you will experience playback issues unless ffmpeg transcoding and normalization are also enabled.</p>
|
||||
<p class="text-center text-info small">{{'settings_server.no_plex_path' | i18next}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-hide="hideIfNotPlexPath()">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<h6 style="font-weight: bold">Video Options</h6>
|
||||
<h6 style="font-weight: bold">{{'settings_server.video_options' | i18next}}</h6>
|
||||
<div class="form-group">
|
||||
<label>Supported Video Formats</label>
|
||||
<label>{{'settings_server.supported_video_formats' | i18next}}</label>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="settings.videoCodecs" ria-describedby="videoCodecsHelp"></input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Max Playable Resolution</label>
|
||||
<label>{{'settings_server.max_playable_resolution' | i18next}}</label>
|
||||
<select ng-model="settings.maxPlayableResolution"
|
||||
ng-options="o.id as o.description for o in resolutionOptions" ></select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Max Transcode Resolution</label>
|
||||
<label>{{'settings_server.max_transcode_resolution' | i18next}}</label>
|
||||
<select ng-model="settings.maxTranscodeResolution"
|
||||
ng-options="o.id as o.description for o in resolutionOptions "></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<h6 style="font-weight: bold">Audio Options</h6>
|
||||
<h6 style="font-weight: bold">{{'settings_server.audio_options' | i18next}}</h6>
|
||||
<div class="form-group">
|
||||
<label>Supported Audio Formats</label>
|
||||
<label>{{'settings_server.supported_audio_formats' | i18next}}</label>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="settings.audioCodecs" ria-describedby="audioCodecsHelp" ></input>
|
||||
<small id="audioCodecsHelp" class="form-text text-muted">Comma separated list. Some possible values are 'ac3,aac,mp3'.</small>
|
||||
<small id="audioCodecsHelp" class="form-text text-muted">{{'settings_server.supported_audio_formats_note' | i18next}}</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Maximum Audio Channels</label>
|
||||
<label>{{'settings_server.max_audio_channels' | i18next}}</label>
|
||||
<select ng-model="settings.maxAudioChannels"
|
||||
ng-options="o.id as o.description for o in maxAudioChannelsOptions" ria-describedby="maxAudioChannelsHelp"></select>
|
||||
<small id="maxAudioChannelsHelp" class="form-text text-muted">Note: 7.1 audio and on some clients, 6.1, is known to cause playback issues.</small>
|
||||
<small id="maxAudioChannelsHelp" class="form-text text-muted">{{'settings_server.max_audio_channels_note' | i18next}}</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Audio Boost</label>
|
||||
<label>{{'settings_server.audio_boost' | i18next}}</label>
|
||||
<select ng-model="settings.audioBoost"
|
||||
ng-options="o.id as o.description for o in audioBoostOptions" ria-describedby="audioBoostHelp"></select>
|
||||
<small id="audioBoostHelp" class="form-text text-muted">Note: Only applies when downmixing to stereo.</small>
|
||||
<small id="audioBoostHelp" class="form-text text-muted">{{'settings_server.audio_boost_note' | i18next}}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" ng-hide="hideIfNotPlexPath()">
|
||||
<div class="col-sm-6">
|
||||
<h6 style="font-weight: bold">Miscellaneous Options</h6>
|
||||
<h6 style="font-weight: bold">{{'settings_server.miscellaneous_options' | i18next}}</h6>
|
||||
<div class="form-group">
|
||||
<label>Max Direct Stream Bitrate (Kbps)</label>
|
||||
<label>{{'settings_server.max_direct_stream_bitrate' | i18next}}</label>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="settings.directStreamBitrate" ></input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Max Transcode Bitrate (Kbps)</label>
|
||||
<label>{{'settings_server.max_transcode_bitrate' | i18next}}</label>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="settings.transcodeBitrate" aria-described-by="transcodebrhelp" ></input>
|
||||
<small id="transcodebrhelp" class='text-muted form-text'>Plex will decide to transcode or direct play based on these settings and if Plex transcodes, it will try to match the transcode bitrate.</small>
|
||||
<small id="transcodebrhelp" class='text-muted form-text'>{{'settings_server.max_transcode_bitrate_note' | i18next}}</small>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Direct Stream Media Buffer Size</label>
|
||||
<label>{{'settings_server.direct_stream_media_buffer' | i18next}}</label>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="settings.mediaBufferSize" ></input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Transcode Media Buffer Size</label>
|
||||
<label>{{'settings_server.transcode_media_buffer' | i18next}}</label>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="settings.transcodeMediaBufferSize" ></input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Stream Protocol</label>
|
||||
<label>{{'settings_server.stream_protocol' | i18next}}</label>
|
||||
<select ng-model="settings.streamProtocol"
|
||||
ng-options="o.id as o.description for o in streamProtocols" ></select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input id="forceDirectPlay" type="checkbox" ng-model="settings.forceDirectPlay" ></input>
|
||||
<label for="forceDirectPlay">Force Direct Play</label>
|
||||
<label for="forceDirectPlay">{{'settings_server.force_direct_play' | i18next}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<h6 style="font-weight: bold">Subtitle Options</h6>
|
||||
<h6 style="font-weight: bold">{{'settings_server.subtitle_options' | i18next}}</h6>
|
||||
<div class="form-group">
|
||||
<label>Subtitle Size</label>
|
||||
<label>{{'settings_server.subtitle_size' | i18next}}</label>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="settings.subtitleSize" ></input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input class="form-check-input" id="enableSubtitles" type="checkbox" ng-model="settings.enableSubtitles" ng-disabled="shouldDisableSubtitles()" ></input>
|
||||
<label class="form-check-label" for="enableSubtitles">Enable Subtitles (Requires Transcoding)</label>
|
||||
<label class="form-check-label" for="enableSubtitles">{{'settings_server.enable_subtitle' | i18next}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" ng-hide="hideIfNotDirectPath()">
|
||||
<div class="col-sm-6">
|
||||
<h6 style="font-weight: bold">Path Replacements</h6>
|
||||
<h6 style="font-weight: bold">{{'settings_server.path_replacements' | i18next}}</h6>
|
||||
<div class="form-group">
|
||||
<label>Original Plex path to replace:</label>
|
||||
<label>{{'settings_server.original_plex_path' | i18next}}</label>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="settings.pathReplace" ></input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Replace Plex path with:</label>
|
||||
<label>{{'settings_server.replace_plex_path' | i18next}}</label>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="settings.pathReplaceWith" ></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,35 +1,35 @@
|
||||
<div>
|
||||
<h5>XMLTV Settings
|
||||
<h5>{{'settings_xmltv.title' | i18next}}
|
||||
|
||||
<button class="pull-right btn btn-sm btn-success" style="margin-left: 5px;" ng-click="updateSettings(settings)">
|
||||
Update
|
||||
{{'settings_xmltv.update' | i18next}}
|
||||
</button>
|
||||
<button class="pull-right btn btn-sm btn-warning" ng-click="resetSettings(settings)">
|
||||
Reset Options
|
||||
{{'settings_xmltv.reset_options' | i18next}}
|
||||
</button>
|
||||
</h5>
|
||||
<h6>Output Path</h6>
|
||||
<h6>{{'settings_xmltv.output_path' | i18next}}</h6>
|
||||
<input type="text" class="form-control form-control-sm" ng-model="settings.file" aria-describedby="pathhelp" readonly ></input>
|
||||
<small id="pathhelp" class="form-text text-muted">You can edit this location in file xmltv-settings.json.</small>
|
||||
<small id="pathhelp" class="form-text text-muted">{{'settings_xmltv.output_path_note' | i18next}}</small>
|
||||
<br></br>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<label>EPG Hours</label>
|
||||
<label>{{'settings_xmltv.epg_hours' | i18next}}</label>
|
||||
<input type="number" class="form-control form-control-sm" ng-model="settings.cache" aria-describedby="cachehelp"></input>
|
||||
<small id="cachehelp" class="form-text text-muted">How many hours of programming to include in the xmltv file.</small>
|
||||
<small id="cachehelp" class="form-text text-muted">{{'settings_xmltv.epg_hours_note' | i18next}}</small>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label>Refresh Timer (hours)</label>
|
||||
<label>{{'settings_xmltv.refresh_timer' | i18next}}</label>
|
||||
<input type="number" class="form-control form-control-sm" ng-model="settings.refresh" aria-describedby="timerhelp"></input>
|
||||
<small id="timerhelp" class="form-text text-muted">How often should the xmltv file be updated.</small>
|
||||
<small id="timerhelp" class="form-text text-muted">{{'settings_xmltv.refresh_timer_note' | i18next}}</small>
|
||||
</div>
|
||||
</div>
|
||||
<br ></br>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="imageCache" aria-describedby="imageCacheHelp" ng-model='settings.enableImageCache'>
|
||||
<label class="form-check-label" for="stealth">Image Cache</label>
|
||||
<label class="form-check-label" for="stealth">{{'settings_xmltv.image_cache' | i18next}}</label>
|
||||
|
||||
<div class='text-muted' id="imageCacheHelp">If enabled the pictures used for Movie and TV Show posters will be cached in dizqueTV's .dizqueTV folder and will be delivered by dizqueTV's server instead of requiring calls to Plex. Note that using fixed xmltv location in Plex (as opposed to url) will not work correctly in this case.</div>
|
||||
<div class='text-muted' id="imageCacheHelp">{{'settings_xmltv.image_cache_note' | i18next}}</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<div class='container-fluid'>
|
||||
|
||||
<h5>
|
||||
{{title}}
|
||||
{{'guide.title' | i18next}}
|
||||
</h5>
|
||||
<div style='padding:0; position:relative'>
|
||||
<table class="table tvguide" style="{'column-width': colspanPercent + '%' }">
|
||||
@ -29,7 +29,7 @@
|
||||
<tr ng-mouseover="channels[channelNumber].mouse=true" ng-mouseleave="channels[channelNumber].mouse=false" ng-repeat="channelNumber in channelNumbers track by $index" ng-Class="{'even' : ($index % 2==0), 'odd' : ($index % 2==1) }" >
|
||||
<td title='{{channels[channelNumber].altTitle}}' class='even channel-number' colspan="{{channelNumberColspan}}" >
|
||||
<div>
|
||||
<a role="button" href='/media-player/{{channelNumber}}.m3u' title="Attempt to play channel: '{{channels[channelNumber].altTitle}}' in local media player" class='btn btn-sm btn-outline-primary play-channel' ng-show='channels[channelNumber].mouse'>
|
||||
<a role="button" href='/media-player/{{channelNumber}}.m3u' title="{{'guide.attempt_to_play_channel' | i18next: {title: channels[channelNumber].altTitle} }}" class='btn btn-sm btn-outline-primary play-channel' ng-show='channels[channelNumber].mouse'>
|
||||
<span class='fa fa-play'></span>
|
||||
</a>
|
||||
<span ng-hide='channels[channelNumber].mouse' >
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user