added UI language selection

This commit is contained in:
Hayden 2021-01-23 19:10:20 -09:00
commit 2989fc9bd7
10 changed files with 137 additions and 81 deletions

View file

@ -16,15 +16,7 @@ Don't forget to [join the Discord](https://discord.gg/R6QDyJgbD2)!
# Todo's # Todo's
Documentation
- [ ] V0.1.0 Release Notes
- [ ] Nextcloud Migration How To
- [ ] New Docker Setup with Sqlite
- [ ] Update Env Variables
- [ ] New Roadmap / Milestones
Frontend Frontend
- [x] Prep / Cook / Total Time Indicator + Editor
- [ ] No Meal Today Page instead of Null - [ ] No Meal Today Page instead of Null
- [ ] Recipe Print Page - [ ] Recipe Print Page
- [ ] Recipe Editor Data Validation Client Side - [ ] Recipe Editor Data Validation Client Side
@ -32,12 +24,7 @@ Frontend
- [ ] Advanced Search Page, draft started - [ ] Advanced Search Page, draft started
- [ ] Filter by Category - [ ] Filter by Category
- [ ] Filter by Tags - [ ] Filter by Tags
- [ ] Search Bar redesign - [ ] Search Bar Results Redesign
- [x] Initial
- [ ] Results redesign
- [x] Replace Backups card with something like Home Assistant
- [x] Replace import card with something like Home Assistant
- [x] Select which imports to do
Backend Backend
- [ ] Database Import - [ ] Database Import
@ -46,11 +33,10 @@ Backend
- [ ] Meal Plans - [ ] Meal Plans
- [x] Settings - [x] Settings
- [x] Themes - [x] Themes
- [x] Remove Print / Debug Code - [ ] Remove Print / Debug Code
- [ ] Support how to sections and how to steps - [ ] Support how to sections and how to steps
- [ ] Recipe request by category/tags - [ ] Recipe request by category/tags
SQL SQL
- [ ] Setup Database Migrations - [ ] Setup Database Migrations

View file

@ -38,7 +38,7 @@ Feature placement is not set in stone. This is much more of a guideline than any
- [ ] Additional Backup / Import Features - [ ] Additional Backup / Import Features
- [ ] Import Recipes Force/Rebase options - [ ] Import Recipes Force/Rebase options
- [x] Upload .zip file - [x] Upload .zip file
- [ ] Improved Color Picker - [x] Improved Color Picker
- [x] Meal Plan redesign - [x] Meal Plan redesign
### Backend ### Backend
- [ ] PostgreSQL Support - [ ] PostgreSQL Support

View file

@ -58,6 +58,7 @@ export default {
mounted() { mounted() {
this.$store.dispatch("initTheme") this.$store.dispatch("initTheme")
this.$store.dispatch("requestRecentRecipes") this.$store.dispatch("requestRecentRecipes")
this.$store.dispatch("initLang")
this.darkModeSystemCheck() this.darkModeSystemCheck()
this.darkModeAddEventListener() this.darkModeAddEventListener()
}, },

View file

@ -0,0 +1,50 @@
<template>
<v-card>
<v-card-title> General Settings </v-card-title>
<v-divider></v-divider>
<v-card-text>
<v-row>
<v-col>
<v-select
v-model="selectedLang"
:items="langOptions"
item-text="name"
item-value="value"
label="Language"
>
</v-select>
</v-col>
<v-spacer></v-spacer>
<v-spacer></v-spacer>
</v-row>
</v-card-text>
</v-card>
</template>
<script>
export default {
data() {
return {
langOptions: [],
selectedLang: "en",
};
},
mounted() {
this.getOptions();
},
watch: {
selectedLang() {
this.$store.commit("setLang", this.selectedLang);
},
},
methods: {
getOptions() {
this.langOptions = this.$store.getters.getAllLangs;
this.selectedLang = this.$store.getters.getActiveLang;
},
},
};
</script>
<style>
</style>

View file

@ -1,44 +1,9 @@
<template> <template>
<div> <div>
<!-- <v-btn block :color="value" @click="dialog = true"> <div class="text-center">
{{ buttonText }} <h3>{{ buttonText }}</h3>
</v-btn> </div>
<v-dialog v-model="dialog" width="400"> <v-text-field v-model="color" hide-details class="ma-0 pa-0" solo>
<v-card>
<v-card-title> {{ buttonText }} {{$t('settings.color')}} </v-card-title>
<v-card-text>
<v-text-field v-model="color"> </v-text-field>
<v-row>
<v-col></v-col>
<v-col>
<v-color-picker
dot-size="28"
hide-inputs
hide-mode-switch
mode="hexa"
:show-swatches="swatches"
swatches-max-height="300"
v-model="color"
@change="updateColor"
></v-color-picker>
</v-col>
<v-col></v-col>
</v-row>
</v-card-text>
<v-card-actions>
<v-btn text @click="toggleSwatches"> {{$t('settings.swatches')}} </v-btn>
<v-btn text @click="dialog = false"> {{$t('general.select')}} </v-btn>
</v-card-actions>
</v-card>
</v-dialog> -->
<v-text-field
v-model="value"
v-mask="mask"
hide-details
class="ma-0 pa-0"
solo
>
<template v-slot:append> <template v-slot:append>
<v-menu <v-menu
v-model="menu" v-model="menu"
@ -52,7 +17,7 @@
</template> </template>
<v-card> <v-card>
<v-card-text class="pa-0"> <v-card-text class="pa-0">
<v-color-picker v-model="value" flat show-swatches /> <v-color-picker v-model="color" flat show-swatches />
</v-card-text> </v-card-text>
</v-card> </v-card>
</v-menu> </v-menu>
@ -71,7 +36,7 @@ export default {
return { return {
dialog: false, dialog: false,
swatches: false, swatches: false,
color: "#1976D2FF", color: "#1976D2",
mask: "!#XXXXXXXX", mask: "!#XXXXXXXX",
menu: false, menu: false,
}; };

View file

@ -1,23 +1,27 @@
import Vue from 'vue' import Vue from "vue";
import VueI18n from 'vue-i18n' import VueI18n from "vue-i18n";
Vue.use(VueI18n) Vue.use(VueI18n);
function loadLocaleMessages () { function loadLocaleMessages() {
const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i) const locales = require.context(
const messages = {} "./locales",
true,
/[A-Za-z0-9-_,\s]+\.json$/i
);
const messages = {};
locales.keys().forEach(key => { locales.keys().forEach(key => {
const matched = key.match(/([A-Za-z0-9-_]+)\./i) const matched = key.match(/([A-Za-z0-9-_]+)\./i);
if (matched && matched.length > 1) { if (matched && matched.length > 1) {
const locale = matched[1] const locale = matched[1];
messages[locale] = locales(key) messages[locale] = locales(key);
} }
}) });
return messages return messages;
} }
export default new VueI18n({ export default new VueI18n({
locale: process.env.VUE_APP_I18N_LOCALE || 'en', locale: "en",
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en', fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
messages: loadLocaleMessages() messages: loadLocaleMessages(),
}) });

View file

@ -4,7 +4,7 @@ import vuetify from "./plugins/vuetify";
import store from "./store/store"; import store from "./store/store";
import VueRouter from "vue-router"; import VueRouter from "vue-router";
import { routes } from "./routes"; import { routes } from "./routes";
import i18n from './i18n' import i18n from "./i18n";
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.use(VueRouter); Vue.use(VueRouter);
@ -14,12 +14,13 @@ const router = new VueRouter({
mode: process.env.NODE_ENV === "production" ? "history" : "hash", mode: process.env.NODE_ENV === "production" ? "history" : "hash",
}); });
new Vue({ new Vue({
vuetify, vuetify,
store, store,
router, router,
i18n, i18n,
render: (h) => h(App) render: h => h(App),
}).$mount("#app"); }).$mount("#app");
// Truncate // Truncate

View file

@ -13,7 +13,8 @@
" "
> >
</v-alert> </v-alert>
<Theme /> <General />
<Theme class="mt-2" />
<Backup class="mt-2" /> <Backup class="mt-2" />
<Webhooks class="mt-2" /> <Webhooks class="mt-2" />
<Migration class="mt-2" /> <Migration class="mt-2" />
@ -39,6 +40,7 @@
<script> <script>
import Backup from "../components/Settings/Backup"; import Backup from "../components/Settings/Backup";
import General from "../components/Settings/General";
import Webhooks from "../components/Settings/Webhook"; import Webhooks from "../components/Settings/Webhook";
import Theme from "../components/Settings/Theme"; import Theme from "../components/Settings/Theme";
import Migration from "../components/Settings/Migration"; import Migration from "../components/Settings/Migration";
@ -50,6 +52,7 @@ export default {
Webhooks, Webhooks,
Theme, Theme,
Migration, Migration,
General,
}, },
data() { data() {
return { return {

View file

@ -0,0 +1,44 @@
import VueI18n from "../../i18n";
const state = {
lang: "en",
allLangs: [
{
name: "English",
value: "en",
},
{
name: "Dutch",
value: "da",
},
{
name: "French",
value: "fr",
},
],
};
const mutations = {
setLang(state, payload) {
VueI18n.locale = payload;
state.lang = payload;
},
};
const actions = {
initLang({ getters }) {
VueI18n.locale = getters.getActiveLang;
},
};
const getters = {
getActiveLang: (state) => state.lang,
getAllLangs: (state) => state.allLangs,
};
export default {
state,
mutations,
actions,
getters,
};

View file

@ -3,17 +3,19 @@ import Vuex from "vuex";
import api from "../api"; import api from "../api";
import createPersistedState from "vuex-persistedstate"; import createPersistedState from "vuex-persistedstate";
import userSettings from "./modules/userSettings"; import userSettings from "./modules/userSettings";
import language from "./modules/language";
Vue.use(Vuex); Vue.use(Vuex);
const store = new Vuex.Store({ const store = new Vuex.Store({
plugins: [ plugins: [
createPersistedState({ createPersistedState({
paths: ["userSettings"], paths: ["userSettings", "language"],
}), }),
], ],
modules: { modules: {
userSettings, userSettings,
language,
}, },
state: { state: {
// Snackbar // Snackbar
@ -59,11 +61,11 @@ const store = new Vuex.Store({
getters: { getters: {
// //
getSnackText: (state) => state.snackText, getSnackText: state => state.snackText,
getSnackActive: (state) => state.snackActive, getSnackActive: state => state.snackActive,
getSnackType: (state) => state.snackType, getSnackType: state => state.snackType,
getRecentRecipes: (state) => state.recentRecipes, getRecentRecipes: state => state.recentRecipes,
}, },
}); });