mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-04 18:15:01 +02:00
Add:Open/close RSS feed for library items
This commit is contained in:
parent
1ddb6eca00
commit
c8053355df
18 changed files with 1238 additions and 12 deletions
125
plugins/i18n.js
Normal file
125
plugins/i18n.js
Normal file
|
@ -0,0 +1,125 @@
|
|||
import Vue from "vue"
|
||||
import enUsStrings from '../strings/en-us.json'
|
||||
|
||||
const defaultCode = 'en-us'
|
||||
|
||||
const languageCodeMap = {
|
||||
'de': { label: 'Deutsch', dateFnsLocale: 'de' },
|
||||
'en-us': { label: 'English', dateFnsLocale: 'enUS' },
|
||||
'es': { label: 'Español', dateFnsLocale: 'es' },
|
||||
'fr': { label: 'Français', dateFnsLocale: 'fr' },
|
||||
'hr': { label: 'Hrvatski', dateFnsLocale: 'hr' },
|
||||
'it': { label: 'Italiano', dateFnsLocale: 'it' },
|
||||
'nl': { label: 'Nederlands', dateFnsLocale: 'nl' },
|
||||
'pl': { label: 'Polski', dateFnsLocale: 'pl' },
|
||||
'ru': { label: 'Русский', dateFnsLocale: 'ru' },
|
||||
'zh-cn': { label: '简体中文 (Simplified Chinese)', dateFnsLocale: 'zhCN' },
|
||||
}
|
||||
|
||||
function supplant(str, subs) {
|
||||
// source: http://crockford.com/javascript/remedial.html
|
||||
return str.replace(/{([^{}]*)}/g,
|
||||
function (a, b) {
|
||||
var r = subs[b]
|
||||
return typeof r === 'string' || typeof r === 'number' ? r : a
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Vue.prototype.$languageCodeOptions = Object.keys(languageCodeMap).map(code => {
|
||||
return {
|
||||
text: languageCodeMap[code].label,
|
||||
value: code
|
||||
}
|
||||
})
|
||||
|
||||
Vue.prototype.$languageCodes = {
|
||||
default: defaultCode,
|
||||
current: defaultCode,
|
||||
local: null,
|
||||
server: null
|
||||
}
|
||||
|
||||
Vue.prototype.$strings = { ...enUsStrings }
|
||||
|
||||
Vue.prototype.$getString = (key, subs) => {
|
||||
if (!Vue.prototype.$strings[key]) return ''
|
||||
if (subs && Array.isArray(subs) && subs.length) {
|
||||
return supplant(Vue.prototype.$strings[key], subs)
|
||||
}
|
||||
return Vue.prototype.$strings[key]
|
||||
}
|
||||
|
||||
var translations = {
|
||||
[defaultCode]: enUsStrings
|
||||
}
|
||||
|
||||
function loadTranslationStrings(code) {
|
||||
return new Promise((resolve) => {
|
||||
import(`../strings/${code}`).then((fileContents) => {
|
||||
resolve(fileContents.default)
|
||||
}).catch((error) => {
|
||||
console.error('Failed to load i18n strings', code, error)
|
||||
resolve(null)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function loadi18n(code) {
|
||||
if (!code) return false
|
||||
if (Vue.prototype.$languageCodes.current == code) {
|
||||
// already set
|
||||
return false
|
||||
}
|
||||
|
||||
const strings = translations[code] || await loadTranslationStrings(code)
|
||||
if (!strings) {
|
||||
console.warn(`Invalid lang code ${code}`)
|
||||
return false
|
||||
}
|
||||
|
||||
translations[code] = strings
|
||||
Vue.prototype.$languageCodes.current = code
|
||||
localStorage.setItem('lang', code)
|
||||
|
||||
for (const key in Vue.prototype.$strings) {
|
||||
Vue.prototype.$strings[key] = strings[key] || translations[defaultCode][key]
|
||||
}
|
||||
|
||||
Vue.prototype.$setDateFnsLocale(languageCodeMap[code].dateFnsLocale)
|
||||
|
||||
this.$eventBus.$emit('change-lang', code)
|
||||
return true
|
||||
}
|
||||
|
||||
Vue.prototype.$setLanguageCode = loadi18n
|
||||
|
||||
// Set the servers default language code, does not override users local language code
|
||||
Vue.prototype.$setServerLanguageCode = (code) => {
|
||||
if (!code) return
|
||||
|
||||
if (!languageCodeMap[code]) {
|
||||
console.warn('invalid server language in', code)
|
||||
} else {
|
||||
Vue.prototype.$languageCodes.server = code
|
||||
if (!Vue.prototype.$languageCodes.local && code !== defaultCode) {
|
||||
loadi18n(code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize with language code in localStorage if valid
|
||||
async function initialize() {
|
||||
const localLanguage = localStorage.getItem('lang')
|
||||
if (!localLanguage) return
|
||||
|
||||
if (!languageCodeMap[localLanguage]) {
|
||||
console.warn('Invalid local language code', localLanguage)
|
||||
localStorage.setItem('lang', defaultCode)
|
||||
} else {
|
||||
Vue.prototype.$languageCodes.local = localLanguage
|
||||
loadi18n(localLanguage)
|
||||
}
|
||||
}
|
||||
initialize()
|
||||
|
|
@ -3,7 +3,8 @@ import vClickOutside from 'v-click-outside'
|
|||
import { App } from '@capacitor/app'
|
||||
import { Dialog } from '@capacitor/dialog'
|
||||
import { AbsFileSystem } from '@/plugins/capacitor'
|
||||
import { StatusBar, Style } from '@capacitor/status-bar';
|
||||
import { StatusBar, Style } from '@capacitor/status-bar'
|
||||
import { Clipboard } from '@capacitor/clipboard'
|
||||
import { formatDistance, format, addDays, isDate } from 'date-fns'
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
|
||||
|
@ -191,14 +192,49 @@ Vue.prototype.$setOrientationLock = (orientationLockSetting) => {
|
|||
if (!window.screen?.orientation) return
|
||||
|
||||
if (orientationLockSetting == 'PORTRAIT') {
|
||||
window.screen.orientation.lock?.('portrait')
|
||||
window.screen.orientation.lock?.('portrait').catch((error) => {
|
||||
console.error(error)
|
||||
})
|
||||
} else if (orientationLockSetting == 'LANDSCAPE') {
|
||||
window.screen.orientation.lock?.('landscape')
|
||||
window.screen.orientation.lock?.('landscape').catch((error) => {
|
||||
console.error(error)
|
||||
})
|
||||
} else {
|
||||
window.screen.orientation.unlock?.()
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$copyToClipboard = (str) => {
|
||||
return Clipboard.write({
|
||||
string: str
|
||||
})
|
||||
}
|
||||
|
||||
// SOURCE: https://gist.github.com/spyesx/561b1d65d4afb595f295
|
||||
// modified: allowed underscores
|
||||
Vue.prototype.$sanitizeSlug = (str) => {
|
||||
if (!str) return ''
|
||||
|
||||
str = str.replace(/^\s+|\s+$/g, '') // trim
|
||||
str = str.toLowerCase()
|
||||
|
||||
// remove accents, swap ñ for n, etc
|
||||
var from = "àáäâèéëêìíïîòóöôùúüûñçěščřžýúůďťň·/,:;"
|
||||
var to = "aaaaeeeeiiiioooouuuuncescrzyuudtn-----"
|
||||
|
||||
for (var i = 0, l = from.length; i < l; i++) {
|
||||
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i))
|
||||
}
|
||||
|
||||
str = str.replace('.', '-') // replace a dot by a dash
|
||||
.replace(/[^a-z0-9 -_]/g, '') // remove invalid chars
|
||||
.replace(/\s+/g, '-') // collapse whitespace and replace by a dash
|
||||
.replace(/-+/g, '-') // collapse dashes
|
||||
.replace(/\//g, '') // collapse all forward-slashes
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
export default ({ store, app }, inject) => {
|
||||
const eventBus = new Vue()
|
||||
inject('eventBus', eventBus)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue