多语言调整
This commit is contained in:
1 parent
04de5e5a8e
commit
8bd9154414
23 files changed
+395
-155
No files matched your search
@@ -100,14 +100,6 @@
|
||||
"presetListError": "Voreinstellungsliste kann nicht gelesen werden",
|
||||
"presetReadError": "Voreinstellung konnte nicht gelesen werden: {file}"
|
||||
},
|
||||
"presets": {
|
||||
"particleSweep": "1.Partikel-Sweep",
|
||||
"barBlocks": "2.Balkenblöcke",
|
||||
"forceTrail": "3.Kraftfeldschweif",
|
||||
"lightningSequence": "4.Blitzsequenz",
|
||||
"texturePivot": "5.Textur-Pivot",
|
||||
"subEmitter": "6.Sub-Emitter"
|
||||
},
|
||||
"curve": {
|
||||
"bezierHint": "Ziehen Sie den quadratischen Griff, um den Bogen anzupassen. · Doppelklicken Sie auf eine leere Stelle, um einen neuen zu erstellen. · Doppelklicken Sie auf einen Knoten, um ihn zu löschen",
|
||||
"linearHint": "Doppelklicken Sie auf eine leere Stelle, um eine neue zu erstellen. Doppelklicken Sie auf einen Knoten, um ihn zu löschen. Ziehen Sie einen Knoten, um ihn anzupassen.",
|
||||
|
||||
@@ -112,14 +112,6 @@
|
||||
"presetListError": "Unable to read preset list",
|
||||
"presetReadError": "Unable to read preset: {file}"
|
||||
},
|
||||
"presets": {
|
||||
"particleSweep": "1. Particle Sweep",
|
||||
"barBlocks": "2. Bar Blocks",
|
||||
"forceTrail": "3. Force Field Trail",
|
||||
"lightningSequence": "4. Lightning Sequence",
|
||||
"texturePivot": "5. Texture Pivot",
|
||||
"subEmitter": "6. Sub-emitter"
|
||||
},
|
||||
"curve": {
|
||||
"bezierHint": "Drag square handles · Double-click empty space to add · Double-click a node to delete",
|
||||
"linearHint": "Double-click empty space to add · Double-click a node to delete · Drag nodes to adjust",
|
||||
|
||||
@@ -100,14 +100,6 @@
|
||||
"presetListError": "No se puede leer la lista preestablecida",
|
||||
"presetReadError": "No se puede leer el ajuste preestablecido: {file}"
|
||||
},
|
||||
"presets": {
|
||||
"particleSweep": "1.Barrido de partículas",
|
||||
"barBlocks": "2.Bloques rectangulares",
|
||||
"forceTrail": "3.Estela de campo de fuerza",
|
||||
"lightningSequence": "4.Secuencia de rayos",
|
||||
"texturePivot": "5.Pivote de textura",
|
||||
"subEmitter": "6.Subemisor"
|
||||
},
|
||||
"curve": {
|
||||
"bezierHint": "Arrastre el controlador cuadrado para ajustar el arco · Haga doble clic en un espacio en blanco para crear uno nuevo · Haga doble clic en un nodo para eliminarlo",
|
||||
"linearHint": "Haga doble clic en un espacio en blanco para crear uno nuevo. Haga doble clic en un nodo para eliminarlo. Arrastra un nodo para ajustarlo.",
|
||||
|
||||
@@ -100,14 +100,6 @@
|
||||
"presetListError": "Impossible de lire la liste des préréglages",
|
||||
"presetReadError": "Impossible de lire le préréglage : {file}"
|
||||
},
|
||||
"presets": {
|
||||
"particleSweep": "1.Balayage de particules",
|
||||
"barBlocks": "2.Blocs rectangulaires",
|
||||
"forceTrail": "3.Traînée de champ de force",
|
||||
"lightningSequence": "4.Séquence d’éclairs",
|
||||
"texturePivot": "5.Pivot de texture",
|
||||
"subEmitter": "6.Sous-émetteur"
|
||||
},
|
||||
"curve": {
|
||||
"bezierHint": "Faites glisser la poignée carrée pour ajuster l'arc · Double-cliquez sur un espace vide pour en créer un nouveau · Double-cliquez sur un nœud pour le supprimer",
|
||||
"linearHint": "Double-cliquez sur un espace vide pour en créer un nouveau. Double-cliquez sur un nœud pour le supprimer. Faites glisser un nœud pour l'ajuster.",
|
||||
|
||||
@@ -100,14 +100,6 @@
|
||||
"presetListError": "プリセットリストを読み取れません",
|
||||
"presetReadError": "プリセットを読み取れません: {file}"
|
||||
},
|
||||
"presets": {
|
||||
"particleSweep": "1.パーティクルスイープ",
|
||||
"barBlocks": "2.バーブロック",
|
||||
"forceTrail": "3.フォースフィールドトレイル",
|
||||
"lightningSequence": "4.雷シーケンス",
|
||||
"texturePivot": "5.テクスチャピボット",
|
||||
"subEmitter": "6.サブエミッター"
|
||||
},
|
||||
"curve": {
|
||||
"bezierHint": "四角いハンドルをドラッグして円弧を調整します。 · 空白スペースをダブルクリックして新しいスペースを作成します。 · ノードをダブルクリックして削除します。",
|
||||
"linearHint": "空白スペースをダブルクリックして、新しいスペースを作成します。ノードをダブルクリックして削除します。ノードをドラッグして調整します。",
|
||||
|
||||
@@ -100,14 +100,6 @@
|
||||
"presetListError": "사전 설정 목록을 읽을 수 없습니다.",
|
||||
"presetReadError": "사전 설정을 읽을 수 없습니다: {file}"
|
||||
},
|
||||
"presets": {
|
||||
"particleSweep": "1.파티클 스윕",
|
||||
"barBlocks": "2.바 블록",
|
||||
"forceTrail": "3.힘장 트레일",
|
||||
"lightningSequence": "4.번개 시퀀스",
|
||||
"texturePivot": "5.텍스처 피벗",
|
||||
"subEmitter": "6.하위 이미터"
|
||||
},
|
||||
"curve": {
|
||||
"bezierHint": "원호를 조정하려면 사각형 핸들을 드래그하세요. · 새 공간을 만들려면 빈 공간을 두 번 클릭하세요. · 삭제하려면 노드를 두 번 클릭하세요.",
|
||||
"linearHint": "빈 공간을 더블클릭하면 새로운 공간이 생성됩니다. 삭제하려면 노드를 두 번 클릭하세요. 노드를 드래그하여 조정하세요.",
|
||||
|
||||
@@ -100,14 +100,6 @@
|
||||
"presetListError": "Não é possível ler a lista predefinida",
|
||||
"presetReadError": "Não é possível ler a predefinição: {file}"
|
||||
},
|
||||
"presets": {
|
||||
"particleSweep": "1.Varredura de partículas",
|
||||
"barBlocks": "2.Blocos retangulares",
|
||||
"forceTrail": "3.Rastro de campo de força",
|
||||
"lightningSequence": "4.Sequência de raios",
|
||||
"texturePivot": "5.Pivô da textura",
|
||||
"subEmitter": "6.Subemissor"
|
||||
},
|
||||
"curve": {
|
||||
"bezierHint": "Arraste a alça quadrada para ajustar o arco · Clique duas vezes em um espaço em branco para criar um novo · Clique duas vezes em um nó para excluí-lo",
|
||||
"linearHint": "Clique duas vezes em um espaço em branco para criar um novo. Clique duas vezes em um nó para excluí-lo. Arraste um nó para ajustá-lo.",
|
||||
|
||||
@@ -112,14 +112,6 @@
|
||||
"presetListError": "无法读取预设列表",
|
||||
"presetReadError": "无法读取预设:{file}"
|
||||
},
|
||||
"presets": {
|
||||
"particleSweep": "1.粒子扫过",
|
||||
"barBlocks": "2.长条方块",
|
||||
"forceTrail": "3.力场拖尾",
|
||||
"lightningSequence": "4.雷电序列帧",
|
||||
"texturePivot": "5.贴图轴点",
|
||||
"subEmitter": "6.子发射器"
|
||||
},
|
||||
"curve": {
|
||||
"bezierHint": "拖动方形手柄调整弧度 · 双击空白新建 · 双击节点删除",
|
||||
"linearHint": "双击空白新建 · 双击节点删除 · 拖动节点调整",
|
||||
|
||||
@@ -100,14 +100,6 @@
|
||||
"presetListError": "無法讀取預設列表",
|
||||
"presetReadError": "無法讀取預設:{file}"
|
||||
},
|
||||
"presets": {
|
||||
"particleSweep": "1.粒子掃過",
|
||||
"barBlocks": "2.長條方塊",
|
||||
"forceTrail": "3.力場拖尾",
|
||||
"lightningSequence": "4.雷電序列幀",
|
||||
"texturePivot": "5.貼圖軸點",
|
||||
"subEmitter": "6.子發射器"
|
||||
},
|
||||
"curve": {
|
||||
"bezierHint": "拖曳方形手把調整弧度 · 雙擊空白新建 · 雙擊節點刪除",
|
||||
"linearHint": "雙擊空白新建 · 雙擊節點刪除 · 拖曳節點調整",
|
||||
|
||||
@@ -27,19 +27,11 @@ import ColorGradientEditor from '../ColorGradientEditor.vue'
|
||||
import ImageResourceCard from '../ImageResourceCard.vue'
|
||||
import SpineObjectPanel from '../../spine/SpineObjectPanel.vue'
|
||||
import { useParticlePanelContext } from './particlePanelContext'
|
||||
import { resolvePresetDisplayName, type PresetOption } from './presetNames'
|
||||
const { configFileInput, selectedPreset, presetOptions, presetLoading, configMessage, configError, saveConfig, onConfigFileChange, refreshPresets, loadSelectedPreset, collapsed, toggle, select } = useParticlePanelContext()
|
||||
const { t } = useI18n()
|
||||
const presetNameKeys: Record<string, string> = {
|
||||
'1.粒子扫过.json': 'presets.particleSweep',
|
||||
'2.长条方块.json': 'presets.barBlocks',
|
||||
'3.力场拖尾.json': 'presets.forceTrail',
|
||||
'4.雷电序列帧.json': 'presets.lightningSequence',
|
||||
'5.贴图轴点.json': 'presets.texturePivot',
|
||||
'6.子发射器.json': 'presets.subEmitter',
|
||||
}
|
||||
function presetDisplayName(preset: { name: string; file: string }) {
|
||||
const key = presetNameKeys[preset.file]
|
||||
return key ? t(key) : preset.name
|
||||
const { locale } = useI18n()
|
||||
function presetDisplayName(preset: PresetOption) {
|
||||
return resolvePresetDisplayName(preset, locale.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
export type PresetDisplayName = string | Record<string, string>
|
||||
|
||||
export interface PresetOption {
|
||||
name?: PresetDisplayName
|
||||
file: string
|
||||
}
|
||||
|
||||
function normalizeName(value: unknown): PresetDisplayName | undefined {
|
||||
if (typeof value === 'string') return value.trim() || undefined
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined
|
||||
const entries = Object.entries(value)
|
||||
.filter((entry): entry is [string, string] => typeof entry[1] === 'string' && !!entry[1].trim())
|
||||
return entries.length ? Object.fromEntries(entries) : undefined
|
||||
}
|
||||
|
||||
/** 兼容自动生成的仅含 file 条目、旧字符串 name 和多语言 name。 */
|
||||
export function parsePresetIndex(value: unknown): PresetOption[] {
|
||||
if (!Array.isArray(value)) return []
|
||||
const result: PresetOption[] = []
|
||||
for (const item of value) {
|
||||
if (typeof item === 'string' && item.trim()) {
|
||||
result.push({ file: item })
|
||||
continue
|
||||
}
|
||||
if (!item || typeof item !== 'object' || Array.isArray(item)) continue
|
||||
const file = typeof item.file === 'string' ? item.file.trim() : ''
|
||||
if (!file) continue
|
||||
result.push({ file, name: normalizeName(item.name) })
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export function resolvePresetDisplayName(preset: PresetOption, locale: string) {
|
||||
if (typeof preset.name === 'string') return preset.name
|
||||
if (preset.name && typeof preset.name === 'object') {
|
||||
return preset.name[locale] || preset.name.en || preset.name['zh-CN']
|
||||
|| preset.file.replace(/^.*[\\/]/, '').replace(/\.json$/i, '')
|
||||
}
|
||||
return preset.file.replace(/^.*[\\/]/, '').replace(/\.json$/i, '')
|
||||
}
|
||||
@@ -25,12 +25,12 @@ import {
|
||||
} from '../../export/spineConnectorClient'
|
||||
import { automaticLoopTransitionFrames } from '../../core/loopSegmentTiming'
|
||||
import { translate } from '../../i18n'
|
||||
|
||||
import { parsePresetIndex, type PresetOption } from './presetNames'
|
||||
|
||||
export function useProjectPresets(store: ReturnType<typeof useParticleStore>) {
|
||||
const configFileInput = ref<HTMLInputElement | null>(null)
|
||||
const selectedPreset = ref('')
|
||||
const presetOptions = ref<Array<{ name: string; file: string }>>([])
|
||||
const presetOptions = ref<PresetOption[]>([])
|
||||
const presetLoading = ref(false)
|
||||
const configMessage = ref('')
|
||||
const configError = ref(false)
|
||||
@@ -62,9 +62,7 @@ async function refreshPresets() {
|
||||
const response = await fetch(`/Preset/index.json?t=${Date.now()}`, { cache: 'no-store' })
|
||||
if (!response.ok) throw new Error(translate('config.presetListError'))
|
||||
const presets = await response.json()
|
||||
presetOptions.value = Array.isArray(presets)
|
||||
? presets.filter((item): item is { name: string; file: string } => !!item && typeof item.name === 'string' && typeof item.file === 'string')
|
||||
: []
|
||||
presetOptions.value = parsePresetIndex(presets)
|
||||
} catch {
|
||||
presetOptions.value = []
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user