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
|
||||
|
||||
Documentation
|
||||
- [ ] V0.1.0 Release Notes
|
||||
- [ ] Nextcloud Migration How To
|
||||
- [ ] New Docker Setup with Sqlite
|
||||
- [ ] Update Env Variables
|
||||
- [ ] New Roadmap / Milestones
|
||||
|
||||
Frontend
|
||||
- [x] Prep / Cook / Total Time Indicator + Editor
|
||||
- [ ] No Meal Today Page instead of Null
|
||||
- [ ] Recipe Print Page
|
||||
- [ ] Recipe Editor Data Validation Client Side
|
||||
|
@ -32,12 +24,7 @@ Frontend
|
|||
- [ ] Advanced Search Page, draft started
|
||||
- [ ] Filter by Category
|
||||
- [ ] Filter by Tags
|
||||
- [ ] Search Bar 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
|
||||
- [ ] Search Bar Results Redesign
|
||||
|
||||
Backend
|
||||
- [ ] Database Import
|
||||
|
@ -46,11 +33,10 @@ Backend
|
|||
- [ ] Meal Plans
|
||||
- [x] Settings
|
||||
- [x] Themes
|
||||
- [x] Remove Print / Debug Code
|
||||
- [ ] Remove Print / Debug Code
|
||||
- [ ] Support how to sections and how to steps
|
||||
- [ ] Recipe request by category/tags
|
||||
|
||||
|
||||
SQL
|
||||
- [ ] 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
|
||||
- [ ] Import Recipes Force/Rebase options
|
||||
- [x] Upload .zip file
|
||||
- [ ] Improved Color Picker
|
||||
- [x] Improved Color Picker
|
||||
- [x] Meal Plan redesign
|
||||
### Backend
|
||||
- [ ] PostgreSQL Support
|
||||
|
|
|
@ -58,6 +58,7 @@ export default {
|
|||
mounted() {
|
||||
this.$store.dispatch("initTheme")
|
||||
this.$store.dispatch("requestRecentRecipes")
|
||||
this.$store.dispatch("initLang")
|
||||
this.darkModeSystemCheck()
|
||||
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>
|
||||
<div>
|
||||
<!-- <v-btn block :color="value" @click="dialog = true">
|
||||
{{ buttonText }}
|
||||
</v-btn>
|
||||
<v-dialog v-model="dialog" width="400">
|
||||
<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
|
||||
>
|
||||
<div class="text-center">
|
||||
<h3>{{ buttonText }}</h3>
|
||||
</div>
|
||||
<v-text-field v-model="color" hide-details class="ma-0 pa-0" solo>
|
||||
<template v-slot:append>
|
||||
<v-menu
|
||||
v-model="menu"
|
||||
|
@ -52,7 +17,7 @@
|
|||
</template>
|
||||
<v-card>
|
||||
<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>
|
||||
</v-menu>
|
||||
|
@ -71,7 +36,7 @@ export default {
|
|||
return {
|
||||
dialog: false,
|
||||
swatches: false,
|
||||
color: "#1976D2FF",
|
||||
color: "#1976D2",
|
||||
mask: "!#XXXXXXXX",
|
||||
menu: false,
|
||||
};
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
import Vue from 'vue'
|
||||
import VueI18n from 'vue-i18n'
|
||||
import Vue from "vue";
|
||||
import VueI18n from "vue-i18n";
|
||||
|
||||
Vue.use(VueI18n)
|
||||
Vue.use(VueI18n);
|
||||
|
||||
function loadLocaleMessages () {
|
||||
const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
|
||||
const messages = {}
|
||||
function loadLocaleMessages() {
|
||||
const locales = require.context(
|
||||
"./locales",
|
||||
true,
|
||||
/[A-Za-z0-9-_,\s]+\.json$/i
|
||||
);
|
||||
const messages = {};
|
||||
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) {
|
||||
const locale = matched[1]
|
||||
messages[locale] = locales(key)
|
||||
const locale = matched[1];
|
||||
messages[locale] = locales(key);
|
||||
}
|
||||
})
|
||||
return messages
|
||||
});
|
||||
return messages;
|
||||
}
|
||||
|
||||
export default new VueI18n({
|
||||
locale: process.env.VUE_APP_I18N_LOCALE || 'en',
|
||||
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
|
||||
messages: loadLocaleMessages()
|
||||
})
|
||||
locale: "en",
|
||||
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
|
||||
messages: loadLocaleMessages(),
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ import vuetify from "./plugins/vuetify";
|
|||
import store from "./store/store";
|
||||
import VueRouter from "vue-router";
|
||||
import { routes } from "./routes";
|
||||
import i18n from './i18n'
|
||||
import i18n from "./i18n";
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
Vue.use(VueRouter);
|
||||
|
@ -14,12 +14,13 @@ const router = new VueRouter({
|
|||
mode: process.env.NODE_ENV === "production" ? "history" : "hash",
|
||||
});
|
||||
|
||||
|
||||
new Vue({
|
||||
vuetify,
|
||||
store,
|
||||
router,
|
||||
i18n,
|
||||
render: (h) => h(App)
|
||||
render: h => h(App),
|
||||
}).$mount("#app");
|
||||
|
||||
// Truncate
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
"
|
||||
>
|
||||
</v-alert>
|
||||
<Theme />
|
||||
<General />
|
||||
<Theme class="mt-2" />
|
||||
<Backup class="mt-2" />
|
||||
<Webhooks class="mt-2" />
|
||||
<Migration class="mt-2" />
|
||||
|
@ -39,6 +40,7 @@
|
|||
|
||||
<script>
|
||||
import Backup from "../components/Settings/Backup";
|
||||
import General from "../components/Settings/General";
|
||||
import Webhooks from "../components/Settings/Webhook";
|
||||
import Theme from "../components/Settings/Theme";
|
||||
import Migration from "../components/Settings/Migration";
|
||||
|
@ -50,6 +52,7 @@ export default {
|
|||
Webhooks,
|
||||
Theme,
|
||||
Migration,
|
||||
General,
|
||||
},
|
||||
data() {
|
||||
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 createPersistedState from "vuex-persistedstate";
|
||||
import userSettings from "./modules/userSettings";
|
||||
import language from "./modules/language";
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
const store = new Vuex.Store({
|
||||
plugins: [
|
||||
createPersistedState({
|
||||
paths: ["userSettings"],
|
||||
paths: ["userSettings", "language"],
|
||||
}),
|
||||
],
|
||||
modules: {
|
||||
userSettings,
|
||||
language,
|
||||
},
|
||||
state: {
|
||||
// Snackbar
|
||||
|
@ -59,11 +61,11 @@ const store = new Vuex.Store({
|
|||
|
||||
getters: {
|
||||
//
|
||||
getSnackText: (state) => state.snackText,
|
||||
getSnackActive: (state) => state.snackActive,
|
||||
getSnackType: (state) => state.snackType,
|
||||
getSnackText: state => state.snackText,
|
||||
getSnackActive: state => state.snackActive,
|
||||
getSnackType: state => state.snackType,
|
||||
|
||||
getRecentRecipes: (state) => state.recentRecipes,
|
||||
getRecentRecipes: state => state.recentRecipes,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue