mirror of
https://github.com/webrecorder/pywb.git
synced 2025-03-24 06:59:52 +01:00
vue ui: added i18n to loader and vue app; added a i18n model that initializes with a config from the server/template and can be used directly or via the vue app root _() method
This commit is contained in:
parent
af04deabe6
commit
ea2e3d7120
File diff suppressed because one or more lines are too long
@ -18,13 +18,46 @@ html, body
|
|||||||
|
|
||||||
{{ banner_html }}
|
{{ banner_html }}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var i18nStrings = {
|
||||||
|
jan_long: "{{ _Q('January') }}",
|
||||||
|
feb_long: "{{ _Q('February') }}",
|
||||||
|
mar_long: "{{ _Q('March') }}",
|
||||||
|
apr_long: "{{ _Q('April') }}",
|
||||||
|
may_long: "{{ _Q('May') }}",
|
||||||
|
jun_long: "{{ _Q('June') }}",
|
||||||
|
jul_long: "{{ _Q('July') }}",
|
||||||
|
aug_long: "{{ _Q('August') }}",
|
||||||
|
sep_long: "{{ _Q('September') }}",
|
||||||
|
oct_long: "{{ _Q('October') }}",
|
||||||
|
nov_long: "{{ _Q('November') }}",
|
||||||
|
dec_long: "{{ _Q('December') }}",
|
||||||
|
jan_short: "{{ _Q('Jan') }}",
|
||||||
|
feb_short: "{{ _Q('Feb') }}",
|
||||||
|
mar_short: "{{ _Q('Mar') }}",
|
||||||
|
apr_short: "{{ _Q('Apr') }}",
|
||||||
|
may_short: "{{ _Q('May') }}",
|
||||||
|
jun_short: "{{ _Q('Jun') }}",
|
||||||
|
jul_short: "{{ _Q('Jul') }}",
|
||||||
|
aug_short: "{{ _Q('Aug') }}",
|
||||||
|
sep_short: "{{ _Q('Sep') }}",
|
||||||
|
oct_short: "{{ _Q('Oct') }}",
|
||||||
|
nov_short: "{{ _Q('Nov') }}",
|
||||||
|
dec_short: "{{ _Q('Dec') }}",
|
||||||
|
"Loading...": "{{ _Q('Loading...') }}",
|
||||||
|
"Current Capture": "{{ _Q('Current Capture') }}",
|
||||||
|
"capture": "{{ _Q('capture') }}",
|
||||||
|
"captures": "{{ _Q('captures') }}",
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body style="margin: 0px; padding: 0px;">
|
<body style="margin: 0px; padding: 0px;">
|
||||||
|
|
||||||
{% if ui.vue_timeline_banner %}
|
{% if ui.vue_timeline_banner %}
|
||||||
<div id="app" style="width: 100%; height: 200px"></div>
|
<div id="app" style="width: 100%; height: 200px"></div>
|
||||||
<script>
|
<script>
|
||||||
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ wb_prefix }}", "{{ timestamp }}", "{{ ui.logo }}");
|
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ wb_prefix }}", "{{ timestamp }}", "{{ ui.logo }}", i18nStrings);
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -18,6 +18,38 @@
|
|||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var i18nStrings = {
|
||||||
|
jan_long: "{{ _Q('January') }}",
|
||||||
|
feb_long: "{{ _Q('February') }}",
|
||||||
|
mar_long: "{{ _Q('March') }}",
|
||||||
|
apr_long: "{{ _Q('April') }}",
|
||||||
|
may_long: "{{ _Q('May') }}",
|
||||||
|
jun_long: "{{ _Q('June') }}",
|
||||||
|
jul_long: "{{ _Q('July') }}",
|
||||||
|
aug_long: "{{ _Q('August') }}",
|
||||||
|
sep_long: "{{ _Q('September') }}",
|
||||||
|
oct_long: "{{ _Q('October') }}",
|
||||||
|
nov_long: "{{ _Q('November') }}",
|
||||||
|
dec_long: "{{ _Q('December') }}",
|
||||||
|
jan_short: "{{ _Q('Jan') }}",
|
||||||
|
feb_short: "{{ _Q('Feb') }}",
|
||||||
|
mar_short: "{{ _Q('Mar') }}",
|
||||||
|
apr_short: "{{ _Q('Apr') }}",
|
||||||
|
may_short: "{{ _Q('May') }}",
|
||||||
|
jun_short: "{{ _Q('Jun') }}",
|
||||||
|
jul_short: "{{ _Q('Jul') }}",
|
||||||
|
aug_short: "{{ _Q('Aug') }}",
|
||||||
|
sep_short: "{{ _Q('Sep') }}",
|
||||||
|
oct_short: "{{ _Q('Oct') }}",
|
||||||
|
nov_short: "{{ _Q('Nov') }}",
|
||||||
|
dec_short: "{{ _Q('Dec') }}",
|
||||||
|
"Loading...": "{{ _Q('Loading...') }}",
|
||||||
|
"Current Capture": "{{ _Q('Current Capture') }}",
|
||||||
|
"capture": "{{ _Q('capture') }}",
|
||||||
|
"captures": "{{ _Q('captures') }}",
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@ -71,7 +103,7 @@
|
|||||||
renderCal.init();
|
renderCal.init();
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ prefix }}", undefined, "{{ ui.logo }}");
|
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ prefix }}", undefined, "{{ ui.logo }}", i18nStrings);
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
</form>
|
</form>
|
||||||
<div v-if="currentSnapshot && !showFullView">
|
<div v-if="currentSnapshot && !showFullView">
|
||||||
<span v-if="config.title">{{ config.title }}</span>
|
<span v-if="config.title">{{ config.title }}</span>
|
||||||
Current capture: {{currentSnapshot.getTimeDateFormatted()}}
|
{{_('Current Capture')}}: {{currentSnapshot.getTimeDateFormatted()}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<CalendarYear v-if="showFullView && currentPeriod && currentPeriod.children.length"
|
<CalendarYear v-if="showFullView && currentPeriod && currentPeriod.children.length"
|
||||||
@ -57,6 +57,7 @@ import TimelineBreadcrumbs from "./components/TimelineBreadcrumbs.vue";
|
|||||||
import CalendarYear from "./components/CalendarYear.vue";
|
import CalendarYear from "./components/CalendarYear.vue";
|
||||||
|
|
||||||
import { PywbSnapshot, PywbPeriod } from "./model.js";
|
import { PywbSnapshot, PywbPeriod } from "./model.js";
|
||||||
|
import {PywbI18N} from "./i18n";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PywbReplayApp",
|
name: "PywbReplayApp",
|
||||||
@ -74,7 +75,7 @@ export default {
|
|||||||
title: "",
|
title: "",
|
||||||
initialView: {}
|
initialView: {}
|
||||||
},
|
},
|
||||||
timelineHighlight: false
|
timelineHighlight: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
components: {Timeline, TimelineBreadcrumbs, CalendarYear},
|
components: {Timeline, TimelineBreadcrumbs, CalendarYear},
|
||||||
@ -87,6 +88,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
_(id) {
|
||||||
|
return PywbI18N.instance.getText(id);
|
||||||
|
},
|
||||||
gotoPeriod: function(newPeriod, onlyZoomToPeriod) {
|
gotoPeriod: function(newPeriod, onlyZoomToPeriod) {
|
||||||
if (this.timelineHighlight) {
|
if (this.timelineHighlight) {
|
||||||
setTimeout((() => {
|
setTimeout((() => {
|
||||||
|
@ -91,7 +91,7 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="calendar-month" :class="{current: isCurrent, 'contains-current-snapshot': containsCurrentSnapshot}">
|
<div class="calendar-month" :class="{current: isCurrent, 'contains-current-snapshot': containsCurrentSnapshot}">
|
||||||
<h3>{{month.getReadableId()}} <span v-if="month.snapshotCount">({{ month.snapshotCount }})</span></h3>
|
<h3>{{getLongMonthName(month.id)}} <span v-if="month.snapshotCount">({{ month.snapshotCount }})</span></h3>
|
||||||
<div v-if="month.snapshotCount">
|
<div v-if="month.snapshotCount">
|
||||||
<span v-for="(day) in ['S', 'M', 'T', 'W', 'H', 'F', 'S']" class="day" :style="dayStyle">{{day}}</span><br/>
|
<span v-for="(day) in ['S', 'M', 'T', 'W', 'H', 'F', 'S']" class="day" :style="dayStyle">{{day}}</span><br/>
|
||||||
<span v-for="(day,i) in days"><br v-if="i && i % 7===0"/><span class="day" :class="{empty: !day || !day.snapshotCount, 'contains-current-snapshot':dayContainsCurrentSnapshot(day)}" :style="dayStyle" @click="gotoDay(day, $event)"><template v-if="day"><span class="size" v-if="day.snapshotCount" :style="getDayCountCircleStyle(day.snapshotCount)"> </span><span class="day-id">{{day.id}}</span><span v-if="day.snapshotCount" class="count">{{day.snapshotCount}} capture<span v-if="day.snapshotCount!==1">s</span></span></template><template v-else v-html="' '"></template></span></span>
|
<span v-for="(day,i) in days"><br v-if="i && i % 7===0"/><span class="day" :class="{empty: !day || !day.snapshotCount, 'contains-current-snapshot':dayContainsCurrentSnapshot(day)}" :style="dayStyle" @click="gotoDay(day, $event)"><template v-if="day"><span class="size" v-if="day.snapshotCount" :style="getDayCountCircleStyle(day.snapshotCount)"> </span><span class="day-id">{{day.id}}</span><span v-if="day.snapshotCount" class="count">{{day.snapshotCount}} capture<span v-if="day.snapshotCount!==1">s</span></span></template><template v-else v-html="' '"></template></span></span>
|
||||||
@ -101,7 +101,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {PywbPeriod} from "../model";
|
import {PywbI18N} from "../i18n";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ["month", "year", "isCurrent", "yearContainsCurrentSnapshot", "currentSnapshot"],
|
props: ["month", "year", "isCurrent", "yearContainsCurrentSnapshot", "currentSnapshot"],
|
||||||
@ -143,6 +143,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getLongMonthName(id) {
|
||||||
|
return PywbI18N.instance.getMonth(id);
|
||||||
|
},
|
||||||
gotoDay(day, event) {
|
gotoDay(day, event) {
|
||||||
if (!day || !day.snapshotCount) {
|
if (!day || !day.snapshotCount) {
|
||||||
return;
|
return;
|
||||||
|
30
pywb/vueui/src/i18n.js
Normal file
30
pywb/vueui/src/i18n.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export class PywbI18N {
|
||||||
|
static init = config => {
|
||||||
|
if (PywbI18N.instance) {
|
||||||
|
throw new Error('cannot instantiate PywbI18N twice');
|
||||||
|
}
|
||||||
|
PywbI18N.instance = new PywbI18N(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PywbI18N expects from the i18n string source to receive months SHORT and LONG names in the config like this:
|
||||||
|
// config.jan_short, config.jan_long, ...., config.<mmm>_short, config.<mmm>_long
|
||||||
|
static monthIdPrefix = {1:"jan", 2:"feb",3:"mar",4:"apr",5:"may",6:"jun",7:"jul",8:"aug",9:"sep",10:"oct",11:"nov",12:"dec"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {PywbI18N|null}
|
||||||
|
*/
|
||||||
|
static instance = null;
|
||||||
|
|
||||||
|
constructor(config) {
|
||||||
|
this.config = {...config}; // make a copy of config
|
||||||
|
}
|
||||||
|
|
||||||
|
// can get long (default) or short month string
|
||||||
|
getMonth(id, type='long') {
|
||||||
|
return decodeURIComponent(this.config[PywbI18N.monthIdPrefix[id]+'_'+type]);
|
||||||
|
}
|
||||||
|
getText(id) {
|
||||||
|
return decodeURIComponent(this.config[id] || id);
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,15 @@
|
|||||||
import appData from "./App.vue";
|
import appData from "./App.vue";
|
||||||
|
|
||||||
import { PywbData } from "./model.js";
|
import { PywbData } from "./model.js";
|
||||||
|
import { PywbI18N } from "./i18n.js";
|
||||||
|
|
||||||
import Vue from "vue/dist/vue.esm.browser";
|
import Vue from "vue/dist/vue.esm.browser";
|
||||||
|
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
export function main(staticPrefix, url, prefix, timestamp, logoUrl) {
|
export function main(staticPrefix, url, prefix, timestamp, logoUrl, i18nStrings) {
|
||||||
const loadingSpinner = new LoadingSpinner(); // bootstrap loading-spinner EARLY ON
|
PywbI18N.init(i18nStrings);
|
||||||
|
const loadingSpinner = new LoadingSpinner({text: PywbI18N.instance?.getText('Loading...')}); // bootstrap loading-spinner EARLY ON
|
||||||
new CDXLoader(staticPrefix, url, prefix, timestamp, logoUrl, loadingSpinner);
|
new CDXLoader(staticPrefix, url, prefix, timestamp, logoUrl, loadingSpinner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const PywbMonthLabels = {1:"Jan", 2:"Feb",3:"Mar",4:"Apr",5:"May",6:"Jun",7:"Jul",8:"Aug",9:"Sep",10:"Oct",11:"Nov",12:"Dec"};
|
import { PywbI18N } from './i18n.js';
|
||||||
|
|
||||||
const PywbPeriodIdDelimiter = '-';
|
const PywbPeriodIdDelimiter = '-';
|
||||||
export function PywbData(rawSnaps) {
|
export function PywbData(rawSnaps) {
|
||||||
const allTimePeriod = new PywbPeriod({type: PywbPeriod.Type.all, id: "all"});
|
const allTimePeriod = new PywbPeriod({type: PywbPeriod.Type.all, id: "all"});
|
||||||
@ -116,11 +117,11 @@ export class PywbSnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getTimeDateFormatted() {
|
getTimeDateFormatted() {
|
||||||
return `${PywbMonthLabels[this.month]} ${this.day}, ${this.year} at ${this.getTimeFormatted()}`;
|
return `${PywbI18N.instance.getMonth(this.month, 'short')} ${this.day}, ${this.year} at ${this.getTimeFormatted()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDateFormatted() {
|
getDateFormatted() {
|
||||||
return `${this.year}-${PywbMonthLabels[this.month]}-${this.day}`;
|
return `${this.year}-${PywbI18N.instance.getMonth(this.month, 'short')}-${this.day}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTimeFormatted() {
|
getTimeFormatted() {
|
||||||
@ -486,7 +487,7 @@ PywbPeriod.prototype.getReadableId = function(hasDayCardinalSuffix) {
|
|||||||
case PywbPeriod.Type.year:
|
case PywbPeriod.Type.year:
|
||||||
return this.id;
|
return this.id;
|
||||||
case PywbPeriod.Type.month:
|
case PywbPeriod.Type.month:
|
||||||
return PywbMonthLabels[this.id];
|
return PywbI18N.instance.getMonth(this.id, 'short');
|
||||||
case PywbPeriod.Type.day: {
|
case PywbPeriod.Type.day: {
|
||||||
let suffix = "";
|
let suffix = "";
|
||||||
if (hasDayCardinalSuffix) {
|
if (hasDayCardinalSuffix) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user