feat: add language to topmenu + globals cleanup + i18n refactor (#3510)
This commit is contained in:
parent
5e36bb4fcd
commit
b6f533be24
15 changed files with 90 additions and 76 deletions
2
lnbits/static/bundle-components.min.js
vendored
2
lnbits/static/bundle-components.min.js
vendored
File diff suppressed because one or more lines are too long
2
lnbits/static/bundle.min.js
vendored
2
lnbits/static/bundle.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -66,7 +66,7 @@ window.LNbits = {
|
||||||
}
|
}
|
||||||
newWallet.msat = data.balance_msat
|
newWallet.msat = data.balance_msat
|
||||||
newWallet.sat = Math.floor(data.balance_msat / 1000)
|
newWallet.sat = Math.floor(data.balance_msat / 1000)
|
||||||
newWallet.fsat = new Intl.NumberFormat(window.LOCALE).format(
|
newWallet.fsat = new Intl.NumberFormat(window.i18n.global.locale).format(
|
||||||
newWallet.sat
|
newWallet.sat
|
||||||
)
|
)
|
||||||
if (newWallet.walletType === 'lightning-shared') {
|
if (newWallet.walletType === 'lightning-shared') {
|
||||||
|
|
@ -105,7 +105,9 @@ window.LNbits = {
|
||||||
obj.msat = obj.amount
|
obj.msat = obj.amount
|
||||||
obj.sat = obj.msat / 1000
|
obj.sat = obj.msat / 1000
|
||||||
obj.tag = obj.extra?.tag
|
obj.tag = obj.extra?.tag
|
||||||
obj.fsat = new Intl.NumberFormat(window.LOCALE).format(obj.sat)
|
obj.fsat = new Intl.NumberFormat(window.i18n.global.locale).format(
|
||||||
|
obj.sat
|
||||||
|
)
|
||||||
obj.isIn = obj.amount > 0
|
obj.isIn = obj.amount > 0
|
||||||
obj.isOut = obj.amount < 0
|
obj.isOut = obj.amount < 0
|
||||||
obj.isPending = obj.status === 'pending'
|
obj.isPending = obj.status === 'pending'
|
||||||
|
|
|
||||||
37
lnbits/static/js/components/lnbits-language-dropdown.js
Normal file
37
lnbits/static/js/components/lnbits-language-dropdown.js
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
window.app.component('lnbits-language-dropdown', {
|
||||||
|
template: '#lnbits-language-dropdown',
|
||||||
|
mixins: [window.windowMixin],
|
||||||
|
methods: {
|
||||||
|
activeLanguage(lang) {
|
||||||
|
return window.i18n.global.locale === lang
|
||||||
|
},
|
||||||
|
changeLanguage(newValue) {
|
||||||
|
this.g.locale = newValue
|
||||||
|
window.i18n.global.locale = newValue
|
||||||
|
this.$q.localStorage.set('lnbits.lang', newValue)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
langs: [
|
||||||
|
{value: 'en', label: 'English', display: '🇬🇧 EN'},
|
||||||
|
{value: 'de', label: 'Deutsch', display: '🇩🇪 DE'},
|
||||||
|
{value: 'es', label: 'Español', display: '🇪🇸 ES'},
|
||||||
|
{value: 'jp', label: '日本語', display: '🇯🇵 JP'},
|
||||||
|
{value: 'cn', label: '中文', display: '🇨🇳 CN'},
|
||||||
|
{value: 'fr', label: 'Français', display: '🇫🇷 FR'},
|
||||||
|
{value: 'it', label: 'Italiano', display: '🇮🇹 IT'},
|
||||||
|
{value: 'pi', label: 'Pirate', display: '🏴☠️ PI'},
|
||||||
|
{value: 'nl', label: 'Nederlands', display: '🇳🇱 NL'},
|
||||||
|
{value: 'we', label: 'Cymraeg', display: '🏴 CY'},
|
||||||
|
{value: 'pl', label: 'Polski', display: '🇵🇱 PL'},
|
||||||
|
{value: 'pt', label: 'Português', display: '🇵🇹 PT'},
|
||||||
|
{value: 'br', label: 'Português do Brasil', display: '🇧🇷 BR'},
|
||||||
|
{value: 'cs', label: 'Česky', display: '🇨🇿 CS'},
|
||||||
|
{value: 'sk', label: 'Slovensky', display: '🇸🇰 SK'},
|
||||||
|
{value: 'kr', label: '한국어', display: '🇰🇷 KR'},
|
||||||
|
{value: 'fi', label: 'Suomi', display: '🇫🇮 FI'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
@ -1,33 +1,3 @@
|
||||||
window.langs = [
|
|
||||||
{value: 'en', label: 'English', display: '🇬🇧 EN'},
|
|
||||||
{value: 'de', label: 'Deutsch', display: '🇩🇪 DE'},
|
|
||||||
{value: 'es', label: 'Español', display: '🇪🇸 ES'},
|
|
||||||
{value: 'jp', label: '日本語', display: '🇯🇵 JP'},
|
|
||||||
{value: 'cn', label: '中文', display: '🇨🇳 CN'},
|
|
||||||
{value: 'fr', label: 'Français', display: '🇫🇷 FR'},
|
|
||||||
{value: 'it', label: 'Italiano', display: '🇮🇹 IT'},
|
|
||||||
{value: 'pi', label: 'Pirate', display: '🏴☠️ PI'},
|
|
||||||
{value: 'nl', label: 'Nederlands', display: '🇳🇱 NL'},
|
|
||||||
{value: 'we', label: 'Cymraeg', display: '🏴 CY'},
|
|
||||||
{value: 'pl', label: 'Polski', display: '🇵🇱 PL'},
|
|
||||||
{value: 'pt', label: 'Português', display: '🇵🇹 PT'},
|
|
||||||
{value: 'br', label: 'Português do Brasil', display: '🇧🇷 BR'},
|
|
||||||
{value: 'cs', label: 'Česky', display: '🇨🇿 CS'},
|
|
||||||
{value: 'sk', label: 'Slovensky', display: '🇸🇰 SK'},
|
|
||||||
{value: 'kr', label: '한국어', display: '🇰🇷 KR'},
|
|
||||||
{value: 'fi', label: 'Suomi', display: '🇫🇮 FI'}
|
|
||||||
]
|
|
||||||
window.LOCALE = 'en'
|
|
||||||
window.dateFormat = 'YYYY-MM-DD HH:mm'
|
|
||||||
window.i18n = new VueI18n.createI18n({
|
|
||||||
locale: window.LOCALE,
|
|
||||||
fallbackLocale: window.LOCALE,
|
|
||||||
messages: window.localisation
|
|
||||||
})
|
|
||||||
const websocketPrefix =
|
|
||||||
window.location.protocol === 'http:' ? 'ws://' : 'wss://'
|
|
||||||
const websocketUrl = `${websocketPrefix}${window.location.host}/api/v1/ws`
|
|
||||||
|
|
||||||
window.g = Vue.reactive({
|
window.g = Vue.reactive({
|
||||||
offline: !navigator.onLine,
|
offline: !navigator.onLine,
|
||||||
visibleDrawer: false,
|
visibleDrawer: false,
|
||||||
|
|
@ -39,9 +9,16 @@ window.g = Vue.reactive({
|
||||||
fiatTracking: false,
|
fiatTracking: false,
|
||||||
wallets: [],
|
wallets: [],
|
||||||
payments: [],
|
payments: [],
|
||||||
langs: [],
|
|
||||||
walletEventListeners: [],
|
walletEventListeners: [],
|
||||||
updatePayments: false,
|
updatePayments: false,
|
||||||
updatePaymentsHash: '',
|
updatePaymentsHash: '',
|
||||||
walletFlip: Quasar.LocalStorage.getItem('lnbits.walletFlip') ?? false
|
walletFlip: Quasar.LocalStorage.getItem('lnbits.walletFlip') ?? false,
|
||||||
|
locale:
|
||||||
|
Quasar.LocalStorage.getItem('lnbits.lang') ?? navigator.languages[1] ?? 'en'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
window.dateFormat = 'YYYY-MM-DD HH:mm'
|
||||||
|
|
||||||
|
const websocketPrefix =
|
||||||
|
window.location.protocol === 'http:' ? 'ws://' : 'wss://'
|
||||||
|
const websocketUrl = `${websocketPrefix}${window.location.host}/api/v1/ws`
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,15 @@ window.app.use(Quasar, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
window.i18n = new VueI18n.createI18n({
|
||||||
|
locale: window.g.locale,
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
messages: window.localisation
|
||||||
|
})
|
||||||
|
|
||||||
window.app.use(window.i18n)
|
window.app.use(window.i18n)
|
||||||
|
|
||||||
window.app.provide('g', g)
|
window.app.provide('g', g)
|
||||||
window.app.use(window.router)
|
window.app.use(window.router)
|
||||||
window.app.component('DynamicComponent', DynamicComponent)
|
window.app.component('DynamicComponent', DynamicComponent)
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,7 @@ window.PagePayments = {
|
||||||
p.timeFrom = moment.utc(p.created_at).local().fromNow()
|
p.timeFrom = moment.utc(p.created_at).local().fromNow()
|
||||||
p.outgoing = p.amount < 0
|
p.outgoing = p.amount < 0
|
||||||
p.amount =
|
p.amount =
|
||||||
new Intl.NumberFormat(window.LOCALE).format(p.amount / 1000) +
|
new Intl.NumberFormat(this.g.locale).format(p.amount / 1000) +
|
||||||
' sats'
|
' sats'
|
||||||
if (p.extra?.wallet_fiat_amount) {
|
if (p.extra?.wallet_fiat_amount) {
|
||||||
p.amountFiat = this.formatCurrency(
|
p.amountFiat = this.formatCurrency(
|
||||||
|
|
@ -180,7 +180,7 @@ window.PagePayments = {
|
||||||
p.internal_memo = p.extra.internal_memo
|
p.internal_memo = p.extra.internal_memo
|
||||||
}
|
}
|
||||||
p.fee_sats =
|
p.fee_sats =
|
||||||
new Intl.NumberFormat(window.LOCALE).format(p.fee / 1000) + ' sats'
|
new Intl.NumberFormat(this.g.locale).format(p.fee / 1000) + ' sats'
|
||||||
|
|
||||||
return p
|
return p
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,13 @@ window._lnbitsUtils = {
|
||||||
return Quasar.date.formatDate(new Date(isoDateString), window.dateFormat)
|
return Quasar.date.formatDate(new Date(isoDateString), window.dateFormat)
|
||||||
},
|
},
|
||||||
formatCurrency(value, currency) {
|
formatCurrency(value, currency) {
|
||||||
return new Intl.NumberFormat(window.LOCALE, {
|
return new Intl.NumberFormat(window.i18n.global.locale, {
|
||||||
style: 'currency',
|
style: 'currency',
|
||||||
currency: currency || 'sat'
|
currency: currency || 'sat'
|
||||||
}).format(value)
|
}).format(value)
|
||||||
},
|
},
|
||||||
formatSat(value) {
|
formatSat(value) {
|
||||||
return new Intl.NumberFormat(window.LOCALE).format(value)
|
return new Intl.NumberFormat(window.i18n.global.locale).format(value)
|
||||||
},
|
},
|
||||||
formatMsat(value) {
|
formatMsat(value) {
|
||||||
return this.formatSat(value / 1000)
|
return this.formatSat(value / 1000)
|
||||||
|
|
|
||||||
|
|
@ -283,14 +283,6 @@ window.windowMixin = {
|
||||||
}
|
}
|
||||||
this.applyBackgroundImage()
|
this.applyBackgroundImage()
|
||||||
|
|
||||||
let locale = this.$q.localStorage.getItem('lnbits.lang')
|
|
||||||
if (locale) {
|
|
||||||
window.LOCALE = locale
|
|
||||||
window.i18n.global.locale = locale
|
|
||||||
}
|
|
||||||
|
|
||||||
this.g.langs = window.langs ?? []
|
|
||||||
|
|
||||||
addEventListener('offline', event => {
|
addEventListener('offline', event => {
|
||||||
console.log('offline', event)
|
console.log('offline', event)
|
||||||
this.g.offline = true
|
this.g.offline = true
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@
|
||||||
"js/components/lnbits-header.js",
|
"js/components/lnbits-header.js",
|
||||||
"js/components/lnbits-drawer.js",
|
"js/components/lnbits-drawer.js",
|
||||||
"js/components/lnbits-manage-extension-list.js",
|
"js/components/lnbits-manage-extension-list.js",
|
||||||
|
"js/components/lnbits-language-dropdown.js",
|
||||||
"js/components/extension-settings.js",
|
"js/components/extension-settings.js",
|
||||||
"js/components/data-fields.js",
|
"js/components/data-fields.js",
|
||||||
"js/components/payment-list.js",
|
"js/components/payment-list.js",
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ include('components/lnbits-footer.vue') %} {%
|
||||||
include('components/lnbits-header.vue') %} {%
|
include('components/lnbits-header.vue') %} {%
|
||||||
include('components/lnbits-drawer.vue') %} {%
|
include('components/lnbits-drawer.vue') %} {%
|
||||||
include('components/lnbits-home-logos.vue') %} {%
|
include('components/lnbits-home-logos.vue') %} {%
|
||||||
include('components/lnbits-manage-extension-list.vue') %}
|
include('components/lnbits-manage-extension-list.vue') %} {%
|
||||||
|
include('components/lnbits-language-dropdown.vue') %}
|
||||||
|
|
||||||
<template id="lnbits-wallet-list">
|
<template id="lnbits-wallet-list">
|
||||||
<q-list
|
<q-list
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@
|
||||||
<span>OFFLINE</span>
|
<span>OFFLINE</span>
|
||||||
</q-badge>
|
</q-badge>
|
||||||
|
|
||||||
|
<lnbits-language-dropdown></lnbits-language-dropdown>
|
||||||
|
|
||||||
<q-btn-dropdown
|
<q-btn-dropdown
|
||||||
v-if="g.user || isUserAuthorized"
|
v-if="g.user || isUserAuthorized"
|
||||||
flat
|
flat
|
||||||
|
|
|
||||||
19
lnbits/templates/components/lnbits-language-dropdown.vue
Normal file
19
lnbits/templates/components/lnbits-language-dropdown.vue
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<template id="lnbits-language-dropdown">
|
||||||
|
<q-btn-dropdown dense flat rounded size="sm" icon="language" class="q-pl-md">
|
||||||
|
<q-list v-for="(lang, index) in langs" :key="index">
|
||||||
|
<q-item
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
:active="activeLanguage(lang.value)"
|
||||||
|
@click="changeLanguage(lang.value)"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label
|
||||||
|
v-text="lang.display ?? lang.value.toUpperCase()"
|
||||||
|
></q-item-label>
|
||||||
|
<q-tooltip><span v-text="lang.label"></span></q-tooltip>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-btn-dropdown>
|
||||||
|
</template>
|
||||||
|
|
@ -366,33 +366,7 @@
|
||||||
<span v-text="$t('language')"></span>
|
<span v-text="$t('language')"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
<q-btn-dropdown
|
<lnbits-language-dropdown />
|
||||||
dense
|
|
||||||
flat
|
|
||||||
round
|
|
||||||
size="sm"
|
|
||||||
icon="language"
|
|
||||||
class="q-pl-md"
|
|
||||||
>
|
|
||||||
<q-list v-for="(lang, index) in g.langs" :key="index">
|
|
||||||
<q-item
|
|
||||||
clickable
|
|
||||||
v-close-popup
|
|
||||||
:active="activeLanguage(lang.value)"
|
|
||||||
@click="changeLanguage(lang.value)"
|
|
||||||
><q-item-section>
|
|
||||||
<q-item-label
|
|
||||||
v-text="
|
|
||||||
lang.display ?? lang.value.toUpperCase()
|
|
||||||
"
|
|
||||||
></q-item-label>
|
|
||||||
<q-tooltip
|
|
||||||
><span v-text="lang.label"></span
|
|
||||||
></q-tooltip>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-btn-dropdown>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row q-mb-md">
|
<div class="row q-mb-md">
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@
|
||||||
"js/components/lnbits-header.js",
|
"js/components/lnbits-header.js",
|
||||||
"js/components/lnbits-drawer.js",
|
"js/components/lnbits-drawer.js",
|
||||||
"js/components/lnbits-manage-extension-list.js",
|
"js/components/lnbits-manage-extension-list.js",
|
||||||
|
"js/components/lnbits-language-dropdown.js",
|
||||||
"js/components/extension-settings.js",
|
"js/components/extension-settings.js",
|
||||||
"js/components/data-fields.js",
|
"js/components/data-fields.js",
|
||||||
"js/components/payment-list.js",
|
"js/components/payment-list.js",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue