Add localization configs and language-menu

This commit is contained in:
Blue (Lukas Rieger) 2021-03-20 23:16:03 +01:00
parent 4b1b32bcd0
commit 5ed5e21896
No known key found for this signature in database
GPG Key ID: 904C4995F9E1F800
17 changed files with 656 additions and 153 deletions

143
public/lang/de.js Normal file
View File

@ -0,0 +1,143 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menü",
tooltip: "Menü"
},
maps: {
title: "Karten",
button: "Karten",
tooltip: "Kartenliste"
},
markers: {
title: "Marker",
button: "Marker",
tooltip: "Markerliste",
marker: "Marker | Marker",
markerSet: "Markerset | Markersets"
},
settings: {
title: "Einstellungen",
button: "Einstellungen"
},
goFullscreen: {
button: "Vollbildmodus"
},
resetCamera: {
button: "Kamera zurücksetzen",
tooltip: "Kamera & Position zurücksetzen"
},
updateMap: {
button: "Karte aktualisieren",
tooltip: "Leere den Karten-Cache"
},
lighting: {
title: "Beleuchtung",
dayNightSwitch: {
tooltip: "Tag/Nacht"
},
sunlight: "Sonnenlicht",
ambientLight: "Umgebungslicht"
},
resolution: {
title: "Auflösung",
high: "Hoch (SSAA, x2)",
normal: "Normal (Nativ, x1)",
low: "Niedrig (Hochskalieren, x0.5)"
},
freeFlightControls: {
title: "Freie Kamera",
mouseSensitivity: "Maus-Sensitivität",
invertMouseY: "Maus Y umkehren"
},
renderDistance: {
title: "Renderdistanz",
hiresLayer: "Hires-Schicht",
lowersLayer: "Lowres-Schicht"
},
theme: {
title: "Farbmodus",
default: "Standard (System/Browser)",
dark: "Dunkel",
light: "Hell"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Einstellungen zurücksetzen"
},
players: {
title: "Spieler",
tooltip: "Spielerliste"
},
compass: {
tooltip: "Kompass / nach Norden ausrichten"
},
controls: {
perspective: {
button: "Perspectiv-Sicht",
tooltip: "Perspectivische Sicht"
},
flatView: {
button: "Flache Sicht",
tooltip: "Orthographisch / Flache Sicht",
},
freeFlight: {
button: "Freie Kamera",
tooltip: "Freie Kamera / Beobachter Modus"
}
},
language: {
title: "Sprache",
},
blockTooltip: {
block: "Block",
position: "Position",
chunk: "Chunk",
region: {
region: "Region",
file: "Datei"
},
light: {
light: "Licht",
sun: "Sonne",
block: "Block",
}
},
info: {
title: "Info",
button: "Info",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Maussteuerung:</h2>
<table>
<tr><th>Bewegen</th><td><kbd>Linksklick</kbd> + ziehen</td></tr>
<tr><th>Zoomen</th><td><kbd>Mausrad</kbd> (scrollen)</td></tr>
<tr><th>Drehen / Schwenken</th><td><kbd>Rechtsklick</kbd> + ziehen</td></tr>
</table>
</p>
<p>
<h2>Tastatursteuerung:</h2>
<table>
<tr><th>Bewegen</th><td><kbd>wasd</kbd> / <kbd>Pfeiltasten</kbd></td></tr>
<tr><th>Zoomen</th><td>Nummernblock: <kbd>+</kbd>/<kbd>-</kbd> oder <kbd>Einfg</kbd>/<kbd>Pos 1</kbd></td></tr>
<tr><th>Drehen / Schwenken</th><td><kbd>Alt</kbd> + <kbd>wasd</kbd> / <kbd>Pfeiltasten</kbd> oder <kbd>Entf</kbd>/<kbd>Ende</kbd>/<kbd>Bild &uarr;</kbd>/<kbd>Bild &darr;</kbd></td></tr>
</table>
</p>
<p>
<h2>Touchsteuerung:</h2>
<table>
<tr><th>Bewegen</th><td>berühren + ziehen</td></tr>
<tr><th>Zoomen</th><td>mit zwei Fingern berühren + zusammen/auseinander ziehen</td></tr>
<tr><th>Drehen / Schwenken</th><td>mit zwei Fingern berühren + drehen / hoch/runter ziehen</td></tr>
</table>
</p>
<br><hr>
<p>
Diese Map wurde mit &#9829; von <a href="https://bluecolo.red/bluemap">BlueMap</a> generiert.
</p>
`
}
}

143
public/lang/en.js Normal file
View File

@ -0,0 +1,143 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menu",
tooltip: "Menu"
},
maps: {
title: "Maps",
button: "Maps",
tooltip: "Map-List"
},
markers: {
title: "Markers",
button: "Markers",
tooltip: "Marker-List",
marker: "marker | markers",
markerSet: "marker-set | marker-sets"
},
settings: {
title: "Settings",
button: "Settings"
},
goFullscreen: {
button: "Go Fullscreen"
},
resetCamera: {
button: "Reset Camera",
tooltip: "Reset Camera & Position"
},
updateMap: {
button: "Update Map",
tooltip: "Clear Tile Cache"
},
lighting: {
title: "Lighting",
dayNightSwitch: {
tooltip: "Day/Night"
},
sunlight: "Sunlight",
ambientLight: "Ambient-Light"
},
resolution: {
title: "Resolution",
high: "High (SSAA, x2)",
normal: "Normal (Native, x1)",
low: "Low (Upscaling, x0.5)"
},
freeFlightControls: {
title: "Free-Flight Controls",
mouseSensitivity: "Mouse-Sensitivity",
invertMouseY: "Invert Mouse Y"
},
renderDistance: {
title: "Render Distance",
hiresLayer: "Hires layer",
lowersLayer: "Lowres layer"
},
theme: {
title: "Theme",
default: "Default (System/Browser)",
dark: "Dark",
light: "Light"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Reset All Settings"
},
players: {
title: "Players",
tooltip: "Player-List"
},
compass: {
tooltip: "Compass / Face North"
},
controls: {
perspective: {
button: "Perspective",
tooltip: "Perspective-View"
},
flatView: {
button: "Flat",
tooltip: "Orthographic / Flat-View",
},
freeFlight: {
button: "Free-Flight",
tooltip: "Free-Flight / Spectator Mode"
}
},
language: {
title: "Language",
},
blockTooltip: {
block: "Block",
position: "Position",
chunk: "Chunk",
region: {
region: "Region",
file: "File"
},
light: {
light: "Light",
sun: "Sun",
block: "Block",
}
},
info: {
title: "Info",
button: "Info",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Mouse-Controls:</h2>
<table>
<tr><th>move</th><td><kbd>left-click</kbd> + drag</td></tr>
<tr><th>zoom</th><td><kbd>mousewheel</kbd> (scroll)</td></tr>
<tr><th>rotate / tilt</th><td><kbd>right-click</kbd> + drag</td></tr>
</table>
</p>
<p>
<h2>Keyboard-Controls:</h2>
<table>
<tr><th>move</th><td><kbd>wasd</kbd> / <kbd>arrow-keys</kbd></td></tr>
<tr><th>zoom</th><td>Numpad: <kbd>+</kbd>/<kbd>-</kbd> or <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>rotate / tilt</th><td><kbd>Left-Alt</kbd> + <kbd>wasd</kbd> / <kbd>arrow-keys</kbd> or <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Touch-Controls:</h2>
<table>
<tr><th>move</th><td>touch + drag</td></tr>
<tr><th>zoom</th><td>touch with two fingers + pinch</td></tr>
<tr><th>rotate / tilt</th><td>touch with two fingers + rotate / move up/down</td></tr>
</table>
</p>
<br><hr>
<p>
This map has been generated with &#9829; using <a href="https://bluecolo.red/bluemap">BlueMap</a>.
</p>
`
}
}

15
public/lang/settings.js Normal file
View File

@ -0,0 +1,15 @@
export default {
default: "en",
languages: [
{
locale: "en",
name: "English"
},
/* // uncomment the languages you need, or add your own
{
locale: "de",
name: "Deutsch"
},
*/
]
}

View File

@ -1,22 +1,22 @@
<template>
<div class="control-bar">
<MenuButton :close="appState.menu.isOpen" :back="false" @action="appState.menu.reOpenPage()" :title="$t('menu.title')" />
<MenuButton :close="appState.menu.isOpen" :back="false" @action="appState.menu.reOpenPage()" :title="$t('menu.tooltip')" />
<div class="space thin-hide"></div>
<SvgButton v-if="appState.maps.length > 0" class="thin-hide" :title="$t('maps.ctrlBar')"
<SvgButton v-if="appState.maps.length > 0" class="thin-hide" :title="$t('maps.tooltip')"
@action="appState.menu.openPage('maps', $t('maps.title'))">
<svg viewBox="0 0 30 30">
<polygon points="26.708,22.841 19.049,25.186 11.311,20.718 3.292,22.841 7.725,5.96 13.475,4.814 19.314,7.409 25.018,6.037 "/>
</svg>
</SvgButton>
<SvgButton v-if="markers.markerSets.length > 0 || markers.markers.length > 0" class="thin-hide" :title="$t('markers.ctrlBar')"
@action="appState.menu.openPage('markers', t('markers.title'), {markerSet: markers})">
<SvgButton v-if="markers.markerSets.length > 0 || markers.markers.length > 0" class="thin-hide" :title="$t('markers.tooltip')"
@action="appState.menu.openPage('markers', $t('markers.title'), {markerSet: markers})">
<svg viewBox="0 0 30 30">
<path d="M15,3.563c-4.459,0-8.073,3.615-8.073,8.073c0,6.483,8.196,14.802,8.196,14.802s7.951-8.013,7.951-14.802
C23.073,7.177,19.459,3.563,15,3.563z M15,15.734c-2.263,0-4.098-1.835-4.098-4.099c0-2.263,1.835-4.098,4.098-4.098
c2.263,0,4.098,1.835,4.098,4.098C19.098,13.899,17.263,15.734,15,15.734z"/>
</svg>
</SvgButton>
<SvgButton v-if="!playerMarkerSet.fake" class="thin-hide" :title="$t('players.ctrlBar')" @action="openPlayerList">
<SvgButton v-if="!playerMarkerSet.fake" class="thin-hide" :title="$t('players.tooltip')" @action="openPlayerList">
<svg viewBox="0 0 30 30">
<g>
<path d="M8.95,14.477c0.409-0.77,1.298-1.307,2.164-1.309h0.026c-0.053-0.234-0.087-0.488-0.087-0.755
@ -43,11 +43,11 @@
</svg>
</SvgButton>
<div class="space thin-hide greedy"></div>
<DayNightSwitch class="thin-hide" :title="$t('lighting.dayNightSwitch.ctrlBar')" />
<DayNightSwitch class="thin-hide" :title="$t('lighting.dayNightSwitch.tooltip')" />
<div class="space thin-hide"></div>
<ControlsSwitch class="thin-hide"></ControlsSwitch>
<div class="space thin-hide"></div>
<SvgButton class="thin-hide" :title="$t('resetCamera.ctrlBar')" @action="$bluemap.resetCamera()">
<SvgButton class="thin-hide" :title="$t('resetCamera.tooltip')" @action="$bluemap.resetCamera()">
<svg viewBox="0 0 30 30">
<rect x="7.085" y="4.341" transform="matrix(0.9774 0.2116 -0.2116 0.9774 3.2046 -1.394)" width="2.063" height="19.875"/>
<path d="M12.528,5.088c0,0,3.416-0.382,4.479-0.031c1.005,0.332,2.375,2.219,3.382,2.545c1.096,0.354,4.607-0.089,4.607-0.089
@ -56,7 +56,7 @@
</svg>
</SvgButton>
<PositionInput class="pos-input" />
<Compass :title="$t('compass.ctrlBar')" />
<Compass :title="$t('compass.tooltip')" />
</div>
</template>
@ -102,7 +102,7 @@
methods: {
openPlayerList() {
let playerList = this.playerMarkerSet;
this.appState.menu.openPage('markers', 'Players', {markerSet: playerList});
this.appState.menu.openPage('markers', this.$t("players.title"), {markerSet: playerList});
}
}
}

View File

@ -1,6 +1,6 @@
<template>
<div class="controls-switch">
<SvgButton :active="isPerspectiveView" @action="setPerspectiveView" :title="$t('controls.perspective.ctrlBar')">
<SvgButton :active="isPerspectiveView" @action="setPerspectiveView" :title="$t('controls.perspective.tooltip')">
<svg viewBox="0 0 30 30">
<path d="M19.475,10.574c-0.166-0.021-0.337-0.036-0.51-0.045c-0.174-0.009-0.35-0.013-0.525-0.011
c-0.176,0.002-0.353,0.01-0.526,0.024c-0.175,0.015-0.347,0.036-0.515,0.063l-13.39,2.189
@ -13,12 +13,12 @@
c-0.116-0.051-0.243-0.097-0.381-0.138c-0.137-0.041-0.283-0.078-0.438-0.108C19.803,10.621,19.641,10.595,19.475,10.574"/>
</svg>
</SvgButton>
<SvgButton :active="isFlatView" @action="setFlatView" :title="$t('controls.flatView.ctrlBar')">
<SvgButton :active="isFlatView" @action="setFlatView" :title="$t('controls.flatView.tooltip')">
<svg viewBox="0 0 30 30">
<path d="M22.371,4.158c1.65,0,3,1.35,3,3v15.684c0,1.65-1.35,3-3,3H7.629c-1.65,0-3-1.35-3-3V7.158c0-1.65,1.35-3,3-3H22.371z"/>
</svg>
</SvgButton>
<SvgButton :active="isFreeFlight" @action="setFreeFlight" :title="$t('controls.freeFlight.ctrlBar')">
<SvgButton :active="isFreeFlight" @action="setFreeFlight" :title="$t('controls.freeFlight.tooltip')">
<svg viewBox="0 0 30 30">
<path d="M21.927,11.253c-0.256-0.487-0.915-0.885-1.465-0.885h-2.004c-0.55,0-0.726-0.356-0.39-0.792c0,0,0.698-0.905,0.698-2.041
c0-2.08-1.687-3.767-3.767-3.767s-3.767,1.687-3.767,3.767c0,1.136,0.698,2.041,0.698,2.041c0.336,0.436,0.161,0.794-0.389,0.797

View File

@ -6,13 +6,14 @@
@close="menu.closeAll()">
<div v-if="menu.currentPage().id === 'root'">
<SimpleButton @action="menu.openPage('maps', $t('maps.title'))" :submenu="true">{{ $t("maps.title") }}</SimpleButton>
<SimpleButton @action="menu.openPage('markers', $t('markers.title'), {markerSet: markers})" :submenu="true">{{ $t("markers.title") }}</SimpleButton>
<SimpleButton @action="menu.openPage('settings', $t('settings.title'))" :submenu="true">{{ $t("settings.title") }}</SimpleButton>
<SimpleButton @action="menu.openPage('maps', () => $t('maps.title'))" :submenu="true">{{ $t("maps.button") }}</SimpleButton>
<SimpleButton @action="menu.openPage('markers', () => $t('markers.title'), {markerSet: markers})" :submenu="true">{{ $t("markers.button") }}</SimpleButton>
<SimpleButton @action="menu.openPage('settings', () => $t('settings.title'))" :submenu="true">{{ $t("settings.button") }}</SimpleButton>
<SimpleButton @action="menu.openPage('info', () => $t('info.title'))" :submenu="true">{{ $t("info.button") }}</SimpleButton>
<hr>
<SimpleButton @action="goFullscreen">{{ $t("goFullscreen.title") }}</SimpleButton>
<SimpleButton @action="$bluemap.resetCamera()">{{ $t("resetCamera.title") }}</SimpleButton>
<SimpleButton @action="$bluemap.updateMap()" :title="$t('updateMap.description')">{{ $t("updateMap.title") }}</SimpleButton>
<SimpleButton @action="goFullscreen">{{ $t("goFullscreen.button") }}</SimpleButton>
<SimpleButton @action="$bluemap.resetCamera()">{{ $t("resetCamera.button") }}</SimpleButton>
<SimpleButton @action="$bluemap.updateMap()" :title="$t('updateMap.tooltip')">{{ $t("updateMap.button") }}</SimpleButton>
</div>
<div v-if="menu.currentPage().id === 'maps'">
@ -23,6 +24,8 @@
<SettingsMenu v-if="menu.currentPage().id === 'settings'" />
<div class="info-content" v-if="menu.currentPage().id === 'info'" v-html="$t('info.content')"></div>
</SideMenu>
</template>
@ -54,6 +57,25 @@ export default {
}
</script>
<style>
<style lang="scss">
.info-content {
font-size: 0.8em;
table {
border-collapse: collapse;
width: 100%;
tr {
th, td {
padding: 0.2em 0.5em;
border: solid 1px var(--theme-bg-light);
}
th {
font-weight: inherit;
text-align: inherit;
}
}
}
}
</style>

View File

@ -7,7 +7,7 @@
<div class="info">
<div class="label">{{markerLabel}}</div>
<div class="stats">
<div>
<div v-if="appState.debug">
{{marker.type}}-marker
</div>
<div>
@ -38,6 +38,7 @@ export default {
},
data() {
return {
appState: this.$bluemap.appState,
controls: this.$bluemap.mapViewer.controlsManager.data,
}
},

View File

@ -2,17 +2,17 @@
<div class="marker-set" :title="markerSet.id">
<div class="info" @click="toggle">
<div class="marker-set-switch">
<div class="label">{{ markerSet.label }}</div>
<div class="label">{{ label }}</div>
<SwitchHandle :on="markerSet.visible" v-if="markerSet.toggleable"/>
</div>
<div class="stats">
<div>
{{ markerSet.markers.length }}
{{ markerSet.markers.length !== 1 ? "markers" : "marker" }}
{{ $tc('markers.marker', markerSet.markers.length) }}
</div>
<div v-if="filteredMarkerSets.length > 0">
{{ filteredMarkerSets.length }}
{{ filteredMarkerSets.length !== 1 ? "marker-sets" : "marker-set" }}
{{ $tc('markers.markerSet', filteredMarkerSets.length) }}
</div>
</div>
</div>
@ -41,6 +41,10 @@ export default {
return this.markerSet.markerSets.filter(markerSet => {
return (markerSet.id !== "bm-popup-set");
});
},
label() {
if (this.markerSet.id === "bm-players") return this.$t("players.title");
return this.markerSet.label;
}
},
methods: {

View File

@ -1,16 +1,16 @@
<template>
<div>
<Group title="View / Controls">
<SimpleButton :active="appState.controls.state === 'perspective'" @action="$bluemap.setPerspectiveView(500, appState.controls.state === 'free' ? 100 : 0)">{{$t('controls.perspective.title')}}</SimpleButton>
<SimpleButton :active="appState.controls.state === 'flat'" @action="$bluemap.setFlatView(500, appState.controls.state === 'free' ? 100 : 0)">{{$t('controls.flatView.title')}}</SimpleButton>
<SimpleButton :active="appState.controls.state === 'free'" @action="$bluemap.setFreeFlight(500)">{{$t('controls.freeFlight.title')}}</SimpleButton>
<SimpleButton :active="appState.controls.state === 'perspective'" @action="$bluemap.setPerspectiveView(500, appState.controls.state === 'free' ? 100 : 0)">{{$t('controls.perspective.button')}}</SimpleButton>
<SimpleButton :active="appState.controls.state === 'flat'" @action="$bluemap.setFlatView(500, appState.controls.state === 'free' ? 100 : 0)">{{$t('controls.flatView.button')}}</SimpleButton>
<SimpleButton :active="appState.controls.state === 'free'" @action="$bluemap.setFreeFlight(500)">{{$t('controls.freeFlight.button')}}</SimpleButton>
</Group>
<Group :title="$t('lighting.title')">
<Slider :value="mapViewer.uniforms.sunlightStrength.value" :min="0" :max="1" :step="0.01"
@update="mapViewer.uniforms.sunlightStrength.value = $event">Sunlight</Slider>
@update="mapViewer.uniforms.sunlightStrength.value = $event">{{$t('lighting.sunlight')}}</Slider>
<Slider :value="mapViewer.uniforms.ambientLight.value" :min="0" :max="1" :step="0.01"
@update="mapViewer.uniforms.ambientLight.value = $event">Ambient-Light</Slider>
@update="mapViewer.uniforms.ambientLight.value = $event">{{$t('lighting.ambientLight')}}</Slider>
</Group>
<Group :title="$t('resolution.title')">
@ -40,9 +40,16 @@
>{{theme.name}}</SimpleButton>
</Group>
<SwitchButton :on="appState.debug" @action="switchDebug(); $bluemap.saveUserSettings();">{{ $t("debug.title") }}</SwitchButton>
<Group v-if="$i18n.languages.length > 1" :title="$t('language.title')">
<SimpleButton v-for="lang of $i18n.languages" :key="lang.locale"
:active="lang.locale === $i18n.locale"
@action="$i18n.locale = lang.locale; $bluemap.saveUserSettings();"
>{{lang.name}}</SimpleButton>
</Group>
<SimpleButton @action="$bluemap.resetSettings()">{{ $t("resetAllSettings.title") }}</SimpleButton>
<SwitchButton :on="appState.debug" @action="switchDebug(); $bluemap.saveUserSettings();">{{ $t("debug.button") }}</SwitchButton>
<SimpleButton @action="$bluemap.resetSettings()">{{ $t("resetAllSettings.button") }}</SimpleButton>
</div>
</template>
@ -54,15 +61,15 @@ import SwitchButton from "@/components/Menu/SwitchButton";
import i18n from "../../i18n";
const themes = [
{name: i18n.t("theme.default"), value: null},
{name: i18n.t("theme.dark"), value: 'dark'},
{name: i18n.t("theme.light"), value: 'light'},
{get name(){ return i18n.t("theme.default")}, value: null},
{get name(){ return i18n.t("theme.dark")}, value: 'dark'},
{get name(){ return i18n.t("theme.light")}, value: 'light'},
];
const qualityStages = [
{name: i18n.t("resolution.high"), value: 2},
{name: i18n.t("resolution.normal"), value: 1},
{name: i18n.t("resolution.low"), value: 0.5},
{get name(){ return i18n.t("resolution.high")}, value: 2},
{get name(){ return i18n.t("resolution.normal")}, value: 1},
{get name(){ return i18n.t("resolution.low")}, value: 0.5},
];
export default {

View File

@ -1,85 +0,0 @@
export default {
menu: {
title: "Menu",
ctrlBar: "Menu"
},
maps: {
title: "Maps",
ctrlBar: "Map-List"
},
markers: {
title: "Markers",
ctrlBar: "Marker-List"
},
settings: {
title: "settings"
},
goFullscreen: {
title: "Go Fullscreen"
},
resetCamera: {
title: "Reset Camera",
ctrlBar: "Reset Camera & Position"
},
updateMap: {
title: "Update Map",
description: "Clear Tile Cache"
},
lighting: {
title: "Lighting",
dayNightSwitch: {
ctrlBar: "Day/Night"
},
sunlight: "Sunlight",
ambientLight: "Ambient-Light"
},
resolution: {
title: "Resolution",
high: "High (SSAA, x2)",
normal: "Normal (Native, x1)",
low: "Low (Upscaling, x0.5)"
},
freeFlightControls: {
title: "Free-Flight Controls",
mouseSensitivity: "Mouse-Sensitivity",
invertMouseY: "Invert Mouse Y"
},
renderDistance: {
title: "Render Distance",
hiresLayer: "Hires layer",
lowersLayer: "Lowres layer"
},
theme: {
title: "Theme",
default: "Default (System/Browser)",
dark: "Dark",
light: "Light"
},
debug: {
title: "Debug"
},
resetAllSettings: {
title: "Reset All Settings"
},
players: {
title: "Players",
ctrlBar: "Player-List"
},
compass: {
ctrlBar: "Compass / Face North"
},
controls: {
perspective: {
title: "Perspective",
ctrlBar: "Perspective-View"
},
flatView: {
title: "Flat",
ctrlBar: "Orthographic/Flat-View",
},
freeFlight: {
title: "Free-Flight",
ctrlBar: "Free-Flight/Spectator Mode"
}
}
};

143
src/i18n/fallback.js Normal file
View File

@ -0,0 +1,143 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menu",
tooltip: "Menu"
},
maps: {
title: "Maps",
button: "Maps",
tooltip: "Map-List"
},
markers: {
title: "Markers",
button: "Markers",
tooltip: "Marker-List",
marker: "marker | markers",
markerSet: "marker-set | marker-sets"
},
settings: {
title: "Settings",
button: "Settings"
},
goFullscreen: {
button: "Go Fullscreen"
},
resetCamera: {
button: "Reset Camera",
tooltip: "Reset Camera & Position"
},
updateMap: {
button: "Update Map",
tooltip: "Clear Tile Cache"
},
lighting: {
title: "Lighting",
dayNightSwitch: {
tooltip: "Day/Night"
},
sunlight: "Sunlight",
ambientLight: "Ambient-Light"
},
resolution: {
title: "Resolution",
high: "High (SSAA, x2)",
normal: "Normal (Native, x1)",
low: "Low (Upscaling, x0.5)"
},
freeFlightControls: {
title: "Free-Flight Controls",
mouseSensitivity: "Mouse-Sensitivity",
invertMouseY: "Invert Mouse Y"
},
renderDistance: {
title: "Render Distance",
hiresLayer: "Hires layer",
lowersLayer: "Lowres layer"
},
theme: {
title: "Theme",
default: "Default (System/Browser)",
dark: "Dark",
light: "Light"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Reset All Settings"
},
players: {
title: "Players",
tooltip: "Player-List"
},
compass: {
tooltip: "Compass / Face North"
},
controls: {
perspective: {
button: "Perspective",
tooltip: "Perspective-View"
},
flatView: {
button: "Flat",
tooltip: "Orthographic / Flat-View",
},
freeFlight: {
button: "Free-Flight",
tooltip: "Free-Flight / Spectator Mode"
}
},
language: {
title: "Language",
},
blockTooltip: {
block: "Block",
position: "Position",
chunk: "Chunk",
region: {
region: "Region",
file: "File"
},
light: {
light: "Light",
sun: "Sun",
block: "Block",
}
},
info: {
title: "Info",
button: "Info",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Mouse-Controls:</h2>
<table>
<tr><th>move</th><td><kbd>left-click</kbd> + drag</td></tr>
<tr><th>zoom</th><td><kbd>mousewheel</kbd> (scroll)</td></tr>
<tr><th>rotate / tilt</th><td><kbd>right-click</kbd> + drag</td></tr>
</table>
</p>
<p>
<h2>Keyboard-Controls:</h2>
<table>
<tr><th>move</th><td><kbd>wasd</kbd> / <kbd>arrow-keys</kbd></td></tr>
<tr><th>zoom</th><td>Numpad: <kbd>+</kbd>/<kbd>-</kbd> or <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>rotate / tilt</th><td><kbd>Left-Alt</kbd> + <kbd>wasd</kbd> / <kbd>arrow-keys</kbd> or <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Touch-Controls:</h2>
<table>
<tr><th>move</th><td>touch + drag</td></tr>
<tr><th>zoom</th><td>touch with two fingers + pinch</td></tr>
<tr><th>rotate / tilt</th><td>touch with two fingers + rotate / move up/down</td></tr>
</table>
</p>
<br><hr>
<p>
This map has been generated with &#9829; using <a href="https://bluecolo.red/bluemap">BlueMap</a>.
</p>
`
}
};

View File

@ -1,12 +1,36 @@
import VueI18n from 'vue-i18n';
import en from './en';
import Vue from 'vue';
import fallback from './fallback';
VueI18n.prototype.setLanguage = async function(lang) {
if (!this.messages[lang]){
try {
let messages = {};
messages = (await import(/* webpackIgnore: true */ `../lang/${lang}.js`)).default;
this.setLocaleMessage(lang, messages);
this.locale = lang;
document.querySelector('html').setAttribute('lang', lang);
} catch (e) {
console.error(`Failed to load language '${lang}'!`, e);
}
}
}
VueI18n.prototype.loadLanguageSettings = async function() {
let settings = (await import(/* webpackIgnore: true */ "../lang/settings.js")).default;
this.languages = settings.languages;
this.setLanguage(settings.default);
};
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: 'en',
messages: { en }
locale: 'fallback',
fallbackLocale: 'fallback',
silentFallbackWarn: true,
messages: { fallback }
});
export default i18n;

View File

@ -35,6 +35,7 @@ import {MainMenu} from "@/js/MainMenu";
import {PopupMarker} from "@/js/PopupMarker";
import {MarkerSet} from "bluemap/src/markers/MarkerSet";
import {getCookie, round, setCookie} from "@/js/Utils";
import i18n from "../i18n";
export class BlueMapApp {
@ -129,15 +130,15 @@ export class BlueMapApp {
this.events.addEventListener("bluemapCameraMoved", this.cameraMoved);
this.events.addEventListener("bluemapMapInteraction", this.mapInteraction);
// load user settings
this.loadUserSettings();
// save user settings
this.saveUserSettings();
// start app update loop
if(this.updateLoop) clearTimeout(this.updateLoop);
this.updateLoop = setTimeout(this.update, 1000);
// load user settings
await this.loadUserSettings();
// save user settings
this.saveUserSettings();
}
update = async () => {
@ -192,6 +193,8 @@ export class BlueMapApp {
this.resetCamera();
}
}
this.updatePageAddress();
});
}
@ -210,6 +213,7 @@ export class BlueMapApp {
controls.controls = this.mapControls;
this.appState.controls.state = "perspective";
this.updatePageAddress();
}
/**
@ -348,7 +352,10 @@ export class BlueMapApp {
cm.tilt = MathUtils.lerp(startTilt, 0, ep);
}, transition, finished => {
this.mapControls.reset();
if (finished) cm.controls = this.mapControls;
if (finished){
cm.controls = this.mapControls;
this.updatePageAddress();
}
});
this.appState.controls.state = "perspective";
@ -378,7 +385,10 @@ export class BlueMapApp {
cm.tilt = MathUtils.lerp(startTilt, 0, ep);
}, transition, finished => {
this.mapControls.reset();
if (finished) cm.controls = this.mapControls;
if (finished){
cm.controls = this.mapControls;
this.updatePageAddress();
}
});
this.appState.controls.state = "flat";
@ -410,7 +420,10 @@ export class BlueMapApp {
cm.ortho = MathUtils.lerp(startOrtho, 0, Math.min(p * 2, 1));
cm.tilt = MathUtils.lerp(startTilt, 0, ep);
}, transition, finished => {
if (finished) cm.controls = this.freeFlightControls;
if (finished){
cm.controls = this.freeFlightControls;
this.updatePageAddress();
}
});
this.appState.controls.state = "free";
@ -460,7 +473,7 @@ export class BlueMapApp {
location.reload();
}
loadUserSettings(){
async loadUserSettings(){
if (!this.settings.useCookies) return;
if (this.loadUserSetting("resetSettings", false)) {
@ -479,6 +492,7 @@ export class BlueMapApp {
this.appState.controls.invertMouse = this.loadUserSetting("invertMouse", this.appState.controls.invertMouse);
this.updateControlsSettings();
this.setTheme(this.loadUserSetting("theme", this.appState.theme));
await i18n.setLanguage(this.loadUserSetting("lang", i18n.locale));
this.setDebug(this.loadUserSetting("debug", this.appState.debug));
alert(this.events, "Settings loaded!", "info");
@ -496,6 +510,7 @@ export class BlueMapApp {
this.saveUserSetting("mouseSensitivity", this.appState.controls.mouseSensitivity);
this.saveUserSetting("invertMouse", this.appState.controls.invertMouse);
this.saveUserSetting("theme", this.appState.theme);
this.saveUserSetting("lang", i18n.locale);
this.saveUserSetting("debug", this.appState.debug);
alert(this.events, "Settings saved!", "info");
@ -539,6 +554,10 @@ export class BlueMapApp {
}
history.replaceState(undefined, undefined, hash);
document.title = i18n.t("pageTitle", {
map: this.mapViewer.map ? this.mapViewer.map.data.name : "?"
});
}
loadPageAddress = async () => {

View File

@ -41,17 +41,26 @@ export class MainMenu {
return this.pageStack[this.pageStack.length - 1];
}
openPage(id = "root", title = i18n.t("menu.title"), data = {}) {
openPage(id = "root", title = () => i18n.t("menu.title"), data = {}) {
if (!this.isOpen){
this.pageStack.splice(0, this.pageStack.length);
this.isOpen = true;
}
this.pageStack.push({
id: id,
title: title,
...data
});
if (typeof title === "function"){
this.pageStack.push({
id: id,
get title(){ return title() },
...data
});
} else {
this.pageStack.push({
id: id,
title: title,
...data
});
}
}
closePage() {

View File

@ -26,6 +26,7 @@ import {Marker} from "bluemap/src/markers/Marker";
import {CSS2DObject} from "bluemap/src/util/CSS2DRenderer";
import {animate, htmlToElement} from "bluemap/src/util/Utils";
import {BoxGeometry, MeshBasicMaterial, Mesh, Vector2} from "three";
import i18n from "../i18n";
export class PopupMarker extends Marker {
@ -90,7 +91,7 @@ export class PopupMarker extends Marker {
if (isHires) {
this.element.innerHTML = `
<div class="group">
<div class="label">Block:</div>
<div class="label">${i18n.t("blockTooltip.block")}:</div>
<div class="content">
<div class="entry"><span class="label">x: </span><span class="value">${this.position.x}</span></div>
<div class="entry"><span class="label">y: </span><span class="value">${this.position.y}</span></div>
@ -101,7 +102,7 @@ export class PopupMarker extends Marker {
} else {
this.element.innerHTML = `
<div class="group">
<div class="label">Position:</div>
<div class="label">${i18n.t("blockTooltip.position")}:</div>
<div class="content">
<div class="entry"><span class="label">x: </span><span class="value">${this.position.x}</span></div>
<div class="entry"><span class="label">z: </span><span class="value">${this.position.z}</span></div>
@ -118,7 +119,7 @@ export class PopupMarker extends Marker {
this.element.innerHTML += `
<hr>
<div class="group">
<div class="label">Chunk:</div>
<div class="label">${i18n.t("blockTooltip.chunk")}:</div>
<div class="content">
<div class="entry"><span class="label">x: </span><span class="value">${chunkCoords.x}</span></div>
<div class="entry"><span class="label">y: </span><span class="value">${chunkCoords.y}</span></div>
@ -127,13 +128,13 @@ export class PopupMarker extends Marker {
</div>
<hr>
<div class="group">
<div class="label">Region:</div>
<div class="label">${i18n.t("blockTooltip.region.region")}:</div>
<div class="content">
<div class="entry"><span class="label">x: </span><span class="value">${regionCoords.x}</span></div>
<div class="entry"><span class="label">z: </span><span class="value">${regionCoords.y}</span></div>
</div>
<div class="content">
<div class="entry"><span class="label">File: </span><span class="value">${regionFile}</span></div>
<div class="entry"><span class="label">${i18n.t("blockTooltip.region.file")}: </span><span class="value">${regionFile}</span></div>
</div>
</div>
`;
@ -149,10 +150,10 @@ export class PopupMarker extends Marker {
this.element.innerHTML += `
<hr>
<div class="group">
<div class="label">Light:</div>
<div class="label">${i18n.t("blockTooltip.light.light")}:</div>
<div class="content">
<div class="entry"><span class="label">Sun: </span><span class="value">${sunlight}</span></div>
<div class="entry"><span class="label">Block: </span><span class="value">${blocklight}</span></div>
<div class="entry"><span class="label">${i18n.t("blockTooltip.light.sun")}: </span><span class="value">${sunlight}</span></div>
<div class="entry"><span class="label">${i18n.t("blockTooltip.light.block")}: </span><span class="value">${blocklight}</span></div>
</div>
</div>
`;

View File

@ -35,22 +35,23 @@ String.prototype.includesCI = function (val) {
// bluemap app
const bluemap = new BlueMapApp(document.getElementById("map-container"));
window.bluemap = bluemap;
// init vue
Vue.config.productionTip = false;
Object.defineProperty(Vue.prototype, '$bluemap', {
get () { return bluemap }
get() { return bluemap; }
});
let vue = new Vue({
const vue = new Vue({
i18n,
render: h => h(App)
}).$mount('#app');
// make bluemap accessible in console
window.bluemap = bluemap;
// load languages
i18n.loadLanguageSettings();
// load bluemap next tick (to let the assets load first)
vue.$nextTick(() => {
bluemap.load().catch(error => console.error(error));
});
});

View File

@ -51,6 +51,62 @@ body {
padding: 0;
}
h1, h2, h3, h4, h5, h6 {
font-weight: inherit;
font-size: inherit;
text-align: left;
margin: 1em 0 0.5em 0;
padding: 0;
}
h1, h2 {
position: relative;
font-size: 1.2em;
margin-left: 0;
margin-right: 0;
padding-left: 0.5em;
padding-bottom: 0.5em;
width: calc(100% - 0.5em);
overflow: hidden;
&:after {
position: absolute;
left: 0;
bottom: 0;
content: '';
width: 100%;
height: 1px;
background-color: var(--theme-bg-light);
}
}
h1 {
width: 100%;
text-align: center;
padding-left: 0;
}
p {
margin: 0.5em;
padding: 0;
}
a {
color: inherit;
text-decoration: underline;
}
kbd {
background-color: var(--theme-bg-light);
border-radius: 0.2em;
margin: 0;
padding: 0 0.2em;
}
// normalize input fields
input {
display: inline-block;