From d6bf31cb3f6068e0660137888724dc536af7d38e Mon Sep 17 00:00:00 2001 From: ichi Date: Sun, 19 Apr 2026 20:44:07 +0900 Subject: [PATCH] feat(i18n): add Japanese locale and update translations for existing locales - Added Japanese (ja-JP) translations for common, editor, dialogs, launch, settings, shortcuts, and timeline. - Updated translations for existing locales (en, es, fr, ko-KR, tr, zh-CN, zh-TW) to include new keys for "showInFolder", "loadingVideo", "trim", and "speed". - Refactored VideoEditor and timeline Item components to utilize localized strings for various user interface elements and notifications. - Enhanced user experience by providing localized messages for project loading, exporting, and timeline actions. --- electron/i18n.ts | 25 ++- src/components/video-editor/VideoEditor.tsx | 46 +++-- src/components/video-editor/timeline/Item.tsx | 6 +- src/i18n/config.ts | 11 +- src/i18n/locales/en/common.json | 1 + src/i18n/locales/en/editor.json | 1 + src/i18n/locales/en/timeline.json | 2 + src/i18n/locales/es/common.json | 1 + src/i18n/locales/es/timeline.json | 2 + src/i18n/locales/fr/common.json | 1 + src/i18n/locales/fr/timeline.json | 2 + src/i18n/locales/ja-JP/common.json | 30 +++ src/i18n/locales/ja-JP/dialogs.json | 71 +++++++ src/i18n/locales/ja-JP/editor.json | 42 ++++ src/i18n/locales/ja-JP/launch.json | 43 ++++ src/i18n/locales/ja-JP/settings.json | 183 ++++++++++++++++++ src/i18n/locales/ja-JP/shortcuts.json | 37 ++++ src/i18n/locales/ja-JP/timeline.json | 55 ++++++ src/i18n/locales/ko-KR/common.json | 1 + src/i18n/locales/ko-KR/editor.json | 1 + src/i18n/locales/ko-KR/timeline.json | 2 + src/i18n/locales/tr/common.json | 1 + src/i18n/locales/tr/timeline.json | 2 + src/i18n/locales/zh-CN/common.json | 1 + src/i18n/locales/zh-CN/editor.json | 1 + src/i18n/locales/zh-CN/timeline.json | 2 + src/i18n/locales/zh-TW/common.json | 1 + src/i18n/locales/zh-TW/editor.json | 1 + src/i18n/locales/zh-TW/timeline.json | 2 + 29 files changed, 552 insertions(+), 22 deletions(-) create mode 100644 src/i18n/locales/ja-JP/common.json create mode 100644 src/i18n/locales/ja-JP/dialogs.json create mode 100644 src/i18n/locales/ja-JP/editor.json create mode 100644 src/i18n/locales/ja-JP/launch.json create mode 100644 src/i18n/locales/ja-JP/settings.json create mode 100644 src/i18n/locales/ja-JP/shortcuts.json create mode 100644 src/i18n/locales/ja-JP/timeline.json diff --git a/electron/i18n.ts b/electron/i18n.ts index 2dfb4d3..4222741 100644 --- a/electron/i18n.ts +++ b/electron/i18n.ts @@ -7,24 +7,45 @@ import commonEs from "../src/i18n/locales/es/common.json"; import dialogsEs from "../src/i18n/locales/es/dialogs.json"; import commonFr from "../src/i18n/locales/fr/common.json"; import dialogsFr from "../src/i18n/locales/fr/dialogs.json"; +import commonJa from "../src/i18n/locales/ja-JP/common.json"; +import dialogsJa from "../src/i18n/locales/ja-JP/dialogs.json"; +import commonKo from "../src/i18n/locales/ko-KR/common.json"; +import dialogsKo from "../src/i18n/locales/ko-KR/dialogs.json"; +import commonTr from "../src/i18n/locales/tr/common.json"; +import dialogsTr from "../src/i18n/locales/tr/dialogs.json"; import commonZh from "../src/i18n/locales/zh-CN/common.json"; import dialogsZh from "../src/i18n/locales/zh-CN/dialogs.json"; +import commonZhTw from "../src/i18n/locales/zh-TW/common.json"; +import dialogsZhTw from "../src/i18n/locales/zh-TW/dialogs.json"; -type Locale = "en" | "zh-CN" | "es" | "fr"; +type Locale = "en" | "zh-CN" | "zh-TW" | "es" | "fr" | "ja-JP" | "ko-KR" | "tr"; type Namespace = "common" | "dialogs"; type MessageMap = Record; const messages: Record> = { en: { common: commonEn, dialogs: dialogsEn }, "zh-CN": { common: commonZh, dialogs: dialogsZh }, + "zh-TW": { common: commonZhTw, dialogs: dialogsZhTw }, es: { common: commonEs, dialogs: dialogsEs }, fr: { common: commonFr, dialogs: dialogsFr }, + "ja-JP": { common: commonJa, dialogs: dialogsJa }, + "ko-KR": { common: commonKo, dialogs: dialogsKo }, + tr: { common: commonTr, dialogs: dialogsTr }, }; let currentLocale: Locale = "en"; export function setMainLocale(locale: string) { - if (locale === "en" || locale === "zh-CN" || locale === "es" || locale === "fr") { + if ( + locale === "en" || + locale === "zh-CN" || + locale === "zh-TW" || + locale === "es" || + locale === "fr" || + locale === "ja-JP" || + locale === "ko-KR" || + locale === "tr" + ) { currentLocale = locale; } } diff --git a/src/components/video-editor/VideoEditor.tsx b/src/components/video-editor/VideoEditor.tsx index 6d21d13..7b558ce 100644 --- a/src/components/video-editor/VideoEditor.tsx +++ b/src/components/video-editor/VideoEditor.tsx @@ -153,10 +153,10 @@ export default function VideoEditor() { const nextSpeedIdRef = useRef(1); const { shortcuts, isMac } = useShortcuts(); + const { locale, setLocale, t: rawT } = useI18n(); const t = useScopedT("editor"); const ts = useScopedT("settings"); const availableLocales = getAvailableLocales(); - const { locale, setLocale } = useI18n(); const nextAnnotationIdRef = useRef(1); const nextAnnotationZIndexRef = useRef(1); @@ -361,7 +361,10 @@ export default function VideoEditor() { setLastSavedSnapshot( createProjectSnapshot( webcamSourcePath - ? { screenVideoPath: sourcePath, webcamVideoPath: webcamSourcePath } + ? { + screenVideoPath: sourcePath, + webcamVideoPath: webcamSourcePath, + } : { screenVideoPath: sourcePath }, INITIAL_EDITOR_STATE, ), @@ -547,18 +550,18 @@ export default function VideoEditor() { } if (!result.success) { - toast.error(result.message || "Failed to load project"); + toast.error(result.message || t("project.failedToLoad")); return; } const restored = await applyLoadedProject(result.project, result.path ?? null); if (!restored) { - toast.error("Invalid project file format"); + toast.error(t("project.invalidFormat")); return; } - toast.success(`Project loaded from ${result.path}`); - }, [applyLoadedProject]); + toast.success(t("project.loadedFrom", { path: result.path ?? "" })); + }, [applyLoadedProject, t]); useEffect(() => { const removeLoadListener = window.electronAPI.onMenuLoadProject(handleLoadProject); @@ -961,7 +964,11 @@ export default function VideoEditor() { pushState((prev) => ({ zoomRegions: prev.zoomRegions.map((region) => region.id === id - ? { ...region, zoomInDurationMs: zoomIn, zoomOutDurationMs: zoomOut } + ? { + ...region, + zoomInDurationMs: zoomIn, + zoomOutDurationMs: zoomOut, + } : region, ), })); @@ -1295,17 +1302,22 @@ export default function VideoEditor() { const handleExportSaved = useCallback( (formatLabel: "GIF" | "Video", filePath: string) => { setExportedFilePath(filePath); - toast.success(`${formatLabel} exported successfully`, { - description: filePath, - action: { - label: "Show in Folder", - onClick: () => { - void handleShowExportedFile(filePath); + toast.success( + t("export.exportedSuccessfully", { + format: formatLabel, + }), + { + description: filePath, + action: { + label: rawT("common.actions.showInFolder"), + onClick: () => { + void handleShowExportedFile(filePath); + }, }, }, - }); + ); }, - [handleShowExportedFile], + [handleShowExportedFile, t, rawT], ); const handleSaveUnsavedExport = useCallback(async () => { @@ -1679,7 +1691,7 @@ export default function VideoEditor() { if (loading) { return (
-
Loading video...
+
{t("loadingVideo")}
); } @@ -1693,7 +1705,7 @@ export default function VideoEditor() { onClick={handleLoadProject} className="px-3 py-1.5 rounded-md bg-[#34B27B] text-white text-sm hover:bg-[#34B27B]/90" > - Load Project File + {ts("project.load")} diff --git a/src/components/video-editor/timeline/Item.tsx b/src/components/video-editor/timeline/Item.tsx index d89de94..aeca711 100644 --- a/src/components/video-editor/timeline/Item.tsx +++ b/src/components/video-editor/timeline/Item.tsx @@ -2,6 +2,7 @@ import type { Span } from "dnd-timeline"; import { useItem, useTimelineContext } from "dnd-timeline"; import { Gauge, MessageSquare, Scissors, ZoomIn } from "lucide-react"; import { useMemo } from "react"; +import { useScopedT } from "@/contexts/I18nContext"; import { cn } from "@/lib/utils"; import { DEFAULT_ZOOM_IN_MS, @@ -59,6 +60,7 @@ export default function Item({ children, onZoomDurationChange, }: ItemProps) { + const t = useScopedT("timeline"); const { pixelsToValue } = useTimelineContext(); const { setNodeRef, attributes, listeners, itemStyle, itemContentStyle } = useItem({ id, @@ -251,14 +253,14 @@ export default function Item({ <> - Trim + {t("labels.trim")} ) : isSpeed ? ( <> - {speedValue !== undefined ? `${speedValue}×` : "Speed"} + {speedValue !== undefined ? `${speedValue}×` : t("labels.speed")} ) : ( diff --git a/src/i18n/config.ts b/src/i18n/config.ts index 03761c8..788a315 100644 --- a/src/i18n/config.ts +++ b/src/i18n/config.ts @@ -1,5 +1,14 @@ export const DEFAULT_LOCALE = "en" as const; -export const SUPPORTED_LOCALES = ["en", "zh-CN", "zh-TW", "es", "fr", "tr", "ko-KR"] as const; +export const SUPPORTED_LOCALES = [ + "en", + "zh-CN", + "zh-TW", + "es", + "fr", + "tr", + "ko-KR", + "ja-JP", +] as const; export const I18N_NAMESPACES = [ "common", "dialogs", diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index fdc65e6..cdefe84 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -9,6 +9,7 @@ "open": "Open", "upload": "Upload", "export": "Export", + "showInFolder": "Show in Folder", "file": "File", "edit": "Edit", "view": "View", diff --git a/src/i18n/locales/en/editor.json b/src/i18n/locales/en/editor.json index ea2ceaa..cbff4a9 100644 --- a/src/i18n/locales/en/editor.json +++ b/src/i18n/locales/en/editor.json @@ -5,6 +5,7 @@ "cancel": "Cancel", "confirm": "Confirm" }, + "loadingVideo": "Loading video...", "errors": { "noVideoLoaded": "No video loaded", "videoNotReady": "Video not ready", diff --git a/src/i18n/locales/en/timeline.json b/src/i18n/locales/en/timeline.json index b4d5bd8..389184b 100644 --- a/src/i18n/locales/en/timeline.json +++ b/src/i18n/locales/en/timeline.json @@ -17,6 +17,8 @@ "labels": { "pan": "Pan", "zoom": "Zoom", + "trim": "Trim", + "speed": "Speed", "zoomItem": "Zoom {{index}}", "trimItem": "Trim {{index}}", "speedItem": "Speed {{index}}", diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index a6f61e7..13cccb0 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -9,6 +9,7 @@ "open": "Abrir", "upload": "Subir", "export": "Exportar", + "showInFolder": "Mostrar en carpeta", "file": "Archivo", "edit": "Editar", "view": "Vista", diff --git a/src/i18n/locales/es/timeline.json b/src/i18n/locales/es/timeline.json index 12a83b0..1a1abe1 100644 --- a/src/i18n/locales/es/timeline.json +++ b/src/i18n/locales/es/timeline.json @@ -17,6 +17,8 @@ "labels": { "pan": "Desplazar", "zoom": "Zoom", + "trim": "Recortar", + "speed": "Velocidad", "zoomItem": "Zoom {{index}}", "trimItem": "Recorte {{index}}", "speedItem": "Velocidad {{index}}", diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index 7eb7f83..5d09214 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -9,6 +9,7 @@ "open": "Ouvrir", "upload": "Téléverser", "export": "Exporter", + "showInFolder": "Afficher dans le dossier", "file": "Fichier", "edit": "Éditer", "view": "Affichage", diff --git a/src/i18n/locales/fr/timeline.json b/src/i18n/locales/fr/timeline.json index 5985ea6..b4c6e16 100644 --- a/src/i18n/locales/fr/timeline.json +++ b/src/i18n/locales/fr/timeline.json @@ -17,6 +17,8 @@ "labels": { "pan": "Panoramique", "zoom": "Zoom", + "trim": "Couper", + "speed": "Vitesse", "zoomItem": "Zoom {{index}}", "trimItem": "Coupe {{index}}", "speedItem": "Vitesse {{index}}", diff --git a/src/i18n/locales/ja-JP/common.json b/src/i18n/locales/ja-JP/common.json new file mode 100644 index 0000000..ee2205a --- /dev/null +++ b/src/i18n/locales/ja-JP/common.json @@ -0,0 +1,30 @@ +{ + "actions": { + "cancel": "キャンセル", + "save": "保存", + "delete": "削除", + "close": "閉じる", + "share": "共有", + "done": "完了", + "open": "開く", + "upload": "アップロード", + "export": "エクスポート", + "showInFolder": "フォルダに表示", + "file": "ファイル", + "edit": "編集", + "view": "表示", + "window": "ウィンドウ", + "quit": "終了", + "stopRecording": "録画停止" + }, + "playback": { + "play": "再生", + "pause": "一時停止", + "fullscreen": "全画面表示", + "exitFullscreen": "全画面表示を終了" + }, + "locale": { + "name": "日本語", + "short": "JA" + } +} diff --git a/src/i18n/locales/ja-JP/dialogs.json b/src/i18n/locales/ja-JP/dialogs.json new file mode 100644 index 0000000..3c3fce5 --- /dev/null +++ b/src/i18n/locales/ja-JP/dialogs.json @@ -0,0 +1,71 @@ +{ + "export": { + "complete": "エクスポート完了", + "yourFormatReady": "あなたの{{format}}が準備できました", + "showInFolder": "フォルダで表示", + "finalizingVideo": "ビデオのエクスポートを最終処理中...", + "compilingGifProgress": "GIFをコンパイル中... {{progress}}%", + "compilingGifWait": "GIFをコンパイル中... しばらくお待ちください", + "takeMoment": "少々お待ちください...", + "failed": "エクスポートに失敗しました", + "tryAgain": "もう一度お試しください", + "finalizingVideoTitle": "ビデオの最終処理", + "compilingGif": "GIFをコンパイル中", + "exportingFormat": "{{format}}をエクスポート中", + "compiling": "コンパイル中", + "renderingFrames": "フレームをレンダリング中", + "processing": "処理中...", + "finalizing": "最終処理中...", + "compilingStatus": "コンパイル中...", + "status": "ステータス", + "format": "フォーマット", + "frames": "フレーム", + "cancelExport": "エクスポートをキャンセル", + "savedSuccessfully": "{{format}}を正常に保存しました!" + }, + "tutorial": { + "triggerLabel": "トリミングの仕組み", + "title": "トリミングの仕組み", + "description": "動画の不要な部分を削除する方法について解説します。", + "explanationBefore": "トリムツールは、動画から", + "remove": "「削除したい部分」", + "explanationMiddle": "を指定することで機能します。エクスポート時には、赤い枠で", + "covered": "囲まれた部分", + "explanationAfter": "がすべてカットされます。", + "visualExample": "視覚的な例", + "removed": "削除", + "kept": "保持", + "part1": "パート 1", + "part2": "パート 2", + "part3": "パート 3", + "finalVideo": "完成動画", + "step1Title": "1. 削除範囲を追加", + "step1DescriptionBefore": "キーボードの", + "step1DescriptionAfter": "、またはハサミのアイコンをクリックして、削除したい範囲を指定します。", + + "step2Title": "2. 範囲を調整", + "step2Description": "赤い領域の両端をドラッグして、削除したい範囲を正確に調整します。" + }, + "unsavedChanges": { + "title": "未保存の変更", + "message": "未保存の変更があります。", + "detail": "閉じる前にプロジェクトを保存しますか?", + "saveAndClose": "保存して閉じる", + "discardAndClose": "破棄して閉じる", + "loadProject": "プロジェクトを読み込む…", + "saveProject": "プロジェクトを保存…", + "saveProjectAs": "プロジェクトを名前を付けて保存…" + }, + "fileDialogs": { + "saveGif": "エクスポートしたGIFを保存", + "saveVideo": "エクスポートしたビデオを保存", + "selectVideo": "ビデオファイルを選択", + "saveProject": "OpenScreen プロジェクトを保存", + "openProject": "OpenScreen プロジェクトを開く", + "gifImage": "GIF 画像", + "mp4Video": "MP4 ビデオ", + "videoFiles": "ビデオファイル", + "openscreenProject": "OpenScreen プロジェクト", + "allFiles": "すべてのファイル" + } +} diff --git a/src/i18n/locales/ja-JP/editor.json b/src/i18n/locales/ja-JP/editor.json new file mode 100644 index 0000000..1501230 --- /dev/null +++ b/src/i18n/locales/ja-JP/editor.json @@ -0,0 +1,42 @@ +{ + "newRecording": { + "title": "レコーダーに戻る", + "description": "現在の作業内容が保存されました。", + "cancel": "キャンセル", + "confirm": "確認" + }, + "loadingVideo": "ビデオを読み込み中...", + "errors": { + "noVideoLoaded": "ビデオが読み込まれていません", + "videoNotReady": "ビデオが準備できていません", + "unableToDetermineSourcePath": "ソースビデオのパスを特定できません", + "failedToSaveGif": "GIFの保存に失敗しました", + "gifExportFailed": "GIFのエクスポートに失敗しました", + "failedToSaveVideo": "ビデオの保存に失敗しました", + "exportFailed": "エクスポートに失敗しました", + "exportFailedWithError": "エクスポートに失敗しました: {{error}}", + "failedToSaveExport": "エクスポートの保存に失敗しました", + "failedToSaveExportedVideo": "エクスポートしたビデオの保存に失敗しました", + "failedToRevealInFolder": "フォルダの表示に失敗しました: {{error}}" + }, + "export": { + "canceled": "エクスポートがキャンセルされました", + "exportedSuccessfully": "{{format}}を正常にエクスポートしました" + }, + "project": { + "saveCanceled": "プロジェクトの保存がキャンセルされました", + "failedToSave": "プロジェクトの保存に失敗しました", + "savedTo": "プロジェクトを保存しました: {{path}}", + "failedToLoad": "プロジェクトの読み込みに失敗しました", + "invalidFormat": "無効なプロジェクトファイル形式です", + "loadedFrom": "プロジェクトを読み込みました: {{path}}" + }, + "recording": { + "failedCameraAccess": "カメラのアクセス要求に失敗しました。", + "cameraBlocked": "カメラのアクセスがブロックされています。システム設定で有効にして、ウェブカメラを使用してください。", + "systemAudioUnavailable": "システムオーディオが利用できません。システムオーディオなしで録画します。", + "microphoneDenied": "マイクのアクセスが拒否されました。オーディオなしで録画を続行します。", + "cameraDenied": "カメラのアクセスが拒否されました。ウェブカメラなしで録画を続行します。", + "permissionDenied": "録画の権限が拒否されました。画面録画を許可してください。" + } +} diff --git a/src/i18n/locales/ja-JP/launch.json b/src/i18n/locales/ja-JP/launch.json new file mode 100644 index 0000000..4504b00 --- /dev/null +++ b/src/i18n/locales/ja-JP/launch.json @@ -0,0 +1,43 @@ +{ + "tooltips": { + "hideHUD": "HUDを隠す", + "closeApp": "アプリを閉じる", + "restartRecording": "録画を再開", + "cancelRecording": "録画をキャンセル", + "pauseRecording": "録画を一時停止", + "resumeRecording": "録画を再開", + "openVideoFile": "ビデオファイルを開く", + "openProject": "プロジェクトを開く" + }, + "audio": { + "enableSystemAudio": "システムオーディオを有効にする", + "disableSystemAudio": "システムオーディオを無効にする", + "enableMicrophone": "マイクを有効にする", + "disableMicrophone": "マイクを無効にする", + "defaultMicrophone": "デフォルトのマイク" + }, + "webcam": { + "enableWebcam": "ウェブカメラを有効にする", + "disableWebcam": "ウェブカメラを無効にする", + "defaultCamera": "デフォルトのカメラ", + "searching": "検索中...", + "noneFound": "カメラが見つかりません", + "unavailable": "カメラが利用できません" + }, + "sourceSelector": { + "loading": "ソースを読み込み中...", + "screens": "画面 ({{count}})", + "windows": "ウィンドウ ({{count}})", + "defaultSourceName": "画面" + }, + "recording": { + "selectSource": "録画するソースを選択してください" + }, + "language": "言語", + "systemLanguagePrompt": { + "title": "システム言語を使用しますか?", + "description": "システム言語として{{language}}が検出されました。OpenScreenを{{language}}に切り替えますか?", + "switch": "{{language}}に切り替え", + "keepDefault": "現在の言語を保持" + } +} diff --git a/src/i18n/locales/ja-JP/settings.json b/src/i18n/locales/ja-JP/settings.json new file mode 100644 index 0000000..9cad3ef --- /dev/null +++ b/src/i18n/locales/ja-JP/settings.json @@ -0,0 +1,183 @@ +{ + "zoom": { + "level": "ズーム倍率", + "selectRegion": "ズーム範囲を選択して調整", + "deleteZoom": "ズームを削除", + "focusMode": { + "title": "フォーカスモード", + "manual": "手動", + "auto": "自動", + "autoDescription": "カメラが録画中のカーソル位置に追従します" + }, + "speed": { + "title": "ズーム速度", + "instant": "即時", + "fast": "高速", + "smooth": "滑らか", + "lazy": "遅延" + } + }, + "speed": { + "playbackSpeed": "再生速度", + "selectRegion": "速度範囲を選択して調整", + "deleteRegion": "速度範囲を削除", + "customPlaybackSpeed": "カスタム再生速度", + "maxSpeedError": "速度は16×を超えることはできません" + }, + "trim": { + "deleteRegion": "トリム範囲を削除" + }, + "layout": { + "title": "レイアウト", + "preset": "プリセット", + "selectPreset": "プリセットを選択", + "pictureInPicture": "ピクチャーインピクチャー", + "verticalStack": "縦積み", + "dualFrame": "デュアルフレーム", + "webcamShape": "カメラの形状", + "webcamSize": "カメラのサイズ" + }, + "effects": { + "title": "ビデオ効果", + "blurBg": "背景をぼかす", + "motionBlur": "モーションブラー", + "off": "オフ", + "shadow": "影", + "roundness": "丸み", + "padding": "余白" + }, + "background": { + "title": "背景", + "image": "画像", + "color": "色", + "gradient": "グラデーション", + "uploadCustom": "カスタムをアップロード", + "gradientLabel": "グラデーション {{index}}" + }, + "crop": { + "title": "クロップ", + "cropVideo": "ビデオをクロップ", + "dragInstruction": "各辺をドラッグしてクロップ範囲を調整", + "ratio": "比率", + "free": "自由", + "done": "完了", + "lockAspectRatio": "アスペクト比を固定", + "unlockAspectRatio": "アスペクト比の固定を解除" + }, + "exportFormat": { + "mp4": "MP4", + "gif": "GIF", + "mp4Video": "MP4 ビデオ", + "mp4Description": "高品質のビデオファイル", + "gifAnimation": "GIF アニメーション", + "gifDescription": "共有用のアニメーション画像" + }, + "exportQuality": { + "title": "エクスポート品質", + "low": "低画質", + "medium": "中画質", + "high": "高画質" + }, + "gifSettings": { + "frameRate": "GIF フレームレート", + "size": "GIF サイズ", + "loop": "GIF をループする" + }, + "project": { + "save": "プロジェクトを保存", + "load": "プロジェクトを読み込む" + }, + "export": { + "videoButton": "ビデオをエクスポート", + "gifButton": "GIF をエクスポート", + "chooseSaveLocation": "保存場所を選択" + }, + "links": { + "reportBug": "バグを報告", + "starOnGithub": "GitHub でスターを付ける" + }, + "imageUpload": { + "invalidFileType": "無効なファイル形式", + "jpgOnly": "JPG または JPEG 画像ファイルをアップロードしてください。", + "uploadSuccess": "カスタム画像が正常にアップロードされました!", + "failedToUpload": "画像のアップロードに失敗しました", + "errorReading": "ファイルの読み取り中にエラーが発生しました。" + }, + "annotation": { + "title": "注釈設定", + "active": "アクティブ", + "typeText": "テキスト", + "typeImage": "画像", + "typeArrow": "矢印", + "typeBlur": "ぼかし", + "textContent": "テキスト内容", + "textPlaceholder": "テキストを入力してください...", + "fontStyle": "フォントスタイル", + "selectStyle": "スタイルを選択", + "size": "サイズ", + "customFonts": "カスタムフォント", + "textColor": "文字色", + "background": "背景", + "none": "なし", + "color": "色", + "clearBackground": "背景をクリア", + "uploadImage": "画像をアップロード", + "supportedFormats": "サポートされている形式: JPG, PNG, GIF, WebP", + "arrowDirection": "矢印の方向", + "strokeWidth": "線の太さ: {{width}}px", + "arrowColor": "矢印の色", + "blurType": "ぼかしの種類", + "blurTypeBlur": "ぼかし", + "blurTypeMosaic": "モザイクぼかし", + "blurColor": "ぼかしの色", + "blurColorWhite": "白", + "blurColorBlack": "黒", + "blurShape": "ぼかしの形状", + "blurIntensity": "ぼかしの強さ", + "mosaicBlockSize": "モザイクブロックのサイズ", + "blurShapeRectangle": "長方形", + "blurShapeOval": "楕円", + "blurShapeFreehand": "自由形状", + "deleteAnnotation": "注釈を削除", + "shortcutsAndTips": "ショートカットとヒント", + "tipMovePlayhead": "重なっている注釈セクションに再生ヘッドを移動し、項目を選択します。", + "tipTabCycle": "Tabキーを使用して重なっている項目を順に切り替えます。", + "tipShiftTabCycle": "Shift+Tabキーを使用して逆順に切り替えます。", + "invalidImageType": "無効なファイル形式", + "imageFormatsOnly": "JPG、PNG、GIF、またはWebP画像ファイルをアップロードしてください。", + "imageUploadSuccess": "画像が正常にアップロードされました!", + "failedImageUpload": "画像のアップロードに失敗しました" + }, + "fontStyles": { + "classic": "クラシック", + "editor": "エディター", + "strong": "ストロング", + "typewriter": "タイプライター", + "deco": "デコ", + "simple": "シンプル", + "modern": "モダン", + "clean": "クリーン" + }, + "customFont": { + "dialogTitle": "Googleフォントを追加", + "urlLabel": "GoogleフォントのインポートURL", + "urlPlaceholder": "https://fonts.googleapis.com/css2?family=Roboto&display=swap", + "urlHelp": "Googleフォントから取得: フォントを選択 → 「フォントを取得」をクリック → @import URLをコピー", + "nameLabel": "表示名", + "namePlaceholder": "マイカスタムフォント", + "nameHelp": "フォントセレクターに表示される名前です", + "addButton": "フォントを追加", + "addingButton": "追加中...", + "errorEmptyUrl": "GoogleフォントのインポートURLを入力してください", + "errorInvalidUrl": "有効なGoogleフォントURLを入力してください", + "errorEmptyName": "フォント名を入力してください", + "errorExtractFailed": "URLからフォントファミリーを抽出できませんでした", + "successMessage": "フォント \"{{fontName}}\" が正常に追加されました", + "failedToAdd": "フォントの追加に失敗しました", + "errorTimeout": "フォントの読み込みに時間がかかりすぎました。URLを確認して再試行してください。", + "errorLoadFailed": "フォントを読み込めませんでした。GoogleフォントのURLが正しいことを確認してください。" + }, + "language": { + "title": "言語" + } +} diff --git a/src/i18n/locales/ja-JP/shortcuts.json b/src/i18n/locales/ja-JP/shortcuts.json new file mode 100644 index 0000000..d4b4a90 --- /dev/null +++ b/src/i18n/locales/ja-JP/shortcuts.json @@ -0,0 +1,37 @@ +{ + "title": "キーボードショートカット", + "customize": "カスタマイズ", + "configurable": "設定可能", + "fixed": "固定", + "pressKey": "キーを押してください…", + "clickToChange": "クリックして変更", + "pressEscToCancel": "Escキーを押してキャンセル", + "helpText": "ショートカットをクリックして新しいキーの組み合わせを押します。Escキーを押してキャンセルします。", + "resetToDefaults": "デフォルトにリセット", + "alreadyUsedBy": "すでに {{action}} に使用されています", + "swap": "入れ替え", + "reservedShortcut": "このショートカットは \"{{label}}\" に予約されており、再割り当てできません。", + "savedToast": "キーボードショートカットが保存されました", + "resetToast": "デフォルトのショートカットにリセット — 保存をクリックして適用", + "actions": { + "addZoom": "ズームを追加", + "addTrim": "トリムを追加", + "addSpeed": "速度を追加", + "addAnnotation": "注釈を追加", + "addBlur": "ぼかしを追加", + "addKeyframe": "キーフレームを追加", + "deleteSelected": "選択を削除", + "playPause": "再生 / 一時停止" + }, + "fixedActions": { + "undo": "元に戻す", + "redo": "やり直す", + "cycleAnnotationsForward": "注釈を順に切り替え", + "cycleAnnotationsBackward": "注釈を逆順に切り替え", + "deleteSelectedAlt": "選択を削除 (alt)", + "panTimeline": "タイムラインをパン", + "zoomTimeline": "タイムラインをズーム", + "frameBack": "フレームを戻す", + "frameForward": "フレームを進める" + } +} diff --git a/src/i18n/locales/ja-JP/timeline.json b/src/i18n/locales/ja-JP/timeline.json new file mode 100644 index 0000000..e0507f6 --- /dev/null +++ b/src/i18n/locales/ja-JP/timeline.json @@ -0,0 +1,55 @@ +{ + "buttons": { + "addZoom": "ズームを追加 (Z)", + "suggestZooms": "カーソル位置からズームを提案", + "addTrim": "トリムを追加 (T)", + "addAnnotation": "注釈を追加 (A)", + "addBlur": "ぼかしを追加 (B)", + "addSpeed": "速度を追加 (S)" + }, + "hints": { + "pressZoom": "Zキーを押してズームを追加", + "pressTrim": "Tキーを押してトリムを追加", + "pressAnnotation": "Aキーを押して注釈を追加", + "pressBlur": "Bキーを押してぼかしを追加", + "pressSpeed": "Sキーを押して速度を追加" + }, + "labels": { + "pan": "移動", + "zoom": "ズーム", + "trim": "トリム", + "speed": "速度", + "zoomItem": "ズーム {{index}}", + "trimItem": "トリム {{index}}", + "speedItem": "速度 {{index}}", + "annotationItem": "注釈", + "blurItem": "ぼかし {{index}}", + "imageItem": "画像", + "emptyText": "空のテキスト" + }, + "emptyState": { + "noVideo": "ビデオが読み込まれていません", + "dragAndDrop": "ビデオをドラッグアンドドロップして編集を開始してください" + }, + "errors": { + "cannotPlaceZoom": "ここにズームを配置できません", + "zoomExistsAtLocation": "この場所にはすでにズームが存在するか、十分なスペースがありません。", + "zoomSuggestionUnavailable": "ズームの自動提案機能が利用できません", + "noCursorTelemetry": "カーソルの動きが記録されていません", + "noCursorTelemetryDescription": "まず画面収録を行い、カーソルに基づく提案を生成してください。", + "noUsableTelemetry": "使用可能なカーソルの動きデータがありません", + "noUsableTelemetryDescription": "録画には十分なカーソルの動きデータが含まれていません。", + "noDwellMoments": "カーソルが静止したポイントが見つかりません", + "noDwellMomentsDescription": "強調したい操作の際に、カーソルを一時停止させて録画してみてください。", + "noAutoZoomSlots": "自動ズームを適用できる箇所がありません", + "noAutoZoomSlotsDescription": "検出された滞留ポイントが既存のズーム領域と重なっています。", + "cannotPlaceTrim": "ここに切り取りを配置できません", + "trimExistsAtLocation": "この場所にはすでに切り取りが存在するか、十分なスペースがありません。", + "cannotPlaceSpeed": "ここに速度を配置できません", + "speedExistsAtLocation": "この場所にはすでに速度が存在するか、十分なスペースがありません。" + }, + "success": { + "addedZoomSuggestions": "カーソルに基づくズーム提案を {{count}} 件追加しました", + "addedZoomSuggestionsPlural": "カーソルに基づくズーム提案を {{count}} 件追加しました" + } +} diff --git a/src/i18n/locales/ko-KR/common.json b/src/i18n/locales/ko-KR/common.json index b83cb44..5d90118 100644 --- a/src/i18n/locales/ko-KR/common.json +++ b/src/i18n/locales/ko-KR/common.json @@ -9,6 +9,7 @@ "open": "열기", "upload": "업로드", "export": "내보내기", + "showInFolder": "폴더에 표시", "file": "파일", "edit": "편집", "view": "보기", diff --git a/src/i18n/locales/ko-KR/editor.json b/src/i18n/locales/ko-KR/editor.json index 4db7d1f..5d02772 100644 --- a/src/i18n/locales/ko-KR/editor.json +++ b/src/i18n/locales/ko-KR/editor.json @@ -5,6 +5,7 @@ "cancel": "취소", "confirm": "확인" }, + "loadingVideo": "비디오 로드 중...", "errors": { "noVideoLoaded": "불러온 비디오가 없습니다", "videoNotReady": "비디오가 준비되지 않았습니다", diff --git a/src/i18n/locales/ko-KR/timeline.json b/src/i18n/locales/ko-KR/timeline.json index 167c26f..7009e68 100644 --- a/src/i18n/locales/ko-KR/timeline.json +++ b/src/i18n/locales/ko-KR/timeline.json @@ -15,6 +15,8 @@ "labels": { "pan": "이동", "zoom": "줌", + "trim": "트림", + "speed": "속도", "zoomItem": "줌 {{index}}", "trimItem": "트림 {{index}}", "speedItem": "속도 {{index}}", diff --git a/src/i18n/locales/tr/common.json b/src/i18n/locales/tr/common.json index 3ec132c..13d006b 100644 --- a/src/i18n/locales/tr/common.json +++ b/src/i18n/locales/tr/common.json @@ -9,6 +9,7 @@ "open": "Aç", "upload": "Yükle", "export": "Dışa Aktar", + "showInFolder": "Klasörde Göster", "file": "Dosya", "edit": "Düzenle", "view": "Görünüm", diff --git a/src/i18n/locales/tr/timeline.json b/src/i18n/locales/tr/timeline.json index 294640b..2632f7a 100644 --- a/src/i18n/locales/tr/timeline.json +++ b/src/i18n/locales/tr/timeline.json @@ -17,6 +17,8 @@ "labels": { "pan": "Kaydır", "zoom": "Yakınlaştır", + "trim": "Kırp", + "speed": "Hız", "zoomItem": "Yakınlaştırma {{index}}", "trimItem": "Kırpma {{index}}", "speedItem": "Hız {{index}}", diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index d8bff69..2291fa6 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -9,6 +9,7 @@ "open": "打开", "upload": "上传", "export": "导出", + "showInFolder": "在文件夹中显示", "file": "文件", "edit": "编辑", "view": "视图", diff --git a/src/i18n/locales/zh-CN/editor.json b/src/i18n/locales/zh-CN/editor.json index 44abab9..6d2f745 100644 --- a/src/i18n/locales/zh-CN/editor.json +++ b/src/i18n/locales/zh-CN/editor.json @@ -5,6 +5,7 @@ "cancel": "取消", "confirm": "确认" }, + "loadingVideo": "正在加载视频...", "errors": { "noVideoLoaded": "未加载视频", "videoNotReady": "视频未就绪", diff --git a/src/i18n/locales/zh-CN/timeline.json b/src/i18n/locales/zh-CN/timeline.json index 7841dcb..783fef6 100644 --- a/src/i18n/locales/zh-CN/timeline.json +++ b/src/i18n/locales/zh-CN/timeline.json @@ -17,6 +17,8 @@ "labels": { "pan": "平移", "zoom": "缩放", + "trim": "剪辑", + "speed": "速度", "zoomItem": "缩放 {{index}}", "trimItem": "剪辑 {{index}}", "speedItem": "速度 {{index}}", diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json index 971d9ab..1ddab48 100644 --- a/src/i18n/locales/zh-TW/common.json +++ b/src/i18n/locales/zh-TW/common.json @@ -9,6 +9,7 @@ "open": "開啟", "upload": "上傳", "export": "匯出", + "showInFolder": "在資料夾中顯示", "file": "檔案", "edit": "編輯", "view": "檢視", diff --git a/src/i18n/locales/zh-TW/editor.json b/src/i18n/locales/zh-TW/editor.json index 73a3f4e..0ef9155 100644 --- a/src/i18n/locales/zh-TW/editor.json +++ b/src/i18n/locales/zh-TW/editor.json @@ -5,6 +5,7 @@ "cancel": "取消", "confirm": "確認" }, + "loadingVideo": "正在載入影片...", "errors": { "noVideoLoaded": "未載入影片", "videoNotReady": "影片未就緒", diff --git a/src/i18n/locales/zh-TW/timeline.json b/src/i18n/locales/zh-TW/timeline.json index 52457d6..cd47b74 100644 --- a/src/i18n/locales/zh-TW/timeline.json +++ b/src/i18n/locales/zh-TW/timeline.json @@ -17,6 +17,8 @@ "labels": { "pan": "平移", "zoom": "縮放", + "trim": "剪輯", + "speed": "速度", "zoomItem": "縮放 {{index}}", "trimItem": "剪輯 {{index}}", "speedItem": "速度 {{index}}",