✨ Add i18n support
This commit is contained in:
@@ -1,35 +1,59 @@
|
||||
<script setup lang="ts">
|
||||
import {useEditorStore} from '@/stores/editorStore';
|
||||
import {useConfigStore} from '@/stores/configStore';
|
||||
import {useLogStore} from '@/stores/logStore';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { ref } from 'vue';
|
||||
import {SUPPORTED_LOCALES, setLocale, SupportedLocaleType} from '@/i18n';
|
||||
|
||||
const editorStore = useEditorStore();
|
||||
const configStore = useConfigStore();
|
||||
const logStore = useLogStore();
|
||||
const { t, locale } = useI18n();
|
||||
|
||||
// 语言下拉菜单
|
||||
const showLanguageMenu = ref(false);
|
||||
|
||||
// 切换语言
|
||||
const changeLanguage = (localeCode: SupportedLocaleType) => {
|
||||
setLocale(localeCode);
|
||||
showLanguageMenu.value = false;
|
||||
};
|
||||
|
||||
// 切换语言菜单显示
|
||||
const toggleLanguageMenu = () => {
|
||||
showLanguageMenu.value = !showLanguageMenu.value;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="toolbar-container">
|
||||
<div class="statistics">
|
||||
<span class="stat-item" title="行数">Ln: <span class="stat-value">{{
|
||||
<span class="stat-item" :title="t('toolbar.editor.lines')">{{ t('toolbar.editor.lines') }}: <span class="stat-value">{{
|
||||
editorStore.documentStats.lines
|
||||
}}</span></span>
|
||||
<span class="stat-item" title="字符数">Ch: <span class="stat-value">{{
|
||||
<span class="stat-item" :title="t('toolbar.editor.characters')">{{ t('toolbar.editor.characters') }}: <span class="stat-value">{{
|
||||
editorStore.documentStats.characters
|
||||
}}</span></span>
|
||||
<span class="stat-item" title="选中字符数" v-if="editorStore.documentStats.selectedCharacters > 0">
|
||||
Sel: <span class="stat-value">{{ editorStore.documentStats.selectedCharacters }}</span>
|
||||
<span class="stat-item" :title="t('toolbar.editor.selected')" v-if="editorStore.documentStats.selectedCharacters > 0">
|
||||
{{ t('toolbar.editor.selected') }}: <span class="stat-value">{{ editorStore.documentStats.selectedCharacters }}</span>
|
||||
</span>
|
||||
<span v-if="logStore.showLog && logStore.latestLog" class="log-item" :class="'log-' + logStore.latestLog.level"
|
||||
@click="logStore.hideCurrentLog()">
|
||||
{{ logStore.latestLog.message }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<span class="font-size" title="字体大小 (Ctrl+滚轮调整)" @click="configStore.resetFontSize">
|
||||
<span class="font-size" :title="t('toolbar.fontSizeTooltip')" @click="configStore.resetFontSize">
|
||||
{{ configStore.config.fontSize }}px
|
||||
</span>
|
||||
<span class="tab-settings">
|
||||
<label title="启用Tab键缩进" class="tab-toggle">
|
||||
<label :title="t('toolbar.tabLabel')" class="tab-toggle">
|
||||
<input type="checkbox" :checked="configStore.config.enableTabIndent" @change="configStore.toggleTabIndent"/>
|
||||
<span>Tab</span>
|
||||
<span>{{ t('toolbar.tabLabel') }}</span>
|
||||
</label>
|
||||
<span class="tab-type" title="Tab类型切换" @click="configStore.toggleTabType">
|
||||
{{ configStore.config.tabType === 'spaces' ? '空格' : '制表符' }}
|
||||
<span class="tab-type" :title="t('toolbar.tabType.' + (configStore.config.tabType === 'spaces' ? 'spaces' : 'tab'))" @click="configStore.toggleTabType">
|
||||
{{ t('toolbar.tabType.' + (configStore.config.tabType === 'spaces' ? 'spaces' : 'tab')) }}
|
||||
</span>
|
||||
<span class="tab-size" title="Tab大小" v-if="configStore.config.tabType === 'spaces'">
|
||||
<button class="tab-btn" @click="configStore.decreaseTabSize" :disabled="configStore.config.tabSize <= configStore.MIN_TAB_SIZE">-</button>
|
||||
@@ -37,8 +61,28 @@ const configStore = useConfigStore();
|
||||
<button class="tab-btn" @click="configStore.increaseTabSize" :disabled="configStore.config.tabSize >= configStore.MAX_TAB_SIZE">+</button>
|
||||
</span>
|
||||
</span>
|
||||
<span class="encoding">{{ configStore.config.encoding }}</span>
|
||||
<button class="settings-btn">
|
||||
<span class="encoding">{{ t('toolbar.encoding') }}</span>
|
||||
|
||||
<!-- 语言切换按钮 -->
|
||||
<div class="language-selector">
|
||||
<button class="language-btn" @click="toggleLanguageMenu">
|
||||
{{ locale }}
|
||||
<span class="arrow-up">▲</span>
|
||||
</button>
|
||||
<div class="language-menu" v-if="showLanguageMenu">
|
||||
<div
|
||||
v-for="lang in SUPPORTED_LOCALES"
|
||||
:key="lang.code"
|
||||
class="language-option"
|
||||
:class="{ active: locale === lang.code }"
|
||||
@click="changeLanguage(lang.code)"
|
||||
>
|
||||
{{ t(`languages.${lang.code}`) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="settings-btn" :title="t('toolbar.settings')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="3"></circle>
|
||||
@@ -61,6 +105,7 @@ const configStore = useConfigStore();
|
||||
height: 28px;
|
||||
font-size: 12px;
|
||||
border-top: 1px solid var(--border-color);
|
||||
user-select: none;
|
||||
|
||||
.statistics {
|
||||
display: flex;
|
||||
@@ -73,6 +118,24 @@ const configStore = useConfigStore();
|
||||
color: #e0e0e0;
|
||||
}
|
||||
}
|
||||
|
||||
.log-item {
|
||||
cursor: default;
|
||||
font-size: 12px;
|
||||
transition: opacity 0.3s ease;
|
||||
|
||||
&.log-info {
|
||||
color: rgba(177, 176, 176, 0.8);
|
||||
}
|
||||
|
||||
&.log-warning {
|
||||
color: rgba(240, 230, 140, 0.8);
|
||||
}
|
||||
|
||||
&.log-error {
|
||||
color: rgba(255, 107, 107, 0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
@@ -142,6 +205,61 @@ const configStore = useConfigStore();
|
||||
color: var(--text-muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* 语言切换样式 */
|
||||
.language-selector {
|
||||
position: relative;
|
||||
|
||||
.language-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
font-size: 11px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.arrow-up {
|
||||
font-size: 8px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.language-menu {
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
right: 0;
|
||||
background-color: var(--bg-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 3px;
|
||||
margin-bottom: 4px;
|
||||
min-width: 100px;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
|
||||
.language-option {
|
||||
padding: 4px 8px;
|
||||
cursor: pointer;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--bg-hover);
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #b5cea8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settings-btn {
|
||||
background: none;
|
||||
|
Reference in New Issue
Block a user