mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-03 13:19:16 -05:00
working on locale (not yet fully working)
This commit is contained in:
@@ -1,12 +1,15 @@
|
|||||||
{% load django_vite %}
|
{% load django_vite %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
|
|
||||||
{% load theming_tags %}
|
{% load theming_tags %}
|
||||||
{% load custom_tags %}
|
{% load custom_tags %}
|
||||||
|
|
||||||
{% theme_values request as theme_values %}
|
{% theme_values request as theme_values %}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="{{ LANGUAGE_CODE }}">
|
||||||
<head>
|
<head>
|
||||||
<title>Tandoor</title>
|
<title>Tandoor</title>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
</v-list>
|
</v-list>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
</v-avatar>
|
</v-avatar>
|
||||||
|
Test: {{$t('No_Results')}}
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
|
|
||||||
<v-main>
|
<v-main>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import {createApp} from "vue";
|
import {createApp} from "vue";
|
||||||
import {createRouter, createWebHashHistory} from 'vue-router'
|
import {createRouter, createWebHashHistory} from 'vue-router'
|
||||||
import {createPinia} from 'pinia'
|
import {createPinia} from 'pinia'
|
||||||
|
import en from '../../locales/en.json'
|
||||||
|
import de from '../../locales/de.json'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import App from './Tandoor.vue'
|
import App from './Tandoor.vue'
|
||||||
|
|
||||||
@@ -15,6 +17,8 @@ import RecipeEditPage from "@/pages/RecipeEditPage.vue";
|
|||||||
import MealPlanPage from "@/pages/MealPlanPage.vue";
|
import MealPlanPage from "@/pages/MealPlanPage.vue";
|
||||||
import SearchPage from "@/pages/SearchPage.vue";
|
import SearchPage from "@/pages/SearchPage.vue";
|
||||||
import TestPage from "@/pages/TestPage.vue";
|
import TestPage from "@/pages/TestPage.vue";
|
||||||
|
import {createI18n} from "vue-i18n";
|
||||||
|
import {getLocale, loadLocaleMessages, setI18nLanguage, setupI18n, SUPPORT_LOCALES} from "@/i18n";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{path: '/', component: StartPage, name: 'view_home'},
|
{path: '/', component: StartPage, name: 'view_home'},
|
||||||
@@ -33,12 +37,29 @@ const router = createRouter({
|
|||||||
routes,
|
routes,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let locale = document.querySelector('html')!.getAttribute('lang')
|
||||||
|
if (locale == null || !SUPPORT_LOCALES.includes(locale)) {
|
||||||
|
console.log('falling back to en because ', locale, ' is not supported as a locale')
|
||||||
|
locale = 'en'
|
||||||
|
}
|
||||||
|
const localeMessages = await import((`../../locales/${locale}.json`))
|
||||||
|
console.log(localeMessages, de)
|
||||||
|
const i18n = setupI18n({
|
||||||
|
legacy: false,
|
||||||
|
locale: locale,
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
messages: {
|
||||||
|
en, de
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(createPinia())
|
app.use(createPinia())
|
||||||
app.use(vuetify)
|
app.use(vuetify)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.use(luxonPlugin)
|
app.use(i18n)
|
||||||
app.use(mavonEditor) // TODO only use on pages that need it
|
app.use(mavonEditor) // TODO only use on pages that need it
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|||||||
@@ -55,10 +55,14 @@ const props = defineProps({
|
|||||||
|
|
||||||
allowCreate: {type: Boolean, default: false},
|
allowCreate: {type: Boolean, default: false},
|
||||||
|
|
||||||
|
placeholder: {type: String, default: undefined},
|
||||||
|
noOptionsText: {type: String, default: undefined},
|
||||||
|
noResultsText: {type: String, default: undefined},
|
||||||
|
|
||||||
// not verified
|
// not verified
|
||||||
search_on_load: {type: Boolean, default: false},
|
search_on_load: {type: Boolean, default: false},
|
||||||
|
|
||||||
placeholder: {type: String, default: undefined},
|
|
||||||
parent_variable: {type: String, default: undefined},
|
parent_variable: {type: String, default: undefined},
|
||||||
|
|
||||||
sticky_options: {
|
sticky_options: {
|
||||||
|
|||||||
100
vue3/src/i18n.ts
Normal file
100
vue3/src/i18n.ts
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import {nextTick, isRef} from 'vue'
|
||||||
|
import {createI18n} from 'vue-i18n'
|
||||||
|
|
||||||
|
import type {
|
||||||
|
I18n,
|
||||||
|
I18nOptions,
|
||||||
|
Locale,
|
||||||
|
VueI18n,
|
||||||
|
Composer,
|
||||||
|
I18nMode
|
||||||
|
} from 'vue-i18n'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lazy loading of translation, resources:
|
||||||
|
* https://vue-i18n.intlify.dev/guide/advanced/lazy.html
|
||||||
|
* https://github.com/intlify/vue-i18n/blob/master/examples/lazy-loading/vite/src/i18n.ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO not sure why/if this is needed, comment out for now and see if anything breaks
|
||||||
|
export const SUPPORT_LOCALES = getSupportedLocales()
|
||||||
|
|
||||||
|
function getSupportedLocales() {
|
||||||
|
let supportedLocales: string[] = []
|
||||||
|
let localeFiles = import.meta.glob('@/locales/*.json');
|
||||||
|
for (const path in localeFiles) {
|
||||||
|
supportedLocales.push(path.split('/').slice(-1)[0].split('.')[0]);
|
||||||
|
}
|
||||||
|
return supportedLocales
|
||||||
|
}
|
||||||
|
|
||||||
|
function isComposer(
|
||||||
|
instance: VueI18n | Composer,
|
||||||
|
mode: I18nMode
|
||||||
|
): instance is Composer {
|
||||||
|
return mode === 'composition' && isRef(instance.locale)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setupI18n2() {
|
||||||
|
let locale = document.querySelector('html')!.getAttribute('lang')
|
||||||
|
if (locale == null || !SUPPORT_LOCALES.includes(locale)) {
|
||||||
|
locale = 'en'
|
||||||
|
}
|
||||||
|
|
||||||
|
const i18n = createI18n({locale: locale})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return i18n
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getLocale(i18n: I18n): string {
|
||||||
|
if (isComposer(i18n.global, i18n.mode)) {
|
||||||
|
return i18n.global.locale.value
|
||||||
|
} else {
|
||||||
|
return i18n.global.locale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setLocale(i18n: I18n, locale: Locale): void {
|
||||||
|
if (isComposer(i18n.global, i18n.mode)) {
|
||||||
|
i18n.global.locale.value = locale
|
||||||
|
} else {
|
||||||
|
i18n.global.locale = locale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setupI18n(options: I18nOptions = {locale: 'en'}): I18n {
|
||||||
|
const i18n = createI18n(options)
|
||||||
|
setI18nLanguage(i18n, options.locale!)
|
||||||
|
return i18n
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setI18nLanguage(i18n: I18n, locale: Locale): void {
|
||||||
|
setLocale(i18n, locale)
|
||||||
|
/**
|
||||||
|
* NOTE:
|
||||||
|
* If you need to specify the language setting for headers, such as the `fetch` API, set it here.
|
||||||
|
* The following is an example for axios.
|
||||||
|
*
|
||||||
|
* axios.defaults.headers.common['Accept-Language'] = locale
|
||||||
|
*/
|
||||||
|
|
||||||
|
// should be done by django
|
||||||
|
// document.querySelector('html')!.setAttribute('lang', locale)
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const getResourceMessages = (r: any) => r.default || r
|
||||||
|
|
||||||
|
export async function loadLocaleMessages(i18n: I18n, locale: Locale) {
|
||||||
|
// load locale messages
|
||||||
|
const messages = await import(`./locales/${locale}.json`).then(
|
||||||
|
getResourceMessages
|
||||||
|
)
|
||||||
|
|
||||||
|
// set locale and locale message
|
||||||
|
i18n.global.setLocaleMessage(locale, messages)
|
||||||
|
|
||||||
|
return nextTick()
|
||||||
|
}
|
||||||
1
vue3/src/locales
Symbolic link
1
vue3/src/locales
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../vue/src/locales/
|
||||||
Reference in New Issue
Block a user