From ec5ef4474ee6958c87782996c943fb162c8b4355 Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Tue, 30 Jun 2026 10:25:52 +0300 Subject: [PATCH] i18n: add Japanese and complete menu localization (#367) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * i18n: more menu translations * chore: code formatting * chore: code formatting * chore: code formatting * i18n: more menu translations * chore: code formatting * i18n: added new menu translations and japanese language * i18n: added theme-auto string * i18n: translated rest of the menu text * fix(i18n): polish PR 273 locale updates - Fix obvious translation regressions in existing locales - Preserve update size interpolation across localized update messages - Use standard UI terms for theme and boolean operation labels * fix(i18n): tune localized toggle labels - Use paired action wording for toggle commands - Clarify Japanese frame-selection command label --------- Co-authored-by: Santos Alarcón --- desktop/generated/menu.json | 12 +- packages/vue/src/i18n/locale.ts | 3 +- packages/vue/src/i18n/messages.ts | 17 +- packages/vue/src/locales/de.json | 38 +-- packages/vue/src/locales/es.json | 22 +- packages/vue/src/locales/fr.json | 38 +-- packages/vue/src/locales/it.json | 38 +-- packages/vue/src/locales/ja.json | 360 +++++++++++++++++++++++++++ packages/vue/src/locales/pl.json | 38 +-- packages/vue/src/locales/ru.json | 38 +-- packages/vue/src/locales/zh-CN.json | 12 +- src/app/shell/menu/app-menu.ts | 22 +- src/app/shell/menu/editor-actions.ts | 16 +- src/app/shell/menu/schema.ts | 12 +- 14 files changed, 563 insertions(+), 103 deletions(-) create mode 100644 packages/vue/src/locales/ja.json diff --git a/desktop/generated/menu.json b/desktop/generated/menu.json index b5aadf848..87e38ae92 100644 --- a/desktop/generated/menu.json +++ b/desktop/generated/menu.json @@ -281,17 +281,17 @@ "type": "separator" }, { - "id": "align-left", + "id": "arrange.align-left", "label": "Align Left", "accelerator": "Alt+A" }, { - "id": "align-center", + "id": "arrange.align-center", "label": "Align Center", "accelerator": "Alt+H" }, { - "id": "align-right", + "id": "arrange.align-right", "label": "Align Right", "accelerator": "Alt+D" }, @@ -299,17 +299,17 @@ "type": "separator" }, { - "id": "align-top", + "id": "arrange.align-top", "label": "Align Top", "accelerator": "Alt+W" }, { - "id": "align-middle", + "id": "arrange.align-middle", "label": "Align Middle", "accelerator": "Alt+V" }, { - "id": "align-bottom", + "id": "arrange.align-bottom", "label": "Align Bottom", "accelerator": "Alt+S" } diff --git a/packages/vue/src/i18n/locale.ts b/packages/vue/src/i18n/locale.ts index bca201b54..366c51543 100644 --- a/packages/vue/src/i18n/locale.ts +++ b/packages/vue/src/i18n/locale.ts @@ -1,7 +1,7 @@ import { browser, localeFrom } from '@nanostores/i18n' import { atom } from 'nanostores' -export const AVAILABLE_LOCALES = ['en', 'de', 'es', 'fr', 'it', 'pl', 'ru', 'zh-CN'] as const +export const AVAILABLE_LOCALES = ['en', 'de', 'es', 'fr', 'it', 'ja', 'pl', 'ru', 'zh-CN'] as const export type Locale = (typeof AVAILABLE_LOCALES)[number] export const LOCALE_LABELS: Record = { @@ -10,6 +10,7 @@ export const LOCALE_LABELS: Record = { es: 'Español', fr: 'Français', it: 'Italiano', + ja: '日本語', pl: 'Polski', ru: 'Русский', 'zh-CN': '中文(简体)' diff --git a/packages/vue/src/i18n/messages.ts b/packages/vue/src/i18n/messages.ts index ae4e07f05..ea76d0485 100644 --- a/packages/vue/src/i18n/messages.ts +++ b/packages/vue/src/i18n/messages.ts @@ -9,6 +9,7 @@ const localeLoaders: Record, () => Promise<{ default: Comp es: () => import('#vue/locales/es.json'), fr: () => import('#vue/locales/fr.json'), it: () => import('#vue/locales/it.json'), + ja: () => import('#vue/locales/ja.json'), pl: () => import('#vue/locales/pl.json'), ru: () => import('#vue/locales/ru.json'), 'zh-CN': () => import('#vue/locales/zh-CN.json') @@ -42,8 +43,10 @@ export const menuMessages = i18n('menu', { copy: 'Copy', paste: 'Paste', - zoomIn: 'Zoom in', - zoomOut: 'Zoom out', + theme: 'Theme', + themeLight: 'Light', + themeDark: 'Dark', + themeAuto: 'Auto', profiler: 'Performance profiler', language: 'Language', checkUpdates: 'Check for updates…', @@ -73,7 +76,15 @@ export const menuMessages = i18n('menu', { copyAsJSX: 'Copy as JSX', copyNodeId: 'Copy node ID', copyXPath: 'Copy XPath', - booleanOperations: 'Boolean operations' + booleanOperations: 'Boolean operations', + arrangeAlignLeft: 'Align left', + arrangeAlignCenter: 'Align center', + arrangeAlignRight: 'Align right', + arrangeAlignTop: 'Align top', + arrangeAlignMiddle: 'Align middle', + arrangeAlignBottom: 'Align bottom', + zoomIn: 'Zoom in', + zoomOut: 'Zoom out' }) export const commandMessages = i18n('commands', { diff --git a/packages/vue/src/locales/de.json b/packages/vue/src/locales/de.json index db87de961..27c0519dc 100644 --- a/packages/vue/src/locales/de.json +++ b/packages/vue/src/locales/de.json @@ -17,6 +17,10 @@ "zoomIn": "Vergrößern", "zoomOut": "Verkleinern", "profiler": "Leistungsprofil", + "theme": "Thema", + "themeLight": "Hell", + "themeDark": "Dunkel", + "themeAuto": "Automatisch", "language": "Sprache", "moveToPage": "Auf Seite verschieben", "createInstance": "Instanz erstellen", @@ -32,7 +36,7 @@ "italic": "Kursiv", "underline": "Unterstrichen", "pasteHere": "Hier einfügen", - "pasteToReplace": "Paste to replace", + "pasteToReplace": "Zum Ersetzen einfügen", "copyPasteAs": "Kopieren/Einfügen als", "copyAsText": "Als Text kopieren", "copyAsSVG": "Als SVG kopieren", @@ -41,9 +45,15 @@ "copyNodeId": "Knoten-ID kopieren", "copyXPath": "XPath kopieren", "checkUpdates": "Nach Updates suchen…", - "booleanOperations": "Boolean operations", + "booleanOperations": "Boolesche Operationen", "strikethrough": "Durchstreichen", - "closeTab": "Tab schließen" + "closeTab": "Tab schließen", + "arrangeAlignLeft": "Links ausrichten", + "arrangeAlignCenter": "Zentrieren", + "arrangeAlignRight": "Rechts ausrichten", + "arrangeAlignTop": "Oben ausrichten", + "arrangeAlignMiddle": "Mittig ausrichten", + "arrangeAlignBottom": "Unten ausrichten" }, "commands": { "undo": "Rückgängig", @@ -66,19 +76,19 @@ "zoomToFit": "Einpassen", "zoomToSelection": "Auswahl einpassen", "groupSelection": "Gruppieren", - "frameSelection": "Frame selection", - "showHide": "Sichtbarkeit", - "lockUnlock": "Sperren", - "unionSelection": "Union selection", - "subtractSelection": "Subtract selection", - "intersectSelection": "Intersect selection", - "excludeSelection": "Exclude selection", - "booleanOperations": "Boolean operations", + "frameSelection": "Auswahl in Rahmen setzen", + "showHide": "Ein-/Ausblenden", + "lockUnlock": "Sperren/Entsperren", + "unionSelection": "Auswahl vereinen", + "subtractSelection": "Auswahl subtrahieren", + "intersectSelection": "Auswahl schneiden", + "excludeSelection": "Auswahl ausschließen", + "booleanOperations": "Boolesche Operationen", "flipHorizontal": "Horizontal spiegeln", "flipVertical": "Vertikal spiegeln", - "flattenSelection": "Flatten", - "outlineText": "Outline text", - "outlineStroke": "Outline stroke" + "flattenSelection": "Abflachen", + "outlineText": "Text in Pfade umwandeln", + "outlineStroke": "Kontur in Pfad umwandeln" }, "tools": { "move": "Verschieben", diff --git a/packages/vue/src/locales/es.json b/packages/vue/src/locales/es.json index f5b751da5..ead3b3269 100644 --- a/packages/vue/src/locales/es.json +++ b/packages/vue/src/locales/es.json @@ -14,10 +14,13 @@ "autosave": "Guardado automático en archivo", "copy": "Copiar", "paste": "Pegar", - "zoomIn": "Ampliar", - "zoomOut": "Reducir", + "theme": "Tema", + "themeLight": "Claro", + "themeDark": "Oscuro", + "themeAuto": "Automático", "profiler": "Perfil de rendimiento", "language": "Idioma", + "toggleUI": "Alternar interfaz", "moveToPage": "Mover a página", "createInstance": "Crear instancia", "hide": "Ocultar", @@ -27,10 +30,10 @@ "cut": "Cortar", "front": "Al frente", "back": "Al fondo", - "toggleUI": "Alternar interfaz", "bold": "Negrita", "italic": "Cursiva", "underline": "Subrayado", + "strikethrough": "Tachado", "pasteHere": "Pegar aquí", "pasteToReplace": "Pegar y reemplazar", "copyPasteAs": "Copiar/Pegar como", @@ -42,8 +45,15 @@ "copyXPath": "Copiar XPath", "checkUpdates": "Buscar actualizaciones…", "booleanOperations": "Operaciones booleanas", - "strikethrough": "Tachado", - "closeTab": "Cerrar pestaña" + "closeTab": "Cerrar pestaña", + "zoomIn": "Ampliar", + "zoomOut": "Reducir", + "arrangeAlignLeft": "Alinear a la izquierda", + "arrangeAlignCenter": "Alinear al centro", + "arrangeAlignRight": "Alinear a la derecha", + "arrangeAlignTop": "Alinear arriba", + "arrangeAlignMiddle": "Alinear centro verticalmente", + "arrangeAlignBottom": "Alinear abajo" }, "commands": { "undo": "Deshacer", @@ -295,7 +305,7 @@ "updateInstallPrompt": "¿Descargar e instalar ahora? La app se reiniciará después de instalar la actualización.", "downloadingUpdate": "Descargando OpenPencil {version}", "updateInstalledTitle": "Actualización instalada", - "updateInstalled": "Se ha instalado la versión {version} de OpenPencil. Reiniciando ahora...", + "updateInstalled": "Se ha instalado la versión {version} de OpenPencil{size}. Reiniciando ahora...", "updateCheckFailed": "Error al encontrar actualizaciones: {error}", "updateUnavailable": "Las actualizaciones aún no están disponibles. Publica primero una versión firmada con latest.json.", "renameCollection": "Renombrar coleccion", diff --git a/packages/vue/src/locales/fr.json b/packages/vue/src/locales/fr.json index 810b8b06c..2754f45bc 100644 --- a/packages/vue/src/locales/fr.json +++ b/packages/vue/src/locales/fr.json @@ -17,6 +17,10 @@ "zoomIn": "Zoom avant", "zoomOut": "Zoom arrière", "profiler": "Profileur de performance", + "theme": "Thème", + "themeLight": "Clair", + "themeDark": "Sombre", + "themeAuto": "Automatique", "language": "Langue", "moveToPage": "Déplacer vers la page", "createInstance": "Créer une instance", @@ -32,7 +36,7 @@ "italic": "Italique", "underline": "Souligné", "pasteHere": "Coller ici", - "pasteToReplace": "Paste to replace", + "pasteToReplace": "Coller pour remplacer", "copyPasteAs": "Copier/Coller en tant que", "copyAsText": "Copier en texte", "copyAsSVG": "Copier en SVG", @@ -41,9 +45,15 @@ "copyNodeId": "Copier l'ID du nœud", "copyXPath": "Copier le XPath", "checkUpdates": "Rechercher des mises à jour…", - "booleanOperations": "Boolean operations", + "booleanOperations": "Opérations booléennes", "strikethrough": "Barré", - "closeTab": "Fermer l’onglet" + "closeTab": "Fermer l’onglet", + "arrangeAlignLeft": "Aligner à gauche", + "arrangeAlignCenter": "Centrer", + "arrangeAlignRight": "Aligner à droite", + "arrangeAlignTop": "Aligner en haut", + "arrangeAlignMiddle": "Centrer verticalement", + "arrangeAlignBottom": "Aligner en bas" }, "commands": { "undo": "Annuler", @@ -66,19 +76,19 @@ "zoomToFit": "Ajuster à l'écran", "zoomToSelection": "Zoom sur la sélection", "groupSelection": "Grouper", - "frameSelection": "Frame selection", - "showHide": "Visibilité", - "lockUnlock": "Verrouillage", - "unionSelection": "Union selection", - "subtractSelection": "Subtract selection", - "intersectSelection": "Intersect selection", - "excludeSelection": "Exclude selection", - "booleanOperations": "Boolean operations", + "frameSelection": "Mettre la sélection dans un cadre", + "showHide": "Afficher/Masquer", + "lockUnlock": "Verrouiller/Déverrouiller", + "unionSelection": "Union de la sélection", + "subtractSelection": "Soustraire la sélection", + "intersectSelection": "Intersection de la sélection", + "excludeSelection": "Exclure la sélection", + "booleanOperations": "Opérations booléennes", "flipHorizontal": "Retourner horizontalement", "flipVertical": "Retourner verticalement", - "flattenSelection": "Flatten", - "outlineText": "Outline text", - "outlineStroke": "Outline stroke" + "flattenSelection": "Aplatir", + "outlineText": "Vectoriser le texte", + "outlineStroke": "Vectoriser le contour" }, "tools": { "move": "Déplacer", diff --git a/packages/vue/src/locales/it.json b/packages/vue/src/locales/it.json index 6f0f8ba47..dab3a13ce 100644 --- a/packages/vue/src/locales/it.json +++ b/packages/vue/src/locales/it.json @@ -18,6 +18,10 @@ "zoomOut": "Riduci", "profiler": "Profilo prestazioni", "language": "Lingua", + "theme": "Tema", + "themeLight": "Chiaro", + "themeDark": "Scuro", + "themeAuto": "Automatico", "moveToPage": "Sposta nella pagina", "createInstance": "Crea istanza", "hide": "Nascondi", @@ -32,7 +36,7 @@ "italic": "Corsivo", "underline": "Sottolineato", "pasteHere": "Incolla qui", - "pasteToReplace": "Paste to replace", + "pasteToReplace": "Incolla per sostituire", "copyPasteAs": "Copia/Incolla come", "copyAsText": "Copia come testo", "copyAsSVG": "Copia come SVG", @@ -41,9 +45,15 @@ "copyNodeId": "Copia ID nodo", "copyXPath": "Copia XPath", "checkUpdates": "Controlla aggiornamenti…", - "booleanOperations": "Boolean operations", + "booleanOperations": "Operazioni booleane", "strikethrough": "Barrato", - "closeTab": "Chiudi scheda" + "closeTab": "Chiudi scheda", + "arrangeAlignLeft": "Allinea a sinistra", + "arrangeAlignCenter": "Centra", + "arrangeAlignRight": "Allinea a destra", + "arrangeAlignTop": "Allinea in alto", + "arrangeAlignMiddle": "Centra verticalmente", + "arrangeAlignBottom": "Allinea in basso" }, "commands": { "undo": "Annulla", @@ -66,19 +76,19 @@ "zoomToFit": "Adatta allo schermo", "zoomToSelection": "Zoom sulla selezione", "groupSelection": "Raggruppa", - "frameSelection": "Frame selection", - "showHide": "Visibilità", - "lockUnlock": "Blocco", - "unionSelection": "Union selection", - "subtractSelection": "Subtract selection", - "intersectSelection": "Intersect selection", - "excludeSelection": "Exclude selection", - "booleanOperations": "Boolean operations", + "frameSelection": "Inserisci selezione in cornice", + "showHide": "Mostra/Nascondi", + "lockUnlock": "Blocca/Sblocca", + "unionSelection": "Unisci selezione", + "subtractSelection": "Sottrai selezione", + "intersectSelection": "Interseca selezione", + "excludeSelection": "Escludi selezione", + "booleanOperations": "Operazioni booleane", "flipHorizontal": "Rifletti orizzontalmente", "flipVertical": "Rifletti verticalmente", - "flattenSelection": "Flatten", - "outlineText": "Outline text", - "outlineStroke": "Outline stroke" + "flattenSelection": "Appiattisci", + "outlineText": "Converti testo in tracciato", + "outlineStroke": "Converti traccia in contorno" }, "tools": { "move": "Sposta", diff --git a/packages/vue/src/locales/ja.json b/packages/vue/src/locales/ja.json new file mode 100644 index 000000000..94ae6e96c --- /dev/null +++ b/packages/vue/src/locales/ja.json @@ -0,0 +1,360 @@ +{ + "menu": { + "file": "ファイル", + "edit": "編集", + "view": "表示", + "object": "オブジェクト", + "arrange": "配置", + "text": "テキスト", + "new": "新規作成", + "open": "開く…", + "save": "保存", + "saveAs": "名前を付けて保存…", + "exportSelection": "選択範囲をエクスポート…", + "autosave": "ファイルに自動保存", + "copy": "コピー", + "paste": "貼り付け", + "theme": "テーマ", + "themeLight": "ライト", + "themeDark": "ダーク", + "themeAuto": "自動", + "profiler": "パフォーマンスプロファイラー", + "language": "言語", + "toggleUI": "UIの切り替え", + "moveToPage": "ページへ移動", + "createInstance": "インスタンスを作成", + "hide": "非表示", + "show": "表示", + "lock": "ロック", + "unlock": "ロック解除", + "cut": "切り取り", + "front": "最前面へ", + "back": "最背面へ", + "bold": "太字", + "italic": "斜体", + "underline": "下線", + "strikethrough": "打ち消し線", + "pasteHere": "ここに貼り付け", + "pasteToReplace": "貼り付けて置換", + "copyPasteAs": "形式を選択してコピー/貼り付け", + "copyAsText": "テキストとしてコピー", + "copyAsSVG": "SVGとしてコピー", + "copyAsPNG": "PNGとしてコピー", + "copyAsJSX": "JSXとしてコピー", + "copyNodeId": "ノードIDをコピー", + "copyXPath": "XPathをコピー", + "checkUpdates": "アップデートを確認…", + "booleanOperations": "パスの型抜き (ブーリアン演算)", + "closeTab": "タブを閉じる", + "zoomIn": "拡大", + "zoomOut": "縮小", + "arrangeAlignLeft": "左揃え", + "arrangeAlignCenter": "中央揃え", + "arrangeAlignRight": "右揃え", + "arrangeAlignTop": "上揃え", + "arrangeAlignMiddle": "上下中央揃え", + "arrangeAlignBottom": "下揃え" + }, + "commands": { + "undo": "元に戻す", + "redo": "やり直し", + "selectAll": "すべて選択", + "duplicate": "複製", + "delete": "削除", + "group": "グループ化", + "ungroup": "グループ解除", + "createComponent": "コンポーネントを作成", + "createComponentSet": "コンポーネントセットを作成", + "createInstance": "インスタンスを作成", + "detachInstance": "インスタンスの切り離し", + "goToMainComponent": "メインコンポーネントに移動", + "addAutoLayout": "オートレイアウトを追加", + "bringToFront": "最前面へ移動", + "sendToBack": "最背面へ移動", + "moveToPage": "ページへ移動", + "zoomTo100": "100%にズーム", + "zoomToFit": "画面に合わせる", + "zoomToSelection": "選択範囲にズーム", + "groupSelection": "グループ化", + "frameSelection": "選択範囲をフレーム化", + "showHide": "表示/非表示", + "lockUnlock": "ロック/ロック解除", + "unionSelection": "選択範囲を結合 (合体)", + "subtractSelection": "選択範囲を型抜き (型抜き)", + "intersectSelection": "選択範囲を交差 (交差)", + "excludeSelection": "選択範囲を中抜き (除外)", + "booleanOperations": "ブーリアン演算", + "flipHorizontal": "水平方向に反転", + "flipVertical": "垂直方向に反転", + "flattenSelection": "フラット化", + "outlineText": "テキストのアウトライン化", + "outlineStroke": "線の境界線をプレビュー (パスのアウトライン化)" + }, + "tools": { + "move": "移動", + "frame": "フレーム", + "section": "セクション", + "rectangle": "長方形", + "ellipse": "楕円", + "line": "直線", + "polygon": "多角形", + "star": "スター", + "pen": "ペンツール", + "text": "テキスト", + "hand": "手のひらツール" + }, + "panels": { + "untitled": "無題", + "nodeCopyString": " コピー", + "layers": "レイヤー", + "pages": "ページ", + "design": "デザイン", + "code": "コード", + "ai": "AI", + "assets": "アセット", + "page": "ページ", + "position": "位置", + "layout": "レイアウト", + "autoLayout": "オートレイアウト", + "alignment": "整列", + "appearance": "外観", + "xAxis": "X軸", + "yAxis": "Y軸", + "rotation": "回転", + "width": "幅", + "height": "高さ", + "opacity": "不透明度", + "radius": "角丸", + "spread": "スプレッド", + "fill": "塗り", + "stroke": "線", + "effects": "エフェクト", + "export": "エクスポート", + "typography": "タイポグラフィ", + "variables": "変数", + "constraints": "制約", + "addFill": "塗りを追加", + "addStroke": "線を追加", + "addEffect": "エフェクトを追加", + "addExport": "エクスポートを追加", + "dropShadow": "ドロップシャドウ", + "innerShadow": "インナーシャドウ", + "layerBlur": "レイヤーぼかし", + "backgroundBlur": "背景ぼかし", + "foregroundBlur": "ぼかし", + "strokeType": "線のタイプ", + "strokeWeight": "線の太さ", + "noSelection": "選択なし", + "noLocalVariables": "ローカル変数なし", + "openVariables": "変数を開く", + "addPage": "ページを追加", + "toggleVisibility": "表示/非表示の切り替え", + "independentCornerRadii": "個別の角丸", + "detachVariable": "変数のリンクを解除", + "applyVariable": "変数を適用", + "noVariablesFound": "変数が見つかりません", + "addAutoLayout": "オートレイアウトを追加", + "removeAutoLayout": "オートレイアウトを削除", + "mixed": "複数選択", + "layersCount": "{count} 個のレイヤー", + "goToMainComponent": "メインコンポーネントに移動", + "detachInstance": "インスタンスの切り離し", + "solid": "ソリッド (単色)", + "linearGradient": "線形グラデーション", + "radialGradient": "放射状グラデーション", + "image": "画像", + "stops": "カラーピッカーの分岐点", + "addStop": "分岐点を追加", + "alignLeft": "左揃え", + "alignCenter": "中央揃え", + "alignRight": "右揃え", + "alignTop": "上揃え", + "alignMiddle": "上下中央揃え", + "alignBottom": "下揃え", + "alignCenterHorizontally": "水平方向の中央揃え", + "alignCenterVertically": "垂直方向の中央揃え", + "flipHorizontal": "水平方向に反転", + "flipVertical": "垂直方向に反転", + "rotate90": "90°回転", + "mixedFillsHelp": "+ をクリックして混合塗りを置換", + "mixedStrokesHelp": "+ をクリックして混合線を置換", + "mixedEffectsHelp": "+ をクリックして混合エフェクトを置換", + "strokeSides": "線の位置", + "clipContent": "コンテンツをクリップ", + "colorFormatRgb": "RGB", + "colorFormatHsl": "HSL", + "colorFormatHsb": "HSB", + "colorFormatOkhcl": "OkHCL", + "colorHintHsl": "H 色相 · S 彩度 · L 輝度", + "colorHintHsb": "H 色相 · S 彩度 · B 明度", + "colorHintOkhcl": "H 色相 · C クロマ · L 輝度 · A アルファ", + "colorPreviewClipped": "プレビュー色域にクリップされました {space}", + "rulers": "定規", + "multiplayerCursors": "他の参加者のカーソル", + "direction": "方向", + "flow": "フロー", + "auto": "自動", + "columns": "列", + "rows": "行", + "gap": "間隔", + "sizingFixed": "固定", + "sizingHug": "コンテンツに合わせる", + "sizingFill": "コンテナを満たす", + "sizingHugShort": "合わせる", + "sizingFillShort": "満たす", + "sizingFillFr": "満たす (fr)", + "sizingFixedPx": "固定 (px)", + "strokeAlignInside": "内側", + "strokeAlignCenter": "中央", + "strokeAlignOutside": "外側", + "exportScale": "エクスポート倍率", + "exportFormat": "エクスポート形式", + "exportPreview": "プレビュー", + "exportRenderingPreview": "プレビューをレンダリング中…", + "createVariable": "変数を作成", + "createColorVariable": "{value} からカラー変数を作成", + "variableName": "変数名", + "create": "作成", + "createNumberVariable": "{value} から数値変数を作成", + "strokeDash": "破線", + "add": "追加", + "variants": "バリアント", + "gapAuto": "間隔自動", + "horizontalGap": "水平方向の間隔", + "verticalGap": "垂直方向の間隔", + "addMinWidth": "最小幅を追加", + "removeMinWidth": "最小幅を削除", + "addMaxWidth": "最大幅を追加", + "removeMaxWidth": "最大幅を削除", + "addMinHeight": "最小高さを追加", + "removeMinHeight": "最小高さを削除", + "addMaxHeight": "最大高さを追加", + "removeMaxHeight": "最大高さを削除", + "minWidthShort": "最小幅", + "maxWidthShort": "最大幅", + "minHeightShort": "最小高", + "maxHeightShort": "最大高", + "setToCurrentWidth": "現在の幅に設定", + "setToCurrentHeight": "現在の高さに設定", + "searchLocalComponents": "ローカルコンポーネントを検索", + "assetLibraryBadge": "ライブラリ", + "assetVariantSummary": "{count} 個のバリアント · {names}", + "duplicateVariantValues": "重複したバリアント値", + "openDocumentation": "ドキュメントを開く", + "noLocalComponents": "ローカルコンポーネントはありません", + "componentSet": "コンポーネントセット", + "component": "コンポーネント", + "insertInstance": "インスタンスを挿入", + "description": "説明", + "documentation": "ドキュメント", + "openDocs": "ドキュメントを開く", + "properties": "プロパティ", + "removeFill": "塗りを削除", + "removeStroke": "線を削除", + "removeEffect": "エフェクトを削除", + "removeExport": "エクスポートを削除", + "effectSettings": "エフェクト設定", + "expandEffectSettings": "エフェクト設定を展開", + "collapseEffectSettings": "エフェクト設定を折りたたむ", + "toggleExportPreview": "エクスポートプレビューの切り替え", + "searchFonts": "フォントを検索..." + }, + "pages": { + "newPage": "新しいページ", + "rename": "名前を変更", + "delete": "削除", + "pageName": "ページ {number}" + }, + "dialogs": { + "cancel": "キャンセル", + "apply": "適用", + "close": "閉じる", + "ok": "確定", + "copy": "コピー", + "copied": "コピーしました", + "createCollection": "コレクションを作成", + "localVariables": "ローカル変数", + "noVariableCollections": "変数コレクションがありません", + "selectLayerForJSX": "JSXコードを表示するレイヤーを選択してください", + "connectAIProvider": "チャットを始めるには、AIプロバイダーを接続してください。", + "connect": "接続", + "getAPIKey": "{provider} からAPIキーを取得 →", + "oneKeyManyModels": "1つのキーで、すべてのプロバイダーの100以上のモデルに対応。", + "describeChange": "変更内容を入力…", + "describeCreateOrChange": "作成または変更したい内容を入力してください。", + "stopGenerating": "生成を停止", + "sendMessage": "メッセージを送信", + "baseURLPlaceholder": "ベースURL (例: http://localhost:11434/v1)", + "modelIDPlaceholder": "モデルID (例: llama-3.3-70b)", + "yourName": "お名前", + "enterYourName": "名前を入力してください", + "shareThisFile": "このファイルを共有", + "joinRoom": "ルームに参加", + "join": "参加", + "roomLink": "ルームのリンク", + "joinCollaboration": "共同編集に参加", + "orJoinRoom": "またはルームに参加", + "pasteRoomLinkOrId": "ルームのリンクまたはIDを貼り付け", + "connected": "接続済み", + "search": "検索…", + "noResults": "結果がありません", + "share": "共有", + "appUpToDate": "OpenPencilは最新の状態です", + "updateAvailableTitle": "OpenPencilのアップデート", + "updateAvailable": "OpenPencil のバージョン {version} が利用可能です。", + "updateInstallPrompt": "今すぐダウンロードしてインストールしますか?インストール後、アプリが再起動します。", + "downloadingUpdate": "OpenPencil {version} をダウンロード中", + "updateInstalledTitle": "アップデート完了", + "updateInstalled": "OpenPencil のバージョン {version} がインストールされました{size}。再起動しています...", + "updateCheckFailed": "アップデートの確認中にエラーが発生しました: {error}", + "updateUnavailable": "アップデートはまだ利用できません。まず、latest.json を含む署名付きバージョンを公開してください。", + "renameCollection": "コレクションの名前を変更", + "deleteCollection": "コレクションを削除", + "modes": "モード", + "addMode": "モードを追加", + "renameMode": "モードの名前を変更", + "duplicateMode": "モードを複製", + "deleteMode": "モードを削除", + "setDefaultMode": "デフォルトに設定", + "aiProvider": "AIプロバイダー", + "providerSettings": "プロバイダー設定", + "done": "完了", + "apiKey": "APIキー", + "apiType": "APIタイプ", + "baseURL": "ベースURL", + "modelID": "モデルID", + "maxOutputTokens": "最大出力トークン数", + "clear": "クリア", + "keySavedReplace": "キーが保存されました - 上書きするには新しいキーを入力してください", + "getAPIKeyGeneric": "APIキーを取得 →", + "pexelsAPIKey": "PexelsのAPIキー (ストックフォト)", + "unsplashAccessKey": "Unsplashのアクセスキー", + "stockPhotoToolOptional": "任意 — stock_photoツール用", + "pexelsAlternativeOptional": "任意 — Pexelsの代替案", + "getPexelsAPIKey": "Pexelsの無料APIキーを取得 →", + "getUnsplashAccessKey": "Unsplashの無料アクセスキーを取得 →", + "completions": "入力補完", + "responses": "応答", + "copiedExclamation": "コピーしました!", + "copyMessage": "メッセージをコピー", + "copyJSXReference": "JSXのprops参照をクリップボードにコピー", + "newTab": "新しいタブ", + "closeTab": "{name} を閉じる", + "showUI": "UIを表示 ({shortcut})", + "fontSettings": "フォント設定", + "you": "あなた", + "youSuffix": "あなた", + "followingPeerStop": "{name} をフォロー中 (クリックして停止)", + "clickToFollowPeer": "クリックして {name} をフォロー" + }, + "variableTypes": { + "color": "カラー", + "colorHint": "塗りの値", + "number": "数値", + "numberHint": "サイズ、間隔、不透明度", + "text": "テキスト", + "textHint": "テキストとラベル", + "boolean": "ブーリアン (真偽値)", + "booleanHint": "真 (True) または 偽 (False)" + } +} diff --git a/packages/vue/src/locales/pl.json b/packages/vue/src/locales/pl.json index fe1d7d018..d6babfcc2 100644 --- a/packages/vue/src/locales/pl.json +++ b/packages/vue/src/locales/pl.json @@ -17,6 +17,10 @@ "zoomIn": "Powiększ", "zoomOut": "Pomniejsz", "profiler": "Profiler wydajności", + "theme": "Motyw", + "themeLight": "Jasny", + "themeDark": "Ciemny", + "themeAuto": "Automatycznie", "language": "Język", "moveToPage": "Przenieś na stronę", "createInstance": "Utwórz instancję", @@ -32,7 +36,7 @@ "italic": "Kursywa", "underline": "Podkreślenie", "pasteHere": "Wklej tutaj", - "pasteToReplace": "Paste to replace", + "pasteToReplace": "Wklej, aby zastąpić", "copyPasteAs": "Kopiuj/Wklej jako", "copyAsText": "Kopiuj jako tekst", "copyAsSVG": "Kopiuj jako SVG", @@ -41,9 +45,15 @@ "copyNodeId": "Kopiuj ID węzła", "copyXPath": "Kopiuj XPath", "checkUpdates": "Sprawdź aktualizacje…", - "booleanOperations": "Boolean operations", + "booleanOperations": "Operacje logiczne", "strikethrough": "Przekreślenie", - "closeTab": "Zamknij kartę" + "closeTab": "Zamknij kartę", + "arrangeAlignLeft": "Wyrównaj do lewej", + "arrangeAlignCenter": "Wyśrodkuj", + "arrangeAlignRight": "Wyrównaj do prawej", + "arrangeAlignTop": "Wyrównaj do góry", + "arrangeAlignMiddle": "Wyśrodkuj w pionie", + "arrangeAlignBottom": "Wyrównaj do dołu" }, "commands": { "undo": "Cofnij", @@ -66,19 +76,19 @@ "zoomToFit": "Dopasuj do ekranu", "zoomToSelection": "Zoom do zaznaczenia", "groupSelection": "Grupuj", - "frameSelection": "Frame selection", - "showHide": "Widoczność", - "lockUnlock": "Blokada", - "unionSelection": "Union selection", - "subtractSelection": "Subtract selection", - "intersectSelection": "Intersect selection", - "excludeSelection": "Exclude selection", - "booleanOperations": "Boolean operations", + "frameSelection": "Umieść zaznaczenie w ramce", + "showHide": "Pokaż/Ukryj", + "lockUnlock": "Zablokuj/Odblokuj", + "unionSelection": "Połącz zaznaczenie", + "subtractSelection": "Odejmij zaznaczenie", + "intersectSelection": "Przetnij zaznaczenie", + "excludeSelection": "Wyklucz zaznaczenie", + "booleanOperations": "Operacje logiczne", "flipHorizontal": "Odbij poziomo", "flipVertical": "Odbij pionowo", - "flattenSelection": "Flatten", - "outlineText": "Outline text", - "outlineStroke": "Outline stroke" + "flattenSelection": "Spłaszcz", + "outlineText": "Kontur tekstu", + "outlineStroke": "Kontur obrysu" }, "tools": { "move": "Przesuń", diff --git a/packages/vue/src/locales/ru.json b/packages/vue/src/locales/ru.json index 2e6b4b860..85db5e418 100644 --- a/packages/vue/src/locales/ru.json +++ b/packages/vue/src/locales/ru.json @@ -18,6 +18,10 @@ "zoomOut": "Уменьшить", "profiler": "Профилирование", "language": "Язык", + "theme": "Тема", + "themeLight": "Светлая", + "themeDark": "Тёмная", + "themeAuto": "Автоматически", "moveToPage": "Переместить на страницу", "createInstance": "Создать экземпляр", "hide": "Скрыть", @@ -32,7 +36,7 @@ "italic": "Курсив", "underline": "Подчёркнутый", "pasteHere": "Вставить сюда", - "pasteToReplace": "Paste to replace", + "pasteToReplace": "Вставить для замены", "copyPasteAs": "Копировать/Вставить как", "copyAsText": "Копировать как текст", "copyAsSVG": "Копировать как SVG", @@ -41,9 +45,15 @@ "copyNodeId": "Копировать ID узла", "copyXPath": "Копировать XPath", "checkUpdates": "Проверить обновления…", - "booleanOperations": "Boolean operations", + "booleanOperations": "Логические операции", "strikethrough": "Зачёркивание", - "closeTab": "Закрыть вкладку" + "closeTab": "Закрыть вкладку", + "arrangeAlignLeft": "Выровнять по левому краю", + "arrangeAlignCenter": "Выровнять по центру по горизонтали", + "arrangeAlignRight": "Выровнять по правому краю", + "arrangeAlignTop": "Выровнять по верхнему краю", + "arrangeAlignMiddle": "Выровнять по центру по вертикали", + "arrangeAlignBottom": "Выровнять по нижнему краю" }, "commands": { "undo": "Отменить", @@ -66,19 +76,19 @@ "zoomToFit": "Вписать в экран", "zoomToSelection": "Масштаб по выделению", "groupSelection": "Сгруппировать", - "frameSelection": "Frame selection", - "showHide": "Видимость", - "lockUnlock": "Блокировка", - "unionSelection": "Union selection", - "subtractSelection": "Subtract selection", - "intersectSelection": "Intersect selection", - "excludeSelection": "Exclude selection", - "booleanOperations": "Boolean operations", + "frameSelection": "Поместить выделение во фрейм", + "showHide": "Показать/Скрыть", + "lockUnlock": "Заблокировать/Разблокировать", + "unionSelection": "Объединить выделение", + "subtractSelection": "Вычесть выделение", + "intersectSelection": "Пересечь выделение", + "excludeSelection": "Исключить выделение", + "booleanOperations": "Логические операции", "flipHorizontal": "Отразить по горизонтали", "flipVertical": "Отразить по вертикали", - "flattenSelection": "Flatten", - "outlineText": "Outline text", - "outlineStroke": "Outline stroke" + "flattenSelection": "Сгладить", + "outlineText": "Преобразовать текст в контуры", + "outlineStroke": "Преобразовать обводку в контур" }, "tools": { "move": "Перемещение", diff --git a/packages/vue/src/locales/zh-CN.json b/packages/vue/src/locales/zh-CN.json index 9d4749c32..b5afaa350 100644 --- a/packages/vue/src/locales/zh-CN.json +++ b/packages/vue/src/locales/zh-CN.json @@ -17,6 +17,10 @@ "zoomIn": "放大", "zoomOut": "缩小", "profiler": "性能分析器", + "theme": "主题", + "themeLight": "浅色", + "themeDark": "深色", + "themeAuto": "跟随系统", "language": "语言", "moveToPage": "移动到页面", "createInstance": "创建实例", @@ -43,7 +47,13 @@ "checkUpdates": "检查更新…", "booleanOperations": "布尔运算", "strikethrough": "删除线", - "closeTab": "关闭标签页" + "closeTab": "关闭标签页", + "arrangeAlignLeft": "左对齐", + "arrangeAlignCenter": "水平居中", + "arrangeAlignRight": "右对齐", + "arrangeAlignTop": "顶部对齐", + "arrangeAlignMiddle": "垂直居中", + "arrangeAlignBottom": "底部对齐" }, "commands": { "undo": "撤销", diff --git a/src/app/shell/menu/app-menu.ts b/src/app/shell/menu/app-menu.ts index e7b692fa3..7ead26f86 100644 --- a/src/app/shell/menu/app-menu.ts +++ b/src/app/shell/menu/app-menu.ts @@ -1,12 +1,12 @@ import { computed } from 'vue' -import { useEditorCommands, useI18n } from '@open-pencil/vue' import type { MenuEntry } from '@open-pencil/vue' +import { useEditorCommands, useI18n } from '@open-pencil/vue' import { useEditorStore } from '@/app/editor/active-store' import { createSharedEditorMenuActions } from '@/app/shell/menu/editor-actions' -import { APP_MENU_SCHEMA } from '@/app/shell/menu/schema' import type { AppMenuActionItem, AppMenuEntry, AppMenuGroupSchema } from '@/app/shell/menu/schema' +import { APP_MENU_SCHEMA } from '@/app/shell/menu/schema' import { appMenuShortcutLabel } from '@/app/shell/menu/shortcut' import { openFileDialog } from '@/app/shell/menu/use' import { useAppTheme } from '@/app/shell/theme' @@ -43,7 +43,23 @@ export function useAppMenu() { paste: 'paste', 'paste-to-replace': 'pasteToReplace', language: 'language', - profiler: 'profiler' + profiler: 'profiler', + 'toggle-ui': 'toggleUI', + theme: 'theme', + 'theme-light': 'themeLight', + 'theme-dark': 'themeDark', + 'theme-auto': 'themeAuto', + 'zoom-in': 'zoomIn', + 'zoom-out': 'zoomOut', + 'text.bold': 'bold', + 'text.italic': 'italic', + 'text.underline': 'underline', + 'arrange.align-left': 'arrangeAlignLeft', + 'arrange.align-center': 'arrangeAlignCenter', + 'arrange.align-right': 'arrangeAlignRight', + 'arrange.align-top': 'arrangeAlignTop', + 'arrange.align-middle': 'arrangeAlignMiddle', + 'arrange.align-bottom': 'arrangeAlignBottom' } const languageMenu = computed(() => diff --git a/src/app/shell/menu/editor-actions.ts b/src/app/shell/menu/editor-actions.ts index 7e5f4bc08..4a3767cc2 100644 --- a/src/app/shell/menu/editor-actions.ts +++ b/src/app/shell/menu/editor-actions.ts @@ -29,7 +29,9 @@ export function selectedTextNode(): SceneNode | undefined { export function toggleSelectedTextBold(): void { const node = selectedTextNode() - updateSelectedText({ fontWeight: node && node.fontWeight >= 700 ? 400 : 700 }) + updateSelectedText({ + fontWeight: node && node.fontWeight >= 700 ? 400 : 700 + }) } export function toggleSelectedTextItalic(): void { @@ -59,11 +61,11 @@ export function createSharedEditorMenuActions( 'text.bold': toggleSelectedTextBold, 'text.italic': toggleSelectedTextItalic, 'text.underline': toggleSelectedTextUnderline, - 'align-left': () => alignSelected('horizontal', 'min'), - 'align-center': () => alignSelected('horizontal', 'center'), - 'align-right': () => alignSelected('horizontal', 'max'), - 'align-top': () => alignSelected('vertical', 'min'), - 'align-middle': () => alignSelected('vertical', 'center'), - 'align-bottom': () => alignSelected('vertical', 'max') + 'arrange.align-left': () => alignSelected('horizontal', 'min'), + 'arrange.align-center': () => alignSelected('horizontal', 'center'), + 'arrange.align-right': () => alignSelected('horizontal', 'max'), + 'arrange.align-top': () => alignSelected('vertical', 'min'), + 'arrange.align-middle': () => alignSelected('vertical', 'center'), + 'arrange.align-bottom': () => alignSelected('vertical', 'max') } } diff --git a/src/app/shell/menu/schema.ts b/src/app/shell/menu/schema.ts index 2dc968729..cb540c077 100644 --- a/src/app/shell/menu/schema.ts +++ b/src/app/shell/menu/schema.ts @@ -230,13 +230,13 @@ export const APP_MENU_SCHEMA = [ command: 'selection.wrapInAutoLayout' }, { type: 'separator' }, - { id: 'align-left', label: 'Align Left', shortcut: 'ALT+A' }, - { id: 'align-center', label: 'Align Center', shortcut: 'ALT+H' }, - { id: 'align-right', label: 'Align Right', shortcut: 'ALT+D' }, + { id: 'arrange.align-left', label: 'Align Left', shortcut: 'ALT+A' }, + { id: 'arrange.align-center', label: 'Align Center', shortcut: 'ALT+H' }, + { id: 'arrange.align-right', label: 'Align Right', shortcut: 'ALT+D' }, { type: 'separator' }, - { id: 'align-top', label: 'Align Top', shortcut: 'ALT+W' }, - { id: 'align-middle', label: 'Align Middle', shortcut: 'ALT+V' }, - { id: 'align-bottom', label: 'Align Bottom', shortcut: 'ALT+S' } + { id: 'arrange.align-top', label: 'Align Top', shortcut: 'ALT+W' }, + { id: 'arrange.align-middle', label: 'Align Middle', shortcut: 'ALT+V' }, + { id: 'arrange.align-bottom', label: 'Align Bottom', shortcut: 'ALT+S' } ] } ] satisfies AppMenuGroupSchema[]