Files
SpineParticlesWeb/scripts/apply-i18n-overrides.mjs
T
2026-10-22 18:37:30 +08:00

298 lines
35 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { readFile, writeFile } from 'node:fs/promises'
const overrides = {
'zh-TW': {
common: {
close: '關閉', reset: '重設', add: '新增', remove: '移除', delete: '刪除', clear: '清除',
cancel: '取消', confirm: '確定', none: '無', enabled: '啟用', disabled: '停用',
fixed: '固定', random: '隨機', curve: '曲線', followExport: '跟隨匯出',
linear: '線性', bezier: '貝茲', above: '上方', below: '下方', left: '左側', right: '右側',
seconds: '秒', frames: '幀',
},
toolbar: {
settings: '系統設定', undo: '復原上一步 (Ctrl+Z)', pan: '拖曳畫布 (Q)', translate: '位移 (W)',
rotate: '旋轉 (E)', scale: '縮放 (R)', zoomIn: '放大', zoomOut: '縮小', fitView: '適合畫布',
toggleGrid: '切換網格', resetView: '重設視圖', background: '背景圖', backgroundSettings: '背景圖顯示設定',
changeBackground: '更換圖像', uploadBackground: '上傳圖像', clearBackground: '清除背景',
noBackground: '未上傳圖像', opacity: '透明度', help: '使用說明', openHelp: '查看使用說明',
},
config: { title: '設定管理', save: '儲存設定', load: '載入設定', selectPreset: '選擇預設', noPresets: '無預設檔案' },
image: { fixed: '固定', sequence: '序列幀', onceHide: '單次-尾幀消失', onceHold: '單次-尾幀固定', loopForward: '正向循環', loopReverse: '反向循環', weight: '權重 %', pivot: '貼圖軸點' },
emission: {
title: '發射模式', stream: '持續', burst: '爆發', normalStream: '一般持續', loopStream: '循環持續',
rate: '發射速率', duration: '發射時長', burstCount: '單次數量', delay: '延遲時間',
shapeTitle: '發射器形狀', point: '點', circle: '圓形', rect: '矩形', cone: '錐形', path: '路徑',
},
attributes: { title: '粒子屬性', initialParams: '粒子初始參數', lifecycleTitle: '粒子生命週期變化參數' },
appearance: { title: '外觀與資源', opacity: '透明度', renderLayer: '渲染層級(Spine 插槽)', imageResources: '圖片資源', independentAlpha: '獨立透明度', off: '關閉', normal: '正常', add: '相加', multiply: '相乘', screen: '濾色' },
scene: { title: '場景物件', particle: '粒子', subEmitter: '子發射器', collision: '碰撞', path: '路徑', positionX: 'X 位置', positionY: 'Y 位置', offsetX: 'X 偏移', offsetY: 'Y 偏移', rotation: '旋轉', scaleX: 'X 縮放', scaleY: 'Y 縮放', xPosition: 'X 位置', yPosition: 'Y 位置', scaleXShort: 'X 縮放', scaleYShort: 'Y 縮放', seed: '隨機種子' },
modifiers: {
title: '修改器', damping: '阻尼', enableNoise: '開啟移動雜訊', enableGravity: '開啟重力', enableWind: '開啟風力',
enableForceField: '開啟力場', enableVortex: '開啟漩渦', enableAttraction: '開啟吸附', enableTrail: '開啟拖尾',
enableFollow: '開啟發射器跟隨', enableCollision: '開啟碰撞', enableSubEmitter: '開啟子發射器',
},
timeline: {
continuousLoop: '持續循環播放', abLoop: '獨立 A/B 區間循環', abLoopShort: 'AB 循環',
emission: '持續發射', particleLife: '粒子存在', spineAnimation: 'Spine 動畫', ownerAnimation: '所屬動畫', frameStatus: '幀 {current} / {total}',
},
export: { title: '匯出設定', spineVersion: 'Spine 版本', fps: '匯出 FPS', exportJson: '匯出 Spine JSON', exportImages: '匯出圖片 ZIP', connectorReady: '連接器可用 · Spine 已就緒', connectorOffline: '本機 Spine 連接器未啟動', spineNotFound: '連接器已啟動,但找不到 Spine', notAuthorized: '連接器已啟動,但目前網站尚未授權', checking: '偵測中', offline: '未啟動', notFound: '找不到 Spine', unauthorized: '未授權', connectorBusy: '正在重新計算並產生 Spine 專案', connectorGenerate: '使用本機 Spine 自動產生 {version} 專案' },
spine: { title: 'Spine 屬性', resources: 'Spine 資源', animations: 'Spine 動畫', hierarchy: '階層樹', xPosition: 'X 位置', yPosition: 'Y 位置', rotation: '旋轉', startTime: '開始時間', scaleX: 'X 縮放', scaleY: 'Y 縮放' },
help: { title: '使用說明', commonOps: '常用操作', shortcuts: '快速鍵', modules: '功能模組詳解' },
presets: { particleSweep: '1.粒子掃過', barBlocks: '2.長條方塊', forceTrail: '3.力場拖尾', lightningSequence: '4.雷電序列幀', texturePivot: '5.貼圖軸點', subEmitter: '6.子發射器' },
},
ja: {
common: {
close: '閉じる', reset: 'リセット', add: '追加', remove: '削除', delete: '削除', clear: 'クリア',
cancel: 'キャンセル', confirm: '確定', none: 'なし', enabled: '有効', disabled: '無効',
fixed: '固定', random: 'ランダム', curve: 'カーブ', followExport: 'エクスポート設定に従う',
linear: 'リニア', bezier: 'ベジェ', above: '上', below: '下', left: '左', right: '右',
seconds: '秒', frames: 'フレーム',
},
toolbar: {
settings: '設定', undo: '元に戻す (Ctrl+Z)', pan: 'キャンバス移動 (Q)', translate: '移動 (W)',
rotate: '回転 (E)', scale: '拡大縮小 (R)', zoomIn: '拡大', zoomOut: '縮小', fitView: 'キャンバスに合わせる',
toggleGrid: 'グリッド切替', resetView: 'ビューをリセット', background: '背景', backgroundSettings: '背景画像設定',
changeBackground: '画像を変更', uploadBackground: '画像をアップロード', clearBackground: '背景をクリア',
noBackground: '画像なし', opacity: '不透明度', help: 'ヘルプ', openHelp: 'ヘルプを開く',
},
config: { title: '設定管理', save: '設定を保存', load: '設定を読み込む', selectPreset: 'プリセットを選択', noPresets: 'プリセットなし' },
image: { fixed: '固定', sequence: 'シーケンス', onceHide: '1回・最終フレームで非表示', onceHold: '1回・最終フレームを保持', loopForward: '正方向ループ', loopReverse: '逆方向ループ', weight: '重み %', pivot: 'テクスチャピボット' },
emission: {
title: 'エミッションモード', stream: 'ストリーム', burst: 'バースト', normalStream: '通常ストリーム', loopStream: 'ループストリーム',
rate: '放出レート', duration: '放出時間', burstCount: '一度の放出数', delay: '遅延時間',
shapeTitle: 'エミッター形状', point: '点', circle: '円', rect: '矩形', cone: '円錐', path: 'パス',
},
attributes: { title: 'パーティクル属性', initialParams: 'パーティクル初期値', lifecycleTitle: 'ライフタイム中の変化' },
appearance: { title: '外観とリソース', opacity: '不透明度', renderLayer: 'レンダー階層(Spine スロット)', imageResources: '画像リソース', independentAlpha: '独立した不透明度', off: 'オフ', normal: '通常', add: '加算', multiply: '乗算', screen: 'スクリーン' },
scene: { title: 'シーンオブジェクト', particle: 'パーティクル', subEmitter: 'サブエミッター', collision: 'コリジョン', path: 'パス', positionX: 'X 位置', positionY: 'Y 位置', offsetX: 'X オフセット', offsetY: 'Y オフセット', rotation: '回転', scaleX: 'X スケール', scaleY: 'Y スケール', xPosition: 'X 位置', yPosition: 'Y 位置', scaleXShort: 'X スケール', scaleYShort: 'Y スケール', seed: 'ランダムシード' },
modifiers: {
title: 'モディファイア', damping: '減衰', enableNoise: '移動ノイズを有効化', enableGravity: '重力を有効化', enableWind: '風を有効化',
enableForceField: 'フォースフィールドを有効化', enableVortex: '渦を有効化', enableAttraction: '吸着を有効化', enableTrail: 'トレイルを有効化',
enableFollow: 'エミッター追従を有効化', enableCollision: 'コリジョンを有効化', enableSubEmitter: 'サブエミッターを有効化',
},
timeline: {
continuousLoop: '連続ループ再生', abLoop: '独立した A/B 区間ループ', abLoopShort: 'AB ループ',
emission: '放出中', particleLife: 'パーティクル存在', spineAnimation: 'Spine アニメーション', ownerAnimation: '所属アニメーション', frameStatus: 'フレーム {current} / {total}',
},
export: { title: 'エクスポート設定', spineVersion: 'Spine バージョン', fps: 'エクスポート FPS', exportJson: 'Spine JSON を書き出す', exportImages: '画像 ZIP を書き出す', connectorReady: 'コネクタ使用可能 · Spine 準備完了', connectorOffline: 'ローカル Spine コネクタが起動していません', spineNotFound: 'コネクタは起動していますが Spine が見つかりません', notAuthorized: 'コネクタは起動していますが、このサイトは未認証です', checking: '確認中', offline: '未起動', notFound: 'Spine が見つかりません', unauthorized: '未認証', connectorBusy: 'Spine プロジェクトを再計算して生成中', connectorGenerate: 'ローカル Spine で Spine {version} プロジェクトを生成' },
spine: { title: 'Spine プロパティ', resources: 'Spine リソース', animations: 'Spine アニメーション', hierarchy: '階層ツリー', xPosition: 'X 位置', yPosition: 'Y 位置', rotation: '回転', startTime: '開始時間', scaleX: 'X スケール', scaleY: 'Y スケール' },
help: { title: 'ヘルプ', commonOps: 'よく使う操作', shortcuts: 'ショートカット', modules: '機能モジュール' },
presets: { particleSweep: '1.パーティクルスイープ', barBlocks: '2.バーブロック', forceTrail: '3.フォースフィールドトレイル', lightningSequence: '4.雷シーケンス', texturePivot: '5.テクスチャピボット', subEmitter: '6.サブエミッター' },
},
ko: {
common: {
close: '닫기', reset: '초기화', add: '추가', remove: '제거', delete: '삭제', clear: '지우기',
cancel: '취소', confirm: '확인', none: '없음', enabled: '사용', disabled: '사용 안 함',
fixed: '고정', random: '랜덤', curve: '곡선', followExport: '내보내기 설정 따르기',
linear: '선형', bezier: '베지어', above: '위', below: '아래', left: '왼쪽', right: '오른쪽',
seconds: '초', frames: '프레임',
},
toolbar: {
settings: '설정', undo: '실행 취소 (Ctrl+Z)', pan: '캔버스 이동 (Q)', translate: '이동 (W)',
rotate: '회전 (E)', scale: '크기 조절 (R)', zoomIn: '확대', zoomOut: '축소', fitView: '캔버스에 맞추기',
toggleGrid: '그리드 전환', resetView: '보기 초기화', background: '배경', backgroundSettings: '배경 이미지 설정',
changeBackground: '이미지 교체', uploadBackground: '이미지 업로드', clearBackground: '배경 지우기',
noBackground: '이미지 없음', opacity: '불투명도', help: '도움말', openHelp: '도움말 열기',
},
config: { title: '설정 관리', save: '설정 저장', load: '설정 불러오기', selectPreset: '프리셋 선택', noPresets: '프리셋 없음' },
image: { fixed: '고정', sequence: '시퀀스', onceHide: '1회·마지막 프레임에서 숨김', onceHold: '1회·마지막 프레임 유지', loopForward: '정방향 루프', loopReverse: '역방향 루프', weight: '가중치 %', pivot: '텍스처 피벗' },
emission: {
title: '이미션 모드', stream: '스트림', burst: '버스트', normalStream: '일반 스트림', loopStream: '루프 스트림',
rate: '이미션 속도', duration: '이미션 시간', burstCount: '1회 생성 수', delay: '지연 시간',
shapeTitle: '이미터 모양', point: '점', circle: '원', rect: '사각형', cone: '원뿔', path: '경로',
},
attributes: { title: '파티클 속성', initialParams: '파티클 초기값', lifecycleTitle: '수명에 따른 변화' },
appearance: { title: '외형과 리소스', opacity: '불투명도', renderLayer: '렌더링 레이어(Spine 슬롯)', imageResources: '이미지 리소스', independentAlpha: '독립 불투명도', off: '끄기', normal: '일반', add: '더하기', multiply: '곱하기', screen: '스크린' },
scene: { title: '장면 오브젝트', particle: '파티클', subEmitter: '하위 이미터', collision: '충돌', path: '경로', positionX: 'X 위치', positionY: 'Y 위치', offsetX: 'X 오프셋', offsetY: 'Y 오프셋', rotation: '회전', scaleX: 'X 크기', scaleY: 'Y 크기', xPosition: 'X 위치', yPosition: 'Y 위치', scaleXShort: 'X 크기', scaleYShort: 'Y 크기', seed: '랜덤 시드' },
modifiers: {
title: '모디파이어', damping: '감쇠', enableNoise: '이동 노이즈 사용', enableGravity: '중력 사용', enableWind: '바람 사용',
enableForceField: '힘장 사용', enableVortex: '소용돌이 사용', enableAttraction: '흡인 사용', enableTrail: '트레일 사용',
enableFollow: '이미터 추적 사용', enableCollision: '충돌 사용', enableSubEmitter: '하위 이미터 사용',
},
timeline: {
continuousLoop: '연속 루프 재생', abLoop: '독립 A/B 구간 루프', abLoopShort: 'AB 루프',
emission: '이미션 중', particleLife: '파티클 존재', spineAnimation: 'Spine 애니메이션', ownerAnimation: '소속 애니메이션', frameStatus: '프레임 {current} / {total}',
},
export: { title: '내보내기 설정', spineVersion: 'Spine 버전', fps: '내보내기 FPS', exportJson: 'Spine JSON 내보내기', exportImages: '이미지 ZIP 내보내기', connectorReady: '커넥터 사용 가능 · Spine 준비됨', connectorOffline: '로컬 Spine 커넥터가 실행 중이 아닙니다', spineNotFound: '커넥터는 실행 중이지만 Spine을 찾을 수 없습니다', notAuthorized: '커넥터는 실행 중이지만 이 사이트는 승인되지 않았습니다', checking: '확인 중', offline: '오프라인', notFound: 'Spine 없음', unauthorized: '승인되지 않음', connectorBusy: 'Spine 프로젝트를 다시 계산하고 생성 중', connectorGenerate: '로컬 Spine으로 Spine {version} 프로젝트 생성' },
spine: { title: 'Spine 속성', resources: 'Spine 리소스', animations: 'Spine 애니메이션', hierarchy: '계층 트리', xPosition: 'X 위치', yPosition: 'Y 위치', rotation: '회전', startTime: '시작 시간', scaleX: 'X 크기', scaleY: 'Y 크기' },
help: { title: '도움말', commonOps: '자주 쓰는 작업', shortcuts: '단축키', modules: '기능 모듈' },
presets: { particleSweep: '1.파티클 스윕', barBlocks: '2.바 블록', forceTrail: '3.힘장 트레일', lightningSequence: '4.번개 시퀀스', texturePivot: '5.텍스처 피벗', subEmitter: '6.하위 이미터' },
},
fr: {
common: {
close: 'Fermer', reset: 'Réinitialiser', add: 'Ajouter', remove: 'Retirer', delete: 'Supprimer', clear: 'Effacer',
cancel: 'Annuler', confirm: 'Confirmer', none: 'Aucun', enabled: 'Activé', disabled: 'Désactivé',
fixed: 'Fixe', random: 'Aléatoire', curve: 'Courbe', followExport: 'Suivre l’export',
linear: 'Linéaire', bezier: 'Bézier', above: 'Au-dessus', below: 'En dessous', left: 'Gauche', right: 'Droite',
seconds: 's', frames: 'images',
},
toolbar: {
settings: 'Paramètres', undo: 'Annuler (Ctrl+Z)', pan: 'Déplacer le canevas (Q)', translate: 'Déplacement (W)',
rotate: 'Rotation (E)', scale: 'Échelle (R)', zoomIn: 'Zoom avant', zoomOut: 'Zoom arrière', fitView: 'Ajuster le canevas',
toggleGrid: 'Afficher/masquer la grille', resetView: 'Réinitialiser la vue', background: 'Arrière-plan', backgroundSettings: 'Paramètres de l’arrière-plan',
changeBackground: 'Remplacer l’image', uploadBackground: 'Importer une image', clearBackground: 'Effacer l’arrière-plan',
noBackground: 'Aucune image', opacity: 'Opacité', help: 'Aide', openHelp: 'Ouvrir l’aide',
},
config: { title: 'Configuration', save: 'Enregistrer', load: 'Charger', selectPreset: 'Choisir un préréglage', noPresets: 'Aucun préréglage' },
image: { fixed: 'Image fixe', sequence: 'Séquence', onceHide: 'Une fois, masquer à la fin', onceHold: 'Une fois, conserver la dernière image', loopForward: 'Boucle avant', loopReverse: 'Boucle arrière', weight: 'Poids %', pivot: 'Pivot de texture' },
emission: {
title: 'Mode d’émission', stream: 'Continu', burst: 'Rafale', normalStream: 'Continu standard', loopStream: 'Boucle continue',
rate: 'Taux d’émission', duration: 'Durée d’émission', burstCount: 'Quantité par rafale', delay: 'Délai',
shapeTitle: 'Forme de l’émetteur', point: 'Point', circle: 'Cercle', rect: 'Rectangle', cone: 'Cône', path: 'Chemin',
},
attributes: { title: 'Attributs des particules', initialParams: 'Valeurs initiales', lifecycleTitle: 'Évolution pendant la durée de vie' },
appearance: { title: 'Apparence et ressources', opacity: 'Opacité', renderLayer: 'Calque de rendu (slot Spine)', imageResources: 'Ressources d’image', independentAlpha: 'Opacité indépendante', off: 'Désactivé', normal: 'Normal', add: 'Ajout', multiply: 'Multiplication', screen: 'Écran' },
scene: { title: 'Objets de scène', particle: 'Particules', subEmitter: 'Sous-émetteur', collision: 'Collision', path: 'Chemin', positionX: 'Position X', positionY: 'Position Y', offsetX: 'Décalage X', offsetY: 'Décalage Y', rotation: 'Rotation', scaleX: 'Échelle X', scaleY: 'Échelle Y', xPosition: 'Position X', yPosition: 'Position Y', scaleXShort: 'Échelle X', scaleYShort: 'Échelle Y', seed: 'Graine aléatoire' },
modifiers: {
title: 'Modificateurs', damping: 'Amortissement', enableNoise: 'Activer le bruit de mouvement', enableGravity: 'Activer la gravité', enableWind: 'Activer le vent',
enableForceField: 'Activer le champ de force', enableVortex: 'Activer le tourbillon', enableAttraction: 'Activer l’attraction', enableTrail: 'Activer la traînée',
enableFollow: 'Activer le suivi de l’émetteur', enableCollision: 'Activer la collision', enableSubEmitter: 'Activer les sous-émetteurs',
},
timeline: {
continuousLoop: 'Lecture en boucle continue', abLoop: 'Boucle indépendante de plage A/B', abLoopShort: 'Boucle AB',
emission: 'Émission', particleLife: 'Particules actives', spineAnimation: 'Animation Spine', ownerAnimation: 'Animation associée', frameStatus: 'Image {current} / {total}',
},
export: { title: 'Paramètres d’export', spineVersion: 'Version de Spine', fps: 'FPS d’export', exportJson: 'Exporter Spine JSON', exportImages: 'Exporter les images ZIP', connectorReady: 'Connecteur disponible · Spine prêt', connectorOffline: 'Le connecteur Spine local n’est pas démarré', spineNotFound: 'Le connecteur est démarré, mais Spine est introuvable', notAuthorized: 'Le connecteur est démarré, mais ce site n’est pas autorisé', checking: 'Vérification', offline: 'Hors ligne', notFound: 'Spine introuvable', unauthorized: 'Non autorisé', connectorBusy: 'Recalcul et génération du projet Spine', connectorGenerate: 'Générer un projet Spine {version} avec Spine local' },
spine: { title: 'Propriétés Spine', resources: 'Ressources Spine', animations: 'Animations Spine', hierarchy: 'Hiérarchie', xPosition: 'Position X', yPosition: 'Position Y', rotation: 'Rotation', startTime: 'Heure de début', scaleX: 'Échelle X', scaleY: 'Échelle Y' },
help: { title: 'Aide', commonOps: 'Actions courantes', shortcuts: 'Raccourcis', modules: 'Guide des modules' },
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' },
},
de: {
common: {
close: 'Schließen', reset: 'Zurücksetzen', add: 'Hinzufügen', remove: 'Entfernen', delete: 'Löschen', clear: 'Leeren',
cancel: 'Abbrechen', confirm: 'Bestätigen', none: 'Keine', enabled: 'Aktiviert', disabled: 'Deaktiviert',
fixed: 'Fest', random: 'Zufällig', curve: 'Kurve', followExport: 'Exporteinstellung folgen',
linear: 'Linear', bezier: 'Bézier', above: 'Über', below: 'Unter', left: 'Links', right: 'Rechts',
seconds: 's', frames: 'Frames',
},
toolbar: {
settings: 'Einstellungen', undo: 'Rückgängig (Ctrl+Z)', pan: 'Canvas verschieben (Q)', translate: 'Verschieben (W)',
rotate: 'Drehen (E)', scale: 'Skalieren (R)', zoomIn: 'Vergrößern', zoomOut: 'Verkleinern', fitView: 'An Canvas anpassen',
toggleGrid: 'Raster umschalten', resetView: 'Ansicht zurücksetzen', background: 'Hintergrund', backgroundSettings: 'Hintergrundeinstellungen',
changeBackground: 'Bild ersetzen', uploadBackground: 'Bild hochladen', clearBackground: 'Hintergrund löschen',
noBackground: 'Kein Bild', opacity: 'Deckkraft', help: 'Hilfe', openHelp: 'Hilfe öffnen',
},
config: { title: 'Konfiguration', save: 'Konfiguration speichern', load: 'Konfiguration laden', selectPreset: 'Voreinstellung wählen', noPresets: 'Keine Voreinstellungen' },
image: { fixed: 'Einzelbild', sequence: 'Sequenz', onceHide: 'Einmal, am Ende ausblenden', onceHold: 'Einmal, letztes Bild halten', loopForward: 'Vorwärts-Schleife', loopReverse: 'Rückwärts-Schleife', weight: 'Gewicht %', pivot: 'Textur-Pivot' },
emission: {
title: 'Emissionsmodus', stream: 'Kontinuierlich', burst: 'Burst', normalStream: 'Normaler Stream', loopStream: 'Loop-Stream',
rate: 'Emissionsrate', duration: 'Emissionsdauer', burstCount: 'Menge pro Burst', delay: 'Verzögerung',
shapeTitle: 'Emitterform', point: 'Punkt', circle: 'Kreis', rect: 'Rechteck', cone: 'Kegel', path: 'Pfad',
},
attributes: { title: 'Partikeleigenschaften', initialParams: 'Initialwerte', lifecycleTitle: 'Änderung über die Lebensdauer' },
appearance: { title: 'Aussehen und Ressourcen', opacity: 'Deckkraft', renderLayer: 'Renderebene (Spine-Slot)', imageResources: 'Bildressourcen', independentAlpha: 'Unabhängige Deckkraft', off: 'Aus', normal: 'Normal', add: 'Addieren', multiply: 'Multiplizieren', screen: 'Bildschirm' },
scene: { title: 'Szenenobjekte', particle: 'Partikel', subEmitter: 'Sub-Emitter', collision: 'Kollision', path: 'Pfad', positionX: 'X-Position', positionY: 'Y-Position', offsetX: 'X-Versatz', offsetY: 'Y-Versatz', rotation: 'Drehung', scaleX: 'X-Skalierung', scaleY: 'Y-Skalierung', xPosition: 'X-Position', yPosition: 'Y-Position', scaleXShort: 'X-Skalierung', scaleYShort: 'Y-Skalierung', seed: 'Zufallsseed' },
modifiers: {
title: 'Modifikatoren', damping: 'Dämpfung', enableNoise: 'Bewegungsrauschen aktivieren', enableGravity: 'Schwerkraft aktivieren', enableWind: 'Wind aktivieren',
enableForceField: 'Kraftfeld aktivieren', enableVortex: 'Wirbel aktivieren', enableAttraction: 'Anziehung aktivieren', enableTrail: 'Schweif aktivieren',
enableFollow: 'Emitter-Verfolgung aktivieren', enableCollision: 'Kollision aktivieren', enableSubEmitter: 'Sub-Emitter aktivieren',
},
timeline: {
continuousLoop: 'Dauerhaft in Schleife abspielen', abLoop: 'Unabhängige A/B-Bereichsschleife', abLoopShort: 'AB-Schleife',
emission: 'Emission', particleLife: 'Aktive Partikel', spineAnimation: 'Spine-Animation', ownerAnimation: 'Zugehörige Animation', frameStatus: 'Frame {current} / {total}',
},
export: { title: 'Exporteinstellungen', spineVersion: 'Spine-Version', fps: 'Export-FPS', exportJson: 'Spine JSON exportieren', exportImages: 'Bilder-ZIP exportieren', connectorReady: 'Connector verfügbar · Spine bereit', connectorOffline: 'Der lokale Spine-Connector läuft nicht', spineNotFound: 'Der Connector läuft, aber Spine wurde nicht gefunden', notAuthorized: 'Der Connector läuft, aber diese Website ist nicht autorisiert', checking: 'Prüfung', offline: 'Offline', notFound: 'Spine nicht gefunden', unauthorized: 'Nicht autorisiert', connectorBusy: 'Spine-Projekt wird neu berechnet und erstellt', connectorGenerate: 'Spine-{version}-Projekt mit lokalem Spine erstellen' },
spine: { title: 'Spine-Eigenschaften', resources: 'Spine-Ressourcen', animations: 'Spine-Animationen', hierarchy: 'Hierarchie', xPosition: 'X-Position', yPosition: 'Y-Position', rotation: 'Drehung', startTime: 'Startzeit', scaleX: 'X-Skalierung', scaleY: 'Y-Skalierung' },
help: { title: 'Hilfe', commonOps: 'Häufige Aktionen', shortcuts: 'Tastenkürzel', modules: 'Modulhandbuch' },
presets: { particleSweep: '1.Partikel-Sweep', barBlocks: '2.Balkenblöcke', forceTrail: '3.Kraftfeldschweif', lightningSequence: '4.Blitzsequenz', texturePivot: '5.Textur-Pivot', subEmitter: '6.Sub-Emitter' },
},
'pt-BR': {
common: {
close: 'Fechar', reset: 'Redefinir', add: 'Adicionar', remove: 'Remover', delete: 'Excluir', clear: 'Limpar',
cancel: 'Cancelar', confirm: 'Confirmar', none: 'Nenhum', enabled: 'Ativado', disabled: 'Desativado',
fixed: 'Fixo', random: 'Aleatório', curve: 'Curva', followExport: 'Seguir exportação',
linear: 'Linear', bezier: 'Bézier', above: 'Acima', below: 'Abaixo', left: 'Esquerda', right: 'Direita',
seconds: 's', frames: 'quadros',
},
toolbar: {
settings: 'Configurações', undo: 'Desfazer (Ctrl+Z)', pan: 'Mover tela (Q)', translate: 'Mover (W)',
rotate: 'Girar (E)', scale: 'Escalar (R)', zoomIn: 'Ampliar', zoomOut: 'Reduzir', fitView: 'Ajustar à tela',
toggleGrid: 'Alternar grade', resetView: 'Redefinir visualização', background: 'Fundo', backgroundSettings: 'Configurações do fundo',
changeBackground: 'Trocar imagem', uploadBackground: 'Enviar imagem', clearBackground: 'Limpar fundo',
noBackground: 'Nenhuma imagem', opacity: 'Opacidade', help: 'Ajuda', openHelp: 'Abrir ajuda',
},
config: { title: 'Gerenciamento de configuração', save: 'Salvar configuração', load: 'Carregar configuração', selectPreset: 'Selecionar predefinição', noPresets: 'Nenhuma predefinição' },
image: { fixed: 'Imagem única', sequence: 'Sequência', onceHide: 'Uma vez, ocultar no final', onceHold: 'Uma vez, manter último quadro', loopForward: 'Loop para frente', loopReverse: 'Loop reverso', weight: 'Peso %', pivot: 'Pivô da textura' },
emission: {
title: 'Modo de emissão', stream: 'Contínuo', burst: 'Explosão', normalStream: 'Contínuo normal', loopStream: 'Loop contínuo',
rate: 'Taxa de emissão', duration: 'Duração da emissão', burstCount: 'Quantidade por explosão', delay: 'Atraso',
shapeTitle: 'Forma do emissor', point: 'Ponto', circle: 'Círculo', rect: 'Retângulo', cone: 'Cone', path: 'Caminho',
},
attributes: { title: 'Atributos das partículas', initialParams: 'Valores iniciais', lifecycleTitle: 'Alterações durante o tempo de vida' },
appearance: { title: 'Aparência e recursos', opacity: 'Opacidade', renderLayer: 'Camada de renderização (slot Spine)', imageResources: 'Recursos de imagem', independentAlpha: 'Opacidade independente', off: 'Desligado', normal: 'Normal', add: 'Adição', multiply: 'Multiplicação', screen: 'Tela' },
scene: { title: 'Objetos da cena', particle: 'Partículas', subEmitter: 'Subemissor', collision: 'Colisão', path: 'Caminho', positionX: 'Posição X', positionY: 'Posição Y', offsetX: 'Deslocamento X', offsetY: 'Deslocamento Y', rotation: 'Rotação', scaleX: 'Escala X', scaleY: 'Escala Y', xPosition: 'Posição X', yPosition: 'Posição Y', scaleXShort: 'Escala X', scaleYShort: 'Escala Y', seed: 'Semente aleatória' },
modifiers: {
title: 'Modificadores', damping: 'Amortecimento', enableNoise: 'Ativar ruído de movimento', enableGravity: 'Ativar gravidade', enableWind: 'Ativar vento',
enableForceField: 'Ativar campo de força', enableVortex: 'Ativar vórtice', enableAttraction: 'Ativar atração', enableTrail: 'Ativar rastro',
enableFollow: 'Ativar seguimento do emissor', enableCollision: 'Ativar colisão', enableSubEmitter: 'Ativar subemissores',
},
timeline: {
continuousLoop: 'Reprodução em loop contínuo', abLoop: 'Loop independente do intervalo A/B', abLoopShort: 'Loop AB',
emission: 'Emissão', particleLife: 'Partículas ativas', spineAnimation: 'Animação Spine', ownerAnimation: 'Animação associada', frameStatus: 'Quadro {current} / {total}',
},
export: { title: 'Configurações de exportação', spineVersion: 'Versão do Spine', fps: 'FPS de exportação', exportJson: 'Exportar Spine JSON', exportImages: 'Exportar imagens ZIP', connectorReady: 'Conector disponível · Spine pronto', connectorOffline: 'O conector local do Spine não está em execução', spineNotFound: 'O conector está ativo, mas o Spine não foi encontrado', notAuthorized: 'O conector está ativo, mas este site não está autorizado', checking: 'Verificando', offline: 'Offline', notFound: 'Spine não encontrado', unauthorized: 'Não autorizado', connectorBusy: 'Recalculando e gerando o projeto Spine', connectorGenerate: 'Gerar projeto Spine {version} com o Spine local' },
spine: { title: 'Propriedades do Spine', resources: 'Recursos Spine', animations: 'Animações Spine', hierarchy: 'Hierarquia', xPosition: 'Posição X', yPosition: 'Posição Y', rotation: 'Rotação', startTime: 'Tempo inicial', scaleX: 'Escala X', scaleY: 'Escala Y' },
help: { title: 'Ajuda', commonOps: 'Ações comuns', shortcuts: 'Atalhos', modules: 'Guia dos módulos' },
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' },
},
es: {
common: {
close: 'Cerrar', reset: 'Restablecer', add: 'Añadir', remove: 'Quitar', delete: 'Eliminar', clear: 'Limpiar',
cancel: 'Cancelar', confirm: 'Confirmar', none: 'Ninguno', enabled: 'Activado', disabled: 'Desactivado',
fixed: 'Fijo', random: 'Aleatorio', curve: 'Curva', followExport: 'Seguir exportación',
linear: 'Lineal', bezier: 'Bézier', above: 'Arriba', below: 'Abajo', left: 'Izquierda', right: 'Derecha',
seconds: 's', frames: 'fotogramas',
},
toolbar: {
settings: 'Ajustes', undo: 'Deshacer (Ctrl+Z)', pan: 'Mover lienzo (Q)', translate: 'Mover (W)',
rotate: 'Girar (E)', scale: 'Escalar (R)', zoomIn: 'Acercar', zoomOut: 'Alejar', fitView: 'Ajustar al lienzo',
toggleGrid: 'Mostrar/ocultar cuadrícula', resetView: 'Restablecer vista', background: 'Fondo', backgroundSettings: 'Ajustes del fondo',
changeBackground: 'Cambiar imagen', uploadBackground: 'Subir imagen', clearBackground: 'Borrar fondo',
noBackground: 'Sin imagen', opacity: 'Opacidad', help: 'Ayuda', openHelp: 'Abrir ayuda',
},
config: { title: 'Gestión de configuración', save: 'Guardar configuración', load: 'Cargar configuración', selectPreset: 'Seleccionar preajuste', noPresets: 'Sin preajustes' },
image: { fixed: 'Imagen única', sequence: 'Secuencia', onceHide: 'Una vez, ocultar al final', onceHold: 'Una vez, mantener último fotograma', loopForward: 'Bucle hacia delante', loopReverse: 'Bucle inverso', weight: 'Peso %', pivot: 'Pivote de textura' },
emission: {
title: 'Modo de emisión', stream: 'Continuo', burst: 'Ráfaga', normalStream: 'Continuo normal', loopStream: 'Bucle continuo',
rate: 'Tasa de emisión', duration: 'Duración de emisión', burstCount: 'Cantidad por ráfaga', delay: 'Retardo',
shapeTitle: 'Forma del emisor', point: 'Punto', circle: 'Círculo', rect: 'Rectángulo', cone: 'Cono', path: 'Ruta',
},
attributes: { title: 'Atributos de partículas', initialParams: 'Valores iniciales', lifecycleTitle: 'Cambios durante la vida útil' },
appearance: { title: 'Apariencia y recursos', opacity: 'Opacidad', renderLayer: 'Capa de renderizado (slot de Spine)', imageResources: 'Recursos de imagen', independentAlpha: 'Opacidad independiente', off: 'Desactivado', normal: 'Normal', add: 'Suma', multiply: 'Multiplicación', screen: 'Pantalla' },
scene: { title: 'Objetos de escena', particle: 'Partículas', subEmitter: 'Subemisor', collision: 'Colisión', path: 'Ruta', positionX: 'Posición X', positionY: 'Posición Y', offsetX: 'Desplazamiento X', offsetY: 'Desplazamiento Y', rotation: 'Rotación', scaleX: 'Escala X', scaleY: 'Escala Y', xPosition: 'Posición X', yPosition: 'Posición Y', scaleXShort: 'Escala X', scaleYShort: 'Escala Y', seed: 'Semilla aleatoria' },
modifiers: {
title: 'Modificadores', damping: 'Amortiguación', enableNoise: 'Activar ruido de movimiento', enableGravity: 'Activar gravedad', enableWind: 'Activar viento',
enableForceField: 'Activar campo de fuerza', enableVortex: 'Activar vórtice', enableAttraction: 'Activar atracción', enableTrail: 'Activar estela',
enableFollow: 'Activar seguimiento del emisor', enableCollision: 'Activar colisión', enableSubEmitter: 'Activar subemisores',
},
timeline: {
continuousLoop: 'Reproducción en bucle continuo', abLoop: 'Bucle independiente del rango A/B', abLoopShort: 'Bucle AB',
emission: 'Emisión', particleLife: 'Partículas activas', spineAnimation: 'Animación de Spine', ownerAnimation: 'Animación asociada', frameStatus: 'Fotograma {current} / {total}',
},
export: { title: 'Ajustes de exportación', spineVersion: 'Versión de Spine', fps: 'FPS de exportación', exportJson: 'Exportar Spine JSON', exportImages: 'Exportar imágenes ZIP', connectorReady: 'Conector disponible · Spine listo', connectorOffline: 'El conector local de Spine no está iniciado', spineNotFound: 'El conector está iniciado, pero no se encontró Spine', notAuthorized: 'El conector está iniciado, pero este sitio no está autorizado', checking: 'Comprobando', offline: 'Sin conexión', notFound: 'Spine no encontrado', unauthorized: 'No autorizado', connectorBusy: 'Recalculando y generando el proyecto de Spine', connectorGenerate: 'Generar proyecto Spine {version} con Spine local' },
spine: { title: 'Propiedades de Spine', resources: 'Recursos de Spine', animations: 'Animaciones de Spine', hierarchy: 'Jerarquía', xPosition: 'Posición X', yPosition: 'Posición Y', rotation: 'Rotación', startTime: 'Tiempo inicial', scaleX: 'Escala X', scaleY: 'Escala Y' },
help: { title: 'Ayuda', commonOps: 'Acciones comunes', shortcuts: 'Atajos', modules: 'Guía de módulos' },
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' },
},
}
function merge(target, source) {
for (const [key, value] of Object.entries(source)) {
if (value && typeof value === 'object' && !Array.isArray(value)) {
target[key] ||= {}
merge(target[key], value)
} else {
target[key] = value
}
}
}
for (const [locale, values] of Object.entries(overrides)) {
const path = `src/i18n/locales/${locale}.json`
const messages = JSON.parse(await readFile(path, 'utf8'))
merge(messages, values)
await writeFile(path, `${JSON.stringify(messages, null, 2)}\n`)
}
console.log('Applied terminology overrides for all added locales.')