Improve locale detection

This commit is contained in:
Matt Isenhower 2022-10-12 17:40:55 -07:00
parent 97c483f7c6
commit 007fe5d906
3 changed files with 74 additions and 14 deletions

61
src/common/i18n.js Normal file
View File

@ -0,0 +1,61 @@
import { createI18n } from 'vue-i18n'
import languages from '../assets/i18n'
const LANGUAGE_KEY = 'lang';
export const locales = [
{ code: 'en-US', flag: '🇺🇸', name: 'English' }, // TODO: Change to "English (US)" when adding en-GB
{ code: 'fr-FR', flag: '🇫🇷', name: 'Français' },
];
let i18n = null;
export function initializeI18n() {
if (!i18n) {
i18n = createI18n({
locale: currentLocale().code,
fallbackLocale: 'en-US',
messages: { ...languages },
});
// Listen for local storage changes
window.addEventListener('storage', reload);
}
return i18n;
}
function reload() {
i18n.global.locale.value = currentLocale().code;
}
function currentLocale() {
return preferredLocale() || detectLocale();
}
function preferredLocale() {
let code = localStorage && localStorage.getItem(LANGUAGE_KEY);
return locales.find(l => l.code === code);
}
export function setPreferredLocale(value) {
localStorage.setItem(LANGUAGE_KEY, value);
reload();
}
function detectLocale() {
let languages = window.navigator.languages || [window.navigator.language];
// Try to find a matching language
for (let language of languages) {
let locale = locales.find(l => l.code.startsWith(language) || l.code.startsWith(language.substring(0, 2)));
if (locale) {
return locale;
}
}
// Fall back to en-US
return locales[0];
}

View File

@ -1,16 +1,20 @@
<template>
<select @change="onLanguageChange" v-model="$i18n.locale" class="bg-transparent text-zinc-300 cursor-pointer">
<template v-for="locale in $i18n.availableLocales" :key="locale">
<option :value="locale">{{ $t('locales.' + locale) }}</option>
<select v-model="currentLanguage" class="bg-transparent text-zinc-300 cursor-pointer">
<template v-for="locale in locales" :key="locale.code">
<option :value="locale.code">{{ locale.flag }} {{ locale.name }}</option>
</template>
</select>
</template>
<script setup>
import { computed } from "vue";
import { useI18n } from "vue-i18n"
const i18n = useI18n()
import { locales, setPreferredLocale } from '@/common/i18n';
const onLanguageChange = () => {
localStorage.setItem('lang', i18n.locale.value)
}
const i18n = useI18n();
const currentLanguage = computed({
get() { return i18n.locale.value; },
set(value) { setPreferredLocale(value); },
});
</script>

View File

@ -1,17 +1,12 @@
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'
import { createPinia } from 'pinia'
import languages from './assets/i18n'
import { initializeI18n } from './common/i18n'
import App from './App.vue'
import router from './router'
const i18n = createI18n({
locale: localStorage.getItem('lang') || navigator.language,
fallbackLocale: 'en-US',
messages: Object.assign(languages)
})
const i18n = initializeI18n();
const app = createApp(App)