mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 06:23:34 -07:00
added UI language selection
This commit is contained in:
parent
ebf437c15a
commit
2989fc9bd7
10 changed files with 137 additions and 81 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
},
|
},
|
||||||
|
|
50
frontend/src/components/Settings/General/index.vue
Normal file
50
frontend/src/components/Settings/General/index.vue
Normal 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>
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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(),
|
||||||
})
|
});
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
44
frontend/src/store/modules/language.js
Normal file
44
frontend/src/store/modules/language.js
Normal 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,
|
||||||
|
};
|
|
@ -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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue