1
0
mirror of https://github.com/webrecorder/pywb.git synced 2025-03-15 00:03:28 +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:
Ivan Velev 2022-02-07 16:49:49 -08:00
parent af04deabe6
commit ea2e3d7120
8 changed files with 257 additions and 216 deletions

File diff suppressed because one or more lines are too long

View File

@ -18,13 +18,46 @@ html, body
{{ 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>
<body style="margin: 0px; padding: 0px;">
{% if ui.vue_timeline_banner %}
<div id="app" style="width: 100%; height: 200px"></div>
<script>
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ wb_prefix }}", "{{ timestamp }}", "{{ ui.logo }}");
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ wb_prefix }}", "{{ timestamp }}", "{{ ui.logo }}", i18nStrings);
</script>
{% endif %}

View File

@ -18,6 +18,38 @@
{% 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 %}
@ -71,7 +103,7 @@
renderCal.init();
{% else %}
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ prefix }}", undefined, "{{ ui.logo }}");
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ prefix }}", undefined, "{{ ui.logo }}", i18nStrings);
{% endif %}

View File

@ -40,7 +40,7 @@
</form>
<div v-if="currentSnapshot && !showFullView">
<span v-if="config.title">{{ config.title }}</span>
Current capture: {{currentSnapshot.getTimeDateFormatted()}}
{{_('Current Capture')}}: {{currentSnapshot.getTimeDateFormatted()}}
</div>
</div>
<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 { PywbSnapshot, PywbPeriod } from "./model.js";
import {PywbI18N} from "./i18n";
export default {
name: "PywbReplayApp",
@ -74,7 +75,7 @@ export default {
title: "",
initialView: {}
},
timelineHighlight: false
timelineHighlight: false,
};
},
components: {Timeline, TimelineBreadcrumbs, CalendarYear},
@ -87,6 +88,9 @@ export default {
}
},
methods: {
_(id) {
return PywbI18N.instance.getText(id);
},
gotoPeriod: function(newPeriod, onlyZoomToPeriod) {
if (this.timelineHighlight) {
setTimeout((() => {

View File

@ -91,7 +91,7 @@
<template>
<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">
<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="'&nbsp;'"></template></span></span>
@ -101,7 +101,7 @@
</template>
<script>
import {PywbPeriod} from "../model";
import {PywbI18N} from "../i18n";
export default {
props: ["month", "year", "isCurrent", "yearContainsCurrentSnapshot", "currentSnapshot"],
@ -143,6 +143,9 @@ export default {
}
},
methods: {
getLongMonthName(id) {
return PywbI18N.instance.getMonth(id);
},
gotoDay(day, event) {
if (!day || !day.snapshotCount) {
return;

30
pywb/vueui/src/i18n.js Normal file
View 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);
}
}

View File

@ -1,13 +1,15 @@
import appData from "./App.vue";
import { PywbData } from "./model.js";
import { PywbI18N } from "./i18n.js";
import Vue from "vue/dist/vue.esm.browser";
// ===========================================================================
export function main(staticPrefix, url, prefix, timestamp, logoUrl) {
const loadingSpinner = new LoadingSpinner(); // bootstrap loading-spinner EARLY ON
export function main(staticPrefix, url, prefix, timestamp, logoUrl, i18nStrings) {
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);
}

View File

@ -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 = '-';
export function PywbData(rawSnaps) {
const allTimePeriod = new PywbPeriod({type: PywbPeriod.Type.all, id: "all"});
@ -116,11 +117,11 @@ export class PywbSnapshot {
}
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() {
return `${this.year}-${PywbMonthLabels[this.month]}-${this.day}`;
return `${this.year}-${PywbI18N.instance.getMonth(this.month, 'short')}-${this.day}`;
}
getTimeFormatted() {
@ -486,7 +487,7 @@ PywbPeriod.prototype.getReadableId = function(hasDayCardinalSuffix) {
case PywbPeriod.Type.year:
return this.id;
case PywbPeriod.Type.month:
return PywbMonthLabels[this.id];
return PywbI18N.instance.getMonth(this.id, 'short');
case PywbPeriod.Type.day: {
let suffix = "";
if (hasDayCardinalSuffix) {