통합: 묶음5 의 마지막 끝 (433f5b1: 192 · 193 · 194 · 196~198) 을 합침 · 194 · 193 을 Tor · DNS 에도
관리자 지시 (10/12, 이번 판에 넣을 마지막 끝). 풀었던 곳: - 번역 json: 세 판으로 열쇠마다 합침 (서로 다르게 바뀐 열쇠 0). - browser_page import: key_hint (194) 와 cef_setup · settings_page · tor_page (tor_dns) 를 모두. 양쪽을 맞춘 것 (작업 세션 판단): - 194 (단축키 안내는 PC 에서만): Tor 화면의 이전 · 다음 페이지 · 새로고침도 keyHint. - 193 (그 설정이 없던 예전 판에서 올라오면 바뀐 동작을 한 번 알림): DNS 강제 (처음 값 직접 지정 8.8.8.8 · 8.8.4.4) 가 없던 판 (10.10 까지) 에서 올라오면 이름을 묻는 서버가 바뀐다 → 'dnsForced' 알림 (되돌리는 곳과 함께). 이미 고른 사람은 알리지 않음. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>fix_mkv
commit
120d20fb86
|
|
@ -9,6 +9,7 @@
|
|||
" (바뀐 날 같음)": " (same modified time)",
|
||||
" (보낼 것이 더 새것)": " (the one being sent is newer)",
|
||||
" (보통)": " (normal)",
|
||||
" (보통과 같음)": " (same as Normal)",
|
||||
" (사용 불가)": " (unavailable)",
|
||||
" (있는 것이 더 새것)": " (the existing one is newer)",
|
||||
" (자막 {0}개 함께)": " ({0} subtitles moved too)",
|
||||
|
|
@ -58,12 +59,14 @@
|
|||
"(현재 방식은 옵션 없음)": "(no options for the built-in method)",
|
||||
"* 는 아무 글자, ? 는 한 글자. 여러 개는 ; 로 (예: *.srt; *.ass)": "* matches any text, ? one character. Separate several with ; (e.g. *.srt; *.ass)",
|
||||
"+ 여기에 새 줄": "+ New line here",
|
||||
"- 감지한 언어": "- detected",
|
||||
"-1 은 아무렇게나": "-1 = random",
|
||||
".{0} 재생 프로그램 (exe)": ".{0} player (exe)",
|
||||
"0 = 제한 없음. 모든 방법에 적용: rsync --bwlimit, 현재 방식은 앱이 조절, robocopy 는 /IPG 로 비슷하게. 옵션 칸에 직접 넣어도 됩니다 (그쪽이 우선)": "0 = unlimited. Applies to every method: rsync --bwlimit, the built-in method throttles itself, robocopy approximates with /IPG. You can also put it in the options field (that takes priority)",
|
||||
"0 으로": "Reset to 0",
|
||||
"10초 뒤로 (←)": "Back 10 seconds (←)",
|
||||
"10초 앞으로 (→)": "Forward 10 seconds (→)",
|
||||
"1분 안": "under 1 min",
|
||||
"5초 뒤로": "Back 5 seconds",
|
||||
"5초 앞으로": "Forward 5 seconds",
|
||||
"90° 회전 (시계 방향)": "Rotate 90° (clockwise)",
|
||||
|
|
@ -101,7 +104,7 @@
|
|||
"AI 자막 만들기{0}{1}": "Make AI subtitles{0}{1}",
|
||||
"AI 자막 시작: {0}": "AI subtitles started: {0}",
|
||||
"AI 자막 실패: {0}\n{1}": "AI subtitles failed: {0}\n{1}",
|
||||
"AI 자막 완료: {0} → {1}\\{2}_AI.srt 외 {3}개": "AI subtitles done: {0} → {1}\\{2}_AI.srt and {3} more",
|
||||
"AI 자막 완료: {0} → {1} 외 {2}개": "AI subtitles done: {0} → {1} and {2} more",
|
||||
"AI 자막 중단: {0}": "AI subtitles stopped: {0}",
|
||||
"AI 자막 취소: {0}": "AI subtitles cancelled: {0}",
|
||||
"AI 자막: {0}": "AI subtitles: {0}",
|
||||
|
|
@ -161,6 +164,7 @@
|
|||
"DNS 서버가 {0} 의 주소를 찾지 못해 {1}": "The DNS server couldn't find the address of {0}, so {1}",
|
||||
"DNS 설정: {0}": "DNS setting: {0}",
|
||||
"DNS 실패 ({0}): {1}": "DNS failure ({0}): {1}",
|
||||
"DNS: 기기 DNS → 직접 지정 (8.8.8.8 · 8.8.4.4). 앱의 인터넷 연결 (브라우저 · 다운로드 · 업데이트) 은 이 서버로 주소를 찾습니다. 되돌리기: 환경 설정 > 네트워크 · DNS > 시스템 DNS (끄기)": "DNS: device DNS → custom (8.8.8.8 · 8.8.4.4). The app's internet connections (browser · downloads · updates) now look up addresses with these servers. To undo: Settings > Network · DNS > System DNS (off)",
|
||||
"DOC · DOCX · HWP · XLS · XLSX 를 PDF 로 바꿔 보기 (변환기를 받음)": "View DOC · DOCX · HWP · XLS · XLSX converted to PDF (downloads a converter)",
|
||||
"DoH 서버 ({0}) 가 HTTP {1} 로 답했습니다": "The DoH server ({0}) answered HTTP {1}",
|
||||
"DoH 서버 ({0}) 에 닿지 않습니다: {1}": "Cannot reach the DoH server ({0}): {1}",
|
||||
|
|
@ -364,6 +368,7 @@
|
|||
"lsync (실시간 동기화)": "lsync (live sync)",
|
||||
"lsync 로 이동": "Move to lsync",
|
||||
"quit 시작": "quit started",
|
||||
"robocopy 복사 · 이동: 원본 안의 링크 · junction 은 따라가지 않고 건너뜁니다 (/XJ - 예전에는 링크가 가리키는 바깥 폴더의 파일까지 복사 · 이동했습니다). 링크째 복사하려면 robocopy 옵션 칸에 /SJ 를 넣으세요": "robocopy copy · move: links and junctions inside the source are no longer followed and are skipped (/XJ - before, files in the outside folder a link pointed to were copied or moved too). To copy links as links, add /SJ to the robocopy options",
|
||||
"robocopy 옵션": "robocopy options",
|
||||
"robocopy 종료 코드 {0}": "robocopy exit code {0}",
|
||||
"rsync --delete · robocopy /PURGE. 끄면 대상에 더하기 · 바꾸기만": "rsync --delete · robocopy /PURGE. When off, only adds · updates in the target",
|
||||
|
|
@ -403,6 +408,7 @@
|
|||
"yt-dlp 의 YouTube 화질 목록 추출": "Extracts the YouTube quality list for yt-dlp",
|
||||
"{0} (AI 번역 ← {1})": "{0} (AI translation ← {1})",
|
||||
"{0} (기본): {1}": "{0} (default): {1}",
|
||||
"{0} (동영상 {1})": "{0} (videos: {1})",
|
||||
"{0} - {1} (약 {2}MB)": "{0} - {1} (about {2}MB)",
|
||||
"{0} / {1}장": "{0} / {1} images",
|
||||
"{0} · {1}{2} (메인 화면 상단에서 변경)": "{0} · {1}{2} (change at the top of the main screen)",
|
||||
|
|
@ -532,6 +538,8 @@
|
|||
"가져온 즐겨찾기": "Imported bookmarks",
|
||||
"가져온 즐겨찾기 ({0})": "Imported bookmarks ({0})",
|
||||
"가져올 즐겨찾기가 없습니다.": "No bookmarks to import.",
|
||||
"감지한 언어: {0} (자동 감지)": "Detected language: {0} (auto-detect)",
|
||||
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "Detected language: {0} - if it is wrong, make them again with another language",
|
||||
"같은 시리즈 (번호만 다른 파일)": "Same series (files that differ only by number)",
|
||||
"같은 이름이 이미 있습니다": "An item with the same name already exists",
|
||||
"같은 이름이 이미 있습니다: {0}": "Already exists with the same name: {0}",
|
||||
|
|
@ -746,6 +754,7 @@
|
|||
"다른 앱에서 동영상을 열 때": "When opening a video from another app",
|
||||
"다른 앱에서 열기: {0}": "Opened from another app: {0}",
|
||||
"다른 앱으로 열기": "Open with another app",
|
||||
"다른 언어로 다시": "Redo with another language",
|
||||
"다른 언어로 된 페이지를 화면 언어 ({0}) 로 번역합니다. 페이지의 글을 Google 번역으로 보냅니다. 주소창 옆 번역 버튼으로 원문 · 번역을 바꿀 수 있습니다.": "Translates pages in other languages into the display language ({0}). The page text is sent to Google Translate. Use the translate button next to the address bar to switch between original · translation.",
|
||||
"다른 언어로 번역 (AI · 이 {0}에서)": "Translate to another language (AI · on this {0})",
|
||||
"다른 이름으로 저장": "Save as",
|
||||
|
|
@ -798,7 +807,7 @@
|
|||
"다음": "Next",
|
||||
"다음 (N)": "Next (N)",
|
||||
"다음 {0}개 기다림": "{0} more waiting",
|
||||
"다음 페이지 (Alt+→)": "Next page (Alt+→)",
|
||||
"다음 페이지": "Next page",
|
||||
"다음부터 묻지 않기 (환경 설정 > 실행 에서 바꿀 수 있음)": "Don't ask again (can be changed in Settings > Run)",
|
||||
"단계": "Steps",
|
||||
"단축키 해제": "Unregister hotkey",
|
||||
|
|
@ -888,7 +897,6 @@
|
|||
"두 창으로": "Two panes",
|
||||
"두 창으로 보기 (좌우)": "Show two panes (side by side)",
|
||||
"뒤로": "Back",
|
||||
"뒤로 (Alt+←)": "Back (Alt+←)",
|
||||
"뒤로 보내고 계속": "Keep running in background",
|
||||
"뒤에서 계속": "Continue in background",
|
||||
"드라이브의 맨 위 폴더는 지울 수 없습니다": "The top folder of a drive can't be deleted",
|
||||
|
|
@ -1112,6 +1120,7 @@
|
|||
"복사 · 이동 {0}개": "{0} copy · move",
|
||||
"복사 · 이동 {0}개가 아직 끝나지 않았습니다. 끝내면 멈추고, 복사하던 파일은 완성되지 않은 채로 남지 않게 지웁니다.": "{0} copy/move tasks have not finished. Exiting stops them, and the file being copied is removed so no incomplete file is left.",
|
||||
"복사 · 이동 중입니다": "Copying · moving in progress",
|
||||
"복사 · 이동: 받는 쪽 파일이 더 새것이면 건너뜁니다 (예전에는 예전 원본으로 덮어쓰고, 이동이면 원본도 지웠습니다). 건너뛴 파일은 원본에 남고 끝 알림에 그 수가 나옵니다. 되돌리기: 환경 설정 > 파일 탐색기 (또는 Rsync) > 받는 쪽이 더 새것이면 건너뛰기": "Copy · move: files are skipped when the receiving side is newer (before, the older source overwrote them, and a move also deleted the source). Skipped files stay in the source and their number appears in the finish notice. To change back: Settings > File explorer (or Rsync) > Skip when the receiving side is newer",
|
||||
"복사 · 이동은 두 창에서 씁니다 (창 배치 > 두 창).": "Copy · move works with two panes (Pane layout > Two panes).",
|
||||
"복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "If the destination folder already has the same name (built-in method · WebDAV)",
|
||||
"복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "Choose items to copy · move (tap, or mark with the circle on the right).",
|
||||
|
|
@ -1199,7 +1208,7 @@
|
|||
"새 화면 \"AI 그림\" 을 위쪽 이동 버튼에 넣었습니다 (글 → 그림 · 그림 → 그림, 모델은 환경 설정에서 받기). 끄기: 환경 설정 > 컴포넌트": "Added a new \"AI images\" screen to the top navigation buttons (text → image · image → image; download models in Settings). To turn off: Settings > Components",
|
||||
"새로 고침": "Refresh",
|
||||
"새로 넣은 비밀번호는 아직 저장되지 않았습니다. 앱을 끄면 사라집니다.": "The password you entered has not been saved yet. It will be lost when you close the app.",
|
||||
"새로고침 (F5)": "Reload (F5)",
|
||||
"새로고침": "Reload",
|
||||
"색 보정": "Color correction",
|
||||
"색온도": "Temperature",
|
||||
"서버 · 서비스 (기기 밖)": "Servers · services (off device)",
|
||||
|
|
@ -1301,7 +1310,7 @@
|
|||
"시작 · 웹 브라우저": "Startup · web browser",
|
||||
"시작 메뉴에 등록": "Add to Start menu",
|
||||
"시작 안 함 (모니터링에서 시작)": "Don't start (start from Monitor)",
|
||||
"시작: {0} → {1}\\{2}{3}": "Started: {0} → {1}\\{2}{3}",
|
||||
"시작: {0} → {1}{2}": "Started: {0} → {1}{2}",
|
||||
"시작하는 중…": "Starting…",
|
||||
"시작하지 못했습니다: {0}": "Could not start: {0}",
|
||||
"시작할 동기화를 고르세요. 고르지 않은 것은 이번 실행 동안 멈춥니다 (모니터링 > lsync 에서 시작).": "Choose which syncs to start. The others stay paused for this session (start them in Monitor > lsync).",
|
||||
|
|
@ -1362,7 +1371,7 @@
|
|||
"압축 파일 안에 없습니다": "Not in the archive",
|
||||
"압축 파일 안에 프로그램이 없습니다.": "The program is not in the archive.",
|
||||
"압축을 풀 수 없습니다: {0}": "Cannot extract the archive: {0}",
|
||||
"앞으로 (Alt+→)": "Forward (Alt+→)",
|
||||
"앞으로": "Forward",
|
||||
"앞의 rsync 가 끝난 뒤에 하세요.": "Wait until the previous rsync finishes.",
|
||||
"앞의 복사 · 이동이 끝난 뒤에 하세요.": "Wait until the current copy · move finishes.",
|
||||
"앱 목록 · 홈 화면과 앱 안 왼쪽 위 버튼의 아이콘입니다. 바꾸면 홈 화면에 둔 아이콘이 없어질 수 있어 앱 목록에서 다시 끌어다 놓아야 할 수 있습니다": "Icon in the app list, home screen and the top-left button in the app. After changing it, the icon on your home screen may disappear and you may need to drag it from the app list again",
|
||||
|
|
@ -1388,7 +1397,7 @@
|
|||
"앱이 켜져 있는 동안 늘 동기화합니다.": "Always syncs while the app is running.",
|
||||
"약 {0} 남음": "about {0} left",
|
||||
"약 {0}~{1}분": "about {0}–{1} min",
|
||||
"약 {0}~{1}분 (동영상 {2})": "about {0}–{1} min (videos: {2})",
|
||||
"약 {0}분": "about {0} min",
|
||||
"양쪽 (⇄) 에서는 원본 파일을 지우지 않습니다 (옵션의 --remove-source-files 는 쓰지 않음).": "Both ways (⇄) never deletes source files (--remove-source-files in the options is not used).",
|
||||
"양쪽을 함께: 받는 쪽이 더 새 파일은 덮어쓰지 않습니다 (-u).": "Both ways: newer files on the receiving side are not overwritten (-u).",
|
||||
"어둡게": "Darker",
|
||||
|
|
@ -1543,6 +1552,7 @@
|
|||
"원어({0})와 같은 언어로는 번역하지 않습니다.": "Will not translate into the same language as the source ({0}).",
|
||||
"원어: {0} ({1})": "Source: {0} ({1})",
|
||||
"원어: 자동 감지 (글자로 추정)": "Source: auto-detect (guessed from the text)",
|
||||
"원어를 골라 다시 만들기": "Choose the source language and redo",
|
||||
"원인: {0}": "Cause: {0}",
|
||||
"월": "Mon",
|
||||
"웹 뷰 프록시 문 닫힘: {0} ({1})": "Web view proxy gate closed: {0} ({1})",
|
||||
|
|
@ -1595,6 +1605,7 @@
|
|||
"이 기기에서는 AI 번역을 쓸 수 없습니다.": "AI translation is not available on this device.",
|
||||
"이 기기에서는 AI 엔진을 찾지 못했습니다. 앱을 다시 설치해 보세요": "The AI engine was not found on this device. Try reinstalling the app",
|
||||
"이 기기에서는 쓸 수 없는 컴포넌트입니다": "This component is not available on this device",
|
||||
"이 기기에서는 적게 · 보통 · 많이 가 모두 같습니다: {0} (메모리가 작아 가장 작은 타일)": "On this device Low · Normal · High are all the same: {0} (smallest tile because memory is small)",
|
||||
"이 기기용 파일 없음": "No file for this device",
|
||||
"이 기기의 CPU 가 이 AI 엔진을 지원하지 않습니다": "This device's CPU does not support this AI engine",
|
||||
"이 기기의 안전 저장소를 쓸 수 없어 비밀번호를 저장하지 못했습니다": "Couldn't save the password because this device's secure storage is unavailable",
|
||||
|
|
@ -1693,7 +1704,7 @@
|
|||
"이전": "Previous",
|
||||
"이전 (P)": "Previous (P)",
|
||||
"이전 설정을 되살렸습니다": "Previous settings restored",
|
||||
"이전 페이지 (Alt+←)": "Previous page (Alt+←)",
|
||||
"이전 페이지": "Previous page",
|
||||
"이탈리아어": "Italian",
|
||||
"인도네시아어": "Indonesian",
|
||||
"인식된 말이 없습니다.": "No speech was recognized.",
|
||||
|
|
@ -1775,7 +1786,7 @@
|
|||
"작업 취소": "Cancel job",
|
||||
"작업 현황": "Job status",
|
||||
"작업 현황 닫기": "Close job status",
|
||||
"작업 현황 보기 · 화면 분할 (Ctrl+Shift+J)": "Show job status · split screen (Ctrl+Shift+J)",
|
||||
"작업 현황 보기 · 화면 분할": "Show job status · split screen",
|
||||
"작업 확인 (진행 중인 작업 없음)": "Job check (no jobs in progress)",
|
||||
"작업이 진행 중입니다": "Tasks are running",
|
||||
"작업하다 남은 임시 파일 · 받다 만 다운로드 (.part 등) · 받다 만 AI 모델 · 업데이트하고 남은 파일 · 지난 작업 기록을 찾아 지웁니다. 받은 동영상 · 만든 MKV · 자막은 지우지 않고, 진행 중인 작업 · 다운로드가 쓰는 것은 건너뜁니다": "Finds and deletes temporary files left from jobs · unfinished downloads (.part etc.) · unfinished AI models · update leftovers · old job logs. Downloaded videos · made MKVs · subtitles are not deleted, and anything used by running jobs · downloads is skipped",
|
||||
|
|
@ -1792,7 +1803,7 @@
|
|||
"재생 속도": "Playback speed",
|
||||
"재생 오류: {0}": "Playback error: {0}",
|
||||
"재생/일시정지 (Space)": "Play/pause (Space)",
|
||||
"재생/정지 (Ctrl+Space)": "Play/stop (Ctrl+Space)",
|
||||
"재생/정지": "Play/stop",
|
||||
"재생목록 불러오는 중… {0}": "Loading playlist… {0}",
|
||||
"재생목록 주소면 목록 전체 받기": "Download the whole list for playlist URLs",
|
||||
"재생목록을 읽을 수 없습니다: {0}": "Cannot read the playlist: {0}",
|
||||
|
|
@ -1884,7 +1895,7 @@
|
|||
"주소 (http · https · 마그넷) 를 찾지 못했거나 이미 받는 중입니다.": "No address (http · https · magnet) found, or it's already downloading.",
|
||||
"주소 이름 (예: youtube.com) 을 찾을 때 물어볼 서버. 직접 지정하면 기기의 DNS 대신 이 서버만 씁니다. 서버에 닿지 않으면 기기 DNS 로 몰래 바꾸지 않고 알립니다.": "The server asked when looking up host names (e.g. youtube.com). When set manually, only this server is used instead of the device DNS. If it cannot be reached, you are told instead of silently switching to the device DNS.",
|
||||
"주소 이름이 너무 깁니다: {0}": "Host name is too long: {0}",
|
||||
"주소 입력 또는 검색 (Ctrl+L)": "Enter an address or search (Ctrl+L)",
|
||||
"주소 입력 또는 검색": "Enter an address or search",
|
||||
"주소 입력 또는 검색 (DuckDuckGo)": "Enter an address or search (DuckDuckGo)",
|
||||
"주소로 열기": "Open by address",
|
||||
"주소를 https 로 바꾸고 다시 확인": "Switch the address to https and check again",
|
||||
|
|
@ -1902,15 +1913,11 @@
|
|||
"즐겨찾기 HTML 가져오기": "Import bookmarks HTML",
|
||||
"즐겨찾기 검색 (이름 · 주소)": "Search bookmarks (name · address)",
|
||||
"즐겨찾기 관리": "Manage bookmarks",
|
||||
"즐겨찾기 관리 (Ctrl+Shift+B)": "Manage bookmarks (Ctrl+Shift+B)",
|
||||
"즐겨찾기 관리자": "Bookmark manager",
|
||||
"즐겨찾기 관리자 (Ctrl+Shift+O)": "Bookmark manager (Ctrl+Shift+O)",
|
||||
"즐겨찾기 관리자에서 보기": "Show in bookmark manager",
|
||||
"즐겨찾기 내보내기 (HTML)": "Export bookmarks (HTML)",
|
||||
"즐겨찾기 수정": "Edit bookmark",
|
||||
"즐겨찾기 수정 (Ctrl+D)": "Edit bookmark (Ctrl+D)",
|
||||
"즐겨찾기 추가": "Add bookmark",
|
||||
"즐겨찾기 추가 (Ctrl+D)": "Add bookmark (Ctrl+D)",
|
||||
"즐겨찾기 추가…": "Add bookmark…",
|
||||
"즐겨찾기 추가됨": "Bookmark added",
|
||||
"즐겨찾기 표시줄": "Bookmarks bar",
|
||||
|
|
@ -2005,6 +2012,7 @@
|
|||
"처음 쓸 때 내려받기 (기본)": "Download on first use (default)",
|
||||
"처음 아이콘 (파랑)": "Original icon (blue)",
|
||||
"처음대로": "Reset to default",
|
||||
"처음부터 정하려면 AI 자막 창의 \"원어 (영상 속 언어)\" 에서 고르세요.": "To set it from the start, choose it in \"Source language (spoken in the video)\" in the AI subtitles window.",
|
||||
"처음으로: {0}": "Back to the first: {0}",
|
||||
"첫 장입니다.": "This is the first page.",
|
||||
"첫 줄 추가": "Add first line",
|
||||
|
|
@ -2096,6 +2104,7 @@
|
|||
"파일 탐색기 두 창 배치: 화면 모양 따라 → 좌우. 되돌리기: 파일 탐색기의 [좌우 ⇆ / 위아래 ⇅] 버튼 또는 창 배치": "File explorer two-pane layout: follow screen shape → side by side. To revert: the [Side by side ⇆ / Top and bottom ⇅] button in the file explorer, or Pane layout",
|
||||
"파일 탐색기 위쪽 ⋮ 메뉴에서도 바꿀 수 있습니다 (좌우 · 위아래 · 버튼 줄 위치 · 버튼 구성)": "You can also change it from the ⋮ menu at the top of the file explorer (side by side · top and bottom · button bar position · buttons)",
|
||||
"파일 탐색기 창: 두 창 → 화면 크기 따라 (폰 세로는 한 창). 되돌리기: 환경 설정 > 파일 탐색기 > 창 배치": "File explorer panes: two panes → by screen size (one pane on a portrait phone). To revert: Settings > File explorer > Pane layout",
|
||||
"파일 탐색기: 파일을 한 번 누르면 바로 엽니다 (고르기 · 메뉴는 길게 누르기). 바꾸기: 환경 설정 > 파일 탐색기 > 누르기": "File explorer: a single tap now opens a file right away (long-press to select or for the menu). To change: Settings > File explorer > Tap",
|
||||
"파일 폴더": "File folder",
|
||||
"파일 확인 중…": "Checking files…",
|
||||
"파일만 골랐을 때": "When only files are selected",
|
||||
|
|
@ -2225,6 +2234,7 @@
|
|||
"화면 · 색 보정": "Frame · color",
|
||||
"화면 가득 (시스템 막대 숨기기)": "Full screen (hide system bars)",
|
||||
"화면 가운데를 왼쪽으로 밀면 다음 화면, 오른쪽으로 밀면 이전 화면 (마지막 다음은 처음으로).": "Swipe left in the middle of the screen for the next screen, right for the previous one (after the last comes the first).",
|
||||
"화면 가운데를 좌우로 밀면 다른 화면 (파일 탐색기 · 다운로드 등) 으로 넘어갑니다. 끄기: 환경 설정 > 컴포넌트 > 좌우로 밀어 화면 이동": "Swiping left or right in the middle of the screen now switches to other screens (file explorer, downloads, etc.). To turn off: Settings > Components > Swipe left/right to switch screens",
|
||||
"화면 글자 전체를 이 기기에서 번역합니다. 몇 분 걸릴 수 있습니다.": "Translates all of the program's text on this device. It may take a few minutes.",
|
||||
"화면 모양 따라": "Follow screen shape",
|
||||
"화면 방향": "Screen orientation",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
" (바뀐 날 같음)": " (更新日時が同じ)",
|
||||
" (보낼 것이 더 새것)": " (送る方が新しい)",
|
||||
" (보통)": "(標準)",
|
||||
" (보통과 같음)": " (普通と同じ)",
|
||||
" (사용 불가)": "(使用不可)",
|
||||
" (있는 것이 더 새것)": " (既存の方が新しい)",
|
||||
" (자막 {0}개 함께)": "(字幕 {0}個も一緒に)",
|
||||
|
|
@ -58,12 +59,14 @@
|
|||
"(현재 방식은 옵션 없음)": "(現在の方式にはオプションなし)",
|
||||
"* 는 아무 글자, ? 는 한 글자. 여러 개는 ; 로 (예: *.srt; *.ass)": "* は任意の文字列、? は 1 文字。複数は ; で区切る (例: *.srt; *.ass)",
|
||||
"+ 여기에 새 줄": "+ ここに新しい行",
|
||||
"- 감지한 언어": "- 検出した言語",
|
||||
"-1 은 아무렇게나": "-1 はランダム",
|
||||
".{0} 재생 프로그램 (exe)": ".{0} 再生プログラム(exe)",
|
||||
"0 = 제한 없음. 모든 방법에 적용: rsync --bwlimit, 현재 방식은 앱이 조절, robocopy 는 /IPG 로 비슷하게. 옵션 칸에 직접 넣어도 됩니다 (그쪽이 우선)": "0 = 制限なし。すべての方法に適用: rsync は --bwlimit、現在の方式はアプリが調整、robocopy は /IPG で近似。オプション欄に直接入れても構いません (そちらが優先)",
|
||||
"0 으로": "0 に戻す",
|
||||
"10초 뒤로 (←)": "10秒戻る(←)",
|
||||
"10초 앞으로 (→)": "10秒進む(→)",
|
||||
"1분 안": "1 分以内",
|
||||
"5초 뒤로": "5秒戻る",
|
||||
"5초 앞으로": "5秒進む",
|
||||
"90° 회전 (시계 방향)": "90° 回転 (時計回り)",
|
||||
|
|
@ -101,7 +104,7 @@
|
|||
"AI 자막 만들기{0}{1}": "AI 字幕を作成{0}{1}",
|
||||
"AI 자막 시작: {0}": "AI 字幕開始: {0}",
|
||||
"AI 자막 실패: {0}\n{1}": "AI 字幕失敗: {0}\n{1}",
|
||||
"AI 자막 완료: {0} → {1}\\{2}_AI.srt 외 {3}개": "AI 字幕完了: {0} → {1}\\{2}_AI.srt ほか {3}個",
|
||||
"AI 자막 완료: {0} → {1} 외 {2}개": "AI 字幕完了: {0} → {1} ほか {2}個",
|
||||
"AI 자막 중단: {0}": "AI 字幕中断: {0}",
|
||||
"AI 자막 취소: {0}": "AI 字幕キャンセル: {0}",
|
||||
"AI 자막: {0}": "AI 字幕: {0}",
|
||||
|
|
@ -161,6 +164,7 @@
|
|||
"DNS 서버가 {0} 의 주소를 찾지 못해 {1}": "DNS サーバーが {0} のアドレスを見つけられないため、{1}",
|
||||
"DNS 설정: {0}": "DNS 設定: {0}",
|
||||
"DNS 실패 ({0}): {1}": "DNS 失敗 ({0}): {1}",
|
||||
"DNS: 기기 DNS → 직접 지정 (8.8.8.8 · 8.8.4.4). 앱의 인터넷 연결 (브라우저 · 다운로드 · 업데이트) 은 이 서버로 주소를 찾습니다. 되돌리기: 환경 설정 > 네트워크 · DNS > 시스템 DNS (끄기)": "DNS: 端末の DNS → 直接指定 (8.8.8.8 · 8.8.4.4)。アプリのインターネット接続 (ブラウザ · ダウンロード · 更新) はこのサーバーでアドレスを調べます。元に戻す: 設定 > ネットワーク · DNS > システム DNS (オフ)",
|
||||
"DOC · DOCX · HWP · XLS · XLSX 를 PDF 로 바꿔 보기 (변환기를 받음)": "DOC・DOCX・HWP・XLS・XLSX を PDF に変換して表示 (変換ツールをダウンロード)",
|
||||
"DoH 서버 ({0}) 가 HTTP {1} 로 답했습니다": "DoH サーバー ({0}) が HTTP {1} を返しました",
|
||||
"DoH 서버 ({0}) 에 닿지 않습니다: {1}": "DoH サーバー ({0}) に届きません: {1}",
|
||||
|
|
@ -364,6 +368,7 @@
|
|||
"lsync (실시간 동기화)": "lsync (リアルタイム同期)",
|
||||
"lsync 로 이동": "lsync へ移動",
|
||||
"quit 시작": "終了開始",
|
||||
"robocopy 복사 · 이동: 원본 안의 링크 · junction 은 따라가지 않고 건너뜁니다 (/XJ - 예전에는 링크가 가리키는 바깥 폴더의 파일까지 복사 · 이동했습니다). 링크째 복사하려면 robocopy 옵션 칸에 /SJ 를 넣으세요": "robocopy のコピー · 移動: 元の中のリンク · ジャンクションはたどらずにスキップします (/XJ - 以前はリンク先の外のフォルダーのファイルまでコピー · 移動していました)。リンクのままコピーするには robocopy オプション欄に /SJ を入れてください",
|
||||
"robocopy 옵션": "robocopy オプション",
|
||||
"robocopy 종료 코드 {0}": "robocopy 終了コード {0}",
|
||||
"rsync --delete · robocopy /PURGE. 끄면 대상에 더하기 · 바꾸기만": "rsync --delete · robocopy /PURGE。オフなら対象に追加 · 更新のみ",
|
||||
|
|
@ -403,6 +408,7 @@
|
|||
"yt-dlp 의 YouTube 화질 목록 추출": "yt-dlp 用の YouTube 画質リストを取得",
|
||||
"{0} (AI 번역 ← {1})": "{0}(AI 翻訳 ← {1})",
|
||||
"{0} (기본): {1}": "{0}(既定): {1}",
|
||||
"{0} (동영상 {1})": "{0} (動画 {1})",
|
||||
"{0} - {1} (약 {2}MB)": "{0} - {1}(約 {2}MB)",
|
||||
"{0} / {1}장": "{0} / {1} 枚",
|
||||
"{0} · {1}{2} (메인 화면 상단에서 변경)": "{0} · {1}{2}(メイン画面の上部で変更)",
|
||||
|
|
@ -532,6 +538,8 @@
|
|||
"가져온 즐겨찾기": "取り込んだブックマーク",
|
||||
"가져온 즐겨찾기 ({0})": "取り込んだブックマーク({0})",
|
||||
"가져올 즐겨찾기가 없습니다.": "取り込むブックマークがありません。",
|
||||
"감지한 언어: {0} (자동 감지)": "検出した言語: {0} (自動検出)",
|
||||
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "検出した言語: {0} - 違っていれば別の言語で作り直してください",
|
||||
"같은 시리즈 (번호만 다른 파일)": "同じシリーズ(番号だけ違うファイル)",
|
||||
"같은 이름이 이미 있습니다": "同じ名前のものが既にあります",
|
||||
"같은 이름이 이미 있습니다: {0}": "同じ名前が既にあります: {0}",
|
||||
|
|
@ -746,6 +754,7 @@
|
|||
"다른 앱에서 동영상을 열 때": "他のアプリで動画を開いたとき",
|
||||
"다른 앱에서 열기: {0}": "他のアプリから開く: {0}",
|
||||
"다른 앱으로 열기": "別のアプリで開く",
|
||||
"다른 언어로 다시": "別の言語でやり直す",
|
||||
"다른 언어로 된 페이지를 화면 언어 ({0}) 로 번역합니다. 페이지의 글을 Google 번역으로 보냅니다. 주소창 옆 번역 버튼으로 원문 · 번역을 바꿀 수 있습니다.": "ほかの言語のページを表示言語 ({0}) に翻訳します。ページの文章は Google 翻訳に送られます。アドレスバー横の翻訳ボタンで原文 · 翻訳を切り替えられます。",
|
||||
"다른 언어로 번역 (AI · 이 {0}에서)": "他の言語に翻訳(AI・この{0}で)",
|
||||
"다른 이름으로 저장": "名前を付けて保存",
|
||||
|
|
@ -798,7 +807,7 @@
|
|||
"다음": "次へ",
|
||||
"다음 (N)": "次へ(N)",
|
||||
"다음 {0}개 기다림": "次の {0} 件が待機中",
|
||||
"다음 페이지 (Alt+→)": "次のページ(Alt+→)",
|
||||
"다음 페이지": "次のページ",
|
||||
"다음부터 묻지 않기 (환경 설정 > 실행 에서 바꿀 수 있음)": "次回から確認しない(環境設定 > 実行 で変更できます)",
|
||||
"단계": "ステップ",
|
||||
"단축키 해제": "ショートカット解除",
|
||||
|
|
@ -888,7 +897,6 @@
|
|||
"두 창으로": "2 画面に",
|
||||
"두 창으로 보기 (좌우)": "2 画面で表示 (左右)",
|
||||
"뒤로": "戻る",
|
||||
"뒤로 (Alt+←)": "戻る (Alt+←)",
|
||||
"뒤로 보내고 계속": "裏で続ける",
|
||||
"뒤에서 계속": "バックグラウンドで続ける",
|
||||
"드라이브의 맨 위 폴더는 지울 수 없습니다": "ドライブの最上位フォルダーは削除できません",
|
||||
|
|
@ -1112,6 +1120,7 @@
|
|||
"복사 · 이동 {0}개": "コピー・移動 {0} 件",
|
||||
"복사 · 이동 {0}개가 아직 끝나지 않았습니다. 끝내면 멈추고, 복사하던 파일은 완성되지 않은 채로 남지 않게 지웁니다.": "コピー・移動 {0} 件がまだ終わっていません。終了すると止まり、コピー中のファイルは未完成のまま残らないよう削除します。",
|
||||
"복사 · 이동 중입니다": "コピー・移動中です",
|
||||
"복사 · 이동: 받는 쪽 파일이 더 새것이면 건너뜁니다 (예전에는 예전 원본으로 덮어쓰고, 이동이면 원본도 지웠습니다). 건너뛴 파일은 원본에 남고 끝 알림에 그 수가 나옵니다. 되돌리기: 환경 설정 > 파일 탐색기 (또는 Rsync) > 받는 쪽이 더 새것이면 건너뛰기": "コピー · 移動: 受け取る側のファイルが新しければスキップします (以前は古い元で上書きし、移動なら元も削除していました)。スキップしたファイルは元に残り、終了の通知にその数が出ます。戻すには: 環境設定 > ファイルエクスプローラー (または Rsync) > 受け取る側が新しければスキップ",
|
||||
"복사 · 이동은 두 창에서 씁니다 (창 배치 > 두 창).": "コピー · 移動は 2 ペインで使います (ペインの配置 > 2 ペイン)。",
|
||||
"복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "コピー・移動先のフォルダーに同じ名前がある場合 (現在の方式・WebDAV)",
|
||||
"복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "コピー · 移動する項目を選んでください (タップ、または右の丸でマーク)。",
|
||||
|
|
@ -1199,7 +1208,7 @@
|
|||
"새 화면 \"AI 그림\" 을 위쪽 이동 버튼에 넣었습니다 (글 → 그림 · 그림 → 그림, 모델은 환경 설정에서 받기). 끄기: 환경 설정 > 컴포넌트": "新しい画面「AI 画像」を上部の移動ボタンに追加しました (テキスト → 画像・画像 → 画像、モデルは環境設定でダウンロード)。オフにする: 環境設定 > コンポーネント",
|
||||
"새로 고침": "更新",
|
||||
"새로 넣은 비밀번호는 아직 저장되지 않았습니다. 앱을 끄면 사라집니다.": "入力したパスワードはまだ保存されていません。アプリを終了すると消えます。",
|
||||
"새로고침 (F5)": "再読み込み(F5)",
|
||||
"새로고침": "再読み込み",
|
||||
"색 보정": "カラー補正",
|
||||
"색온도": "色温度",
|
||||
"서버 · 서비스 (기기 밖)": "サーバー・サービス (端末外)",
|
||||
|
|
@ -1301,7 +1310,7 @@
|
|||
"시작 · 웹 브라우저": "起動・ウェブブラウザー",
|
||||
"시작 메뉴에 등록": "スタートメニューに登録",
|
||||
"시작 안 함 (모니터링에서 시작)": "開始しない (モニタリングで開始)",
|
||||
"시작: {0} → {1}\\{2}{3}": "開始: {0} → {1}\\{2}{3}",
|
||||
"시작: {0} → {1}{2}": "開始: {0} → {1}{2}",
|
||||
"시작하는 중…": "開始中…",
|
||||
"시작하지 못했습니다: {0}": "開始できませんでした: {0}",
|
||||
"시작할 동기화를 고르세요. 고르지 않은 것은 이번 실행 동안 멈춥니다 (모니터링 > lsync 에서 시작).": "開始する同期を選んでください。選ばなかったものは今回の実行中は停止します (モニタリング > lsync で開始)。",
|
||||
|
|
@ -1362,7 +1371,7 @@
|
|||
"압축 파일 안에 없습니다": "圧縮ファイル内にありません",
|
||||
"압축 파일 안에 프로그램이 없습니다.": "圧縮ファイル内にプログラムがありません。",
|
||||
"압축을 풀 수 없습니다: {0}": "圧縮ファイルを展開できません: {0}",
|
||||
"앞으로 (Alt+→)": "進む (Alt+→)",
|
||||
"앞으로": "進む",
|
||||
"앞의 rsync 가 끝난 뒤에 하세요.": "前の rsync が終わってから行ってください。",
|
||||
"앞의 복사 · 이동이 끝난 뒤에 하세요.": "前のコピー · 移動が終わってから行ってください。",
|
||||
"앱 목록 · 홈 화면과 앱 안 왼쪽 위 버튼의 아이콘입니다. 바꾸면 홈 화면에 둔 아이콘이 없어질 수 있어 앱 목록에서 다시 끌어다 놓아야 할 수 있습니다": "アプリ一覧・ホーム画面とアプリ内左上のボタンのアイコンです。変更するとホーム画面のアイコンが消えることがあり、アプリ一覧から再度ドラッグする必要がある場合があります",
|
||||
|
|
@ -1388,7 +1397,7 @@
|
|||
"앱이 켜져 있는 동안 늘 동기화합니다.": "アプリの起動中は常に同期します。",
|
||||
"약 {0} 남음": "残り約 {0}",
|
||||
"약 {0}~{1}분": "約 {0}~{1} 分",
|
||||
"약 {0}~{1}분 (동영상 {2})": "約 {0}~{1} 分 (動画 {2})",
|
||||
"약 {0}분": "約 {0} 分",
|
||||
"양쪽 (⇄) 에서는 원본 파일을 지우지 않습니다 (옵션의 --remove-source-files 는 쓰지 않음).": "双方向 (⇄) では元のファイルを削除しません (オプションの --remove-source-files は使いません)。",
|
||||
"양쪽을 함께: 받는 쪽이 더 새 파일은 덮어쓰지 않습니다 (-u).": "双方向: 受け取る側の方が新しいファイルは上書きしません (-u)。",
|
||||
"어둡게": "暗く",
|
||||
|
|
@ -1543,6 +1552,7 @@
|
|||
"원어({0})와 같은 언어로는 번역하지 않습니다.": "原語({0})と同じ言語には翻訳しません。",
|
||||
"원어: {0} ({1})": "原語: {0}({1})",
|
||||
"원어: 자동 감지 (글자로 추정)": "原語: 自動検出(文字から推定)",
|
||||
"원어를 골라 다시 만들기": "原語を選んで作り直す",
|
||||
"원인: {0}": "原因: {0}",
|
||||
"월": "月",
|
||||
"웹 뷰 프록시 문 닫힘: {0} ({1})": "Web ビュー用プロキシの入口を閉じました: {0} ({1})",
|
||||
|
|
@ -1595,6 +1605,7 @@
|
|||
"이 기기에서는 AI 번역을 쓸 수 없습니다.": "この端末では AI 翻訳を使えません。",
|
||||
"이 기기에서는 AI 엔진을 찾지 못했습니다. 앱을 다시 설치해 보세요": "この端末で AI エンジンが見つかりませんでした。アプリを再インストールしてください",
|
||||
"이 기기에서는 쓸 수 없는 컴포넌트입니다": "この端末では使えないコンポーネントです",
|
||||
"이 기기에서는 적게 · 보통 · 많이 가 모두 같습니다: {0} (메모리가 작아 가장 작은 타일)": "この機器では少なめ · 普通 · 多めはすべて同じです: {0} (メモリが少ないため最小のタイル)",
|
||||
"이 기기용 파일 없음": "このデバイス用のファイルなし",
|
||||
"이 기기의 CPU 가 이 AI 엔진을 지원하지 않습니다": "この端末の CPU はこの AI エンジンに対応していません",
|
||||
"이 기기의 안전 저장소를 쓸 수 없어 비밀번호를 저장하지 못했습니다": "この端末の安全な保存領域を使えないため、パスワードを保存できませんでした",
|
||||
|
|
@ -1693,7 +1704,7 @@
|
|||
"이전": "前へ",
|
||||
"이전 (P)": "前へ(P)",
|
||||
"이전 설정을 되살렸습니다": "以前の設定を復元しました",
|
||||
"이전 페이지 (Alt+←)": "前のページ(Alt+←)",
|
||||
"이전 페이지": "前のページ",
|
||||
"이탈리아어": "イタリア語",
|
||||
"인도네시아어": "インドネシア語",
|
||||
"인식된 말이 없습니다.": "認識された音声がありません。",
|
||||
|
|
@ -1775,7 +1786,7 @@
|
|||
"작업 취소": "作業をキャンセル",
|
||||
"작업 현황": "作業状況",
|
||||
"작업 현황 닫기": "作業状況を閉じる",
|
||||
"작업 현황 보기 · 화면 분할 (Ctrl+Shift+J)": "作業状況を表示・画面分割(Ctrl+Shift+J)",
|
||||
"작업 현황 보기 · 화면 분할": "作業状況を表示・画面分割",
|
||||
"작업 확인 (진행 중인 작업 없음)": "作業確認(進行中の作業なし)",
|
||||
"작업이 진행 중입니다": "作業中です",
|
||||
"작업하다 남은 임시 파일 · 받다 만 다운로드 (.part 등) · 받다 만 AI 모델 · 업데이트하고 남은 파일 · 지난 작업 기록을 찾아 지웁니다. 받은 동영상 · 만든 MKV · 자막은 지우지 않고, 진행 중인 작업 · 다운로드가 쓰는 것은 건너뜁니다": "作業で残った一時ファイル・ダウンロード途中のファイル(.part など)・途中の AI モデル・更新の残り・古い作業記録を探して削除します。ダウンロードした動画・作成した MKV・字幕は削除せず、進行中の作業・ダウンロードが使っているものはスキップします",
|
||||
|
|
@ -1792,7 +1803,7 @@
|
|||
"재생 속도": "再生速度",
|
||||
"재생 오류: {0}": "再生エラー: {0}",
|
||||
"재생/일시정지 (Space)": "再生/一時停止(Space)",
|
||||
"재생/정지 (Ctrl+Space)": "再生/停止(Ctrl+Space)",
|
||||
"재생/정지": "再生/停止",
|
||||
"재생목록 불러오는 중… {0}": "再生リストを読み込み中… {0}",
|
||||
"재생목록 주소면 목록 전체 받기": "再生リストの URL ならリスト全体をダウンロード",
|
||||
"재생목록을 읽을 수 없습니다: {0}": "再生リストを読めません: {0}",
|
||||
|
|
@ -1884,7 +1895,7 @@
|
|||
"주소 (http · https · 마그넷) 를 찾지 못했거나 이미 받는 중입니다.": "アドレス (http・https・マグネット) が見つからないか、すでにダウンロード中です。",
|
||||
"주소 이름 (예: youtube.com) 을 찾을 때 물어볼 서버. 직접 지정하면 기기의 DNS 대신 이 서버만 씁니다. 서버에 닿지 않으면 기기 DNS 로 몰래 바꾸지 않고 알립니다.": "ホスト名 (例: youtube.com) を解決するときに問い合わせるサーバー。手動指定すると端末の DNS の代わりにこのサーバーだけを使います。サーバーに届かない場合は、黙って端末の DNS に切り替えずにお知らせします。",
|
||||
"주소 이름이 너무 깁니다: {0}": "ホスト名が長すぎます: {0}",
|
||||
"주소 입력 또는 검색 (Ctrl+L)": "アドレスを入力または検索(Ctrl+L)",
|
||||
"주소 입력 또는 검색": "アドレスを入力または検索",
|
||||
"주소 입력 또는 검색 (DuckDuckGo)": "アドレス入力または検索 (DuckDuckGo)",
|
||||
"주소로 열기": "アドレスで開く",
|
||||
"주소를 https 로 바꾸고 다시 확인": "アドレスを https に変えてもう一度確認",
|
||||
|
|
@ -1902,15 +1913,11 @@
|
|||
"즐겨찾기 HTML 가져오기": "ブックマーク HTML を取り込む",
|
||||
"즐겨찾기 검색 (이름 · 주소)": "ブックマークを検索(名前・アドレス)",
|
||||
"즐겨찾기 관리": "ブックマーク管理",
|
||||
"즐겨찾기 관리 (Ctrl+Shift+B)": "ブックマーク管理(Ctrl+Shift+B)",
|
||||
"즐겨찾기 관리자": "ブックマークマネージャー",
|
||||
"즐겨찾기 관리자 (Ctrl+Shift+O)": "ブックマークマネージャー(Ctrl+Shift+O)",
|
||||
"즐겨찾기 관리자에서 보기": "ブックマークマネージャーで表示",
|
||||
"즐겨찾기 내보내기 (HTML)": "ブックマークを書き出す(HTML)",
|
||||
"즐겨찾기 수정": "ブックマークを編集",
|
||||
"즐겨찾기 수정 (Ctrl+D)": "ブックマークを編集(Ctrl+D)",
|
||||
"즐겨찾기 추가": "ブックマークを追加",
|
||||
"즐겨찾기 추가 (Ctrl+D)": "ブックマークを追加(Ctrl+D)",
|
||||
"즐겨찾기 추가…": "ブックマークを追加…",
|
||||
"즐겨찾기 추가됨": "ブックマークを追加しました",
|
||||
"즐겨찾기 표시줄": "ブックマークバー",
|
||||
|
|
@ -2005,6 +2012,7 @@
|
|||
"처음 쓸 때 내려받기 (기본)": "初めて使うときにダウンロード (既定)",
|
||||
"처음 아이콘 (파랑)": "最初のアイコン(青)",
|
||||
"처음대로": "既定に戻す",
|
||||
"처음부터 정하려면 AI 자막 창의 \"원어 (영상 속 언어)\" 에서 고르세요.": "最初から決めるには、AI 字幕ウィンドウの「原語(動画内の言語)」で選んでください。",
|
||||
"처음으로: {0}": "最初へ: {0}",
|
||||
"첫 장입니다.": "最初のページです。",
|
||||
"첫 줄 추가": "最初の行を追加",
|
||||
|
|
@ -2096,6 +2104,7 @@
|
|||
"파일 탐색기 두 창 배치: 화면 모양 따라 → 좌우. 되돌리기: 파일 탐색기의 [좌우 ⇆ / 위아래 ⇅] 버튼 또는 창 배치": "ファイルエクスプローラーの 2 画面配置: 画面の形に合わせる → 左右。元に戻す: ファイルエクスプローラーの [左右 ⇆ / 上下 ⇅] ボタンまたは画面配置",
|
||||
"파일 탐색기 위쪽 ⋮ 메뉴에서도 바꿀 수 있습니다 (좌우 · 위아래 · 버튼 줄 위치 · 버튼 구성)": "ファイルエクスプローラー上部の ⋮ メニューからも変えられます (左右 · 上下 · ボタン列の位置 · ボタン構成)",
|
||||
"파일 탐색기 창: 두 창 → 화면 크기 따라 (폰 세로는 한 창). 되돌리기: 환경 설정 > 파일 탐색기 > 창 배치": "ファイルエクスプローラーの画面: 2 画面 → 画面サイズに合わせる (縦向きのスマホは 1 画面)。元に戻す: 環境設定 > ファイルエクスプローラー > 画面配置",
|
||||
"파일 탐색기: 파일을 한 번 누르면 바로 엽니다 (고르기 · 메뉴는 길게 누르기). 바꾸기: 환경 설정 > 파일 탐색기 > 누르기": "ファイルエクスプローラー: ファイルを 1 回タップするとすぐ開きます (選択 · メニューは長押し)。変更: 環境設定 > ファイルエクスプローラー > タップ",
|
||||
"파일 폴더": "ファイル フォルダー",
|
||||
"파일 확인 중…": "ファイルを確認中…",
|
||||
"파일만 골랐을 때": "ファイルだけを選んだとき",
|
||||
|
|
@ -2225,6 +2234,7 @@
|
|||
"화면 · 색 보정": "画面・カラー補正",
|
||||
"화면 가득 (시스템 막대 숨기기)": "全画面 (システムバーを隠す)",
|
||||
"화면 가운데를 왼쪽으로 밀면 다음 화면, 오른쪽으로 밀면 이전 화면 (마지막 다음은 처음으로).": "画面中央を左へスワイプで次の画面、右へで前の画面 (最後の次は最初へ)。",
|
||||
"화면 가운데를 좌우로 밀면 다른 화면 (파일 탐색기 · 다운로드 등) 으로 넘어갑니다. 끄기: 환경 설정 > 컴포넌트 > 좌우로 밀어 화면 이동": "画面の中央を左右にスワイプすると別の画面 (ファイルエクスプローラー · ダウンロードなど) に切り替わります。オフにする: 環境設定 > コンポーネント > 左右スワイプで画面を移動",
|
||||
"화면 글자 전체를 이 기기에서 번역합니다. 몇 분 걸릴 수 있습니다.": "画面の文字をすべてこの端末で翻訳します。数分かかることがあります。",
|
||||
"화면 모양 따라": "画面の形に合わせる",
|
||||
"화면 방향": "画面の向き",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
" (바뀐 날 같음)": "(修改时间相同)",
|
||||
" (보낼 것이 더 새것)": "(要发送的较新)",
|
||||
" (보통)": "(标准)",
|
||||
" (보통과 같음)": "(与普通相同)",
|
||||
" (사용 불가)": "(不可用)",
|
||||
" (있는 것이 더 새것)": "(已有的较新)",
|
||||
" (자막 {0}개 함께)": "(字幕 {0} 个一并移动)",
|
||||
|
|
@ -58,12 +59,14 @@
|
|||
"(현재 방식은 옵션 없음)": "(当前方式没有选项)",
|
||||
"* 는 아무 글자, ? 는 한 글자. 여러 개는 ; 로 (예: *.srt; *.ass)": "* 表示任意字符,? 表示一个字符。多个用 ; 分隔(例:*.srt; *.ass)",
|
||||
"+ 여기에 새 줄": "+ 在此新增一行",
|
||||
"- 감지한 언어": "- 检测到的语言",
|
||||
"-1 은 아무렇게나": "-1 为随机",
|
||||
".{0} 재생 프로그램 (exe)": ".{0} 播放程序(exe)",
|
||||
"0 = 제한 없음. 모든 방법에 적용: rsync --bwlimit, 현재 방식은 앱이 조절, robocopy 는 /IPG 로 비슷하게. 옵션 칸에 직접 넣어도 됩니다 (그쪽이 우선)": "0 = 不限制。适用于所有方式: rsync 用 --bwlimit,当前方式由应用调节,robocopy 用 /IPG 近似。也可直接写在选项栏中 (优先)",
|
||||
"0 으로": "归零",
|
||||
"10초 뒤로 (←)": "后退 10 秒(←)",
|
||||
"10초 앞으로 (→)": "前进 10 秒(→)",
|
||||
"1분 안": "1 分钟以内",
|
||||
"5초 뒤로": "后退 5 秒",
|
||||
"5초 앞으로": "前进 5 秒",
|
||||
"90° 회전 (시계 방향)": "旋转 90° (顺时针)",
|
||||
|
|
@ -101,7 +104,7 @@
|
|||
"AI 자막 만들기{0}{1}": "生成 AI 字幕{0}{1}",
|
||||
"AI 자막 시작: {0}": "AI 字幕开始: {0}",
|
||||
"AI 자막 실패: {0}\n{1}": "AI 字幕失败: {0}\n{1}",
|
||||
"AI 자막 완료: {0} → {1}\\{2}_AI.srt 외 {3}개": "AI 字幕完成: {0} → {1}\\{2}_AI.srt 等 {3} 个",
|
||||
"AI 자막 완료: {0} → {1} 외 {2}개": "AI 字幕完成: {0} → {1} 等 {2} 个",
|
||||
"AI 자막 중단: {0}": "AI 字幕中断: {0}",
|
||||
"AI 자막 취소: {0}": "AI 字幕已取消: {0}",
|
||||
"AI 자막: {0}": "AI 字幕: {0}",
|
||||
|
|
@ -161,6 +164,7 @@
|
|||
"DNS 서버가 {0} 의 주소를 찾지 못해 {1}": "DNS 服务器找不到 {0} 的地址,因此{1}",
|
||||
"DNS 설정: {0}": "DNS 设置: {0}",
|
||||
"DNS 실패 ({0}): {1}": "DNS 失败 ({0}): {1}",
|
||||
"DNS: 기기 DNS → 직접 지정 (8.8.8.8 · 8.8.4.4). 앱의 인터넷 연결 (브라우저 · 다운로드 · 업데이트) 은 이 서버로 주소를 찾습니다. 되돌리기: 환경 설정 > 네트워크 · DNS > 시스템 DNS (끄기)": "DNS:设备 DNS → 手动指定 (8.8.8.8 · 8.8.4.4)。应用的网络连接 (浏览器 · 下载 · 更新) 将用这些服务器查找地址。恢复:设置 > 网络 · DNS > 系统 DNS (关闭)",
|
||||
"DOC · DOCX · HWP · XLS · XLSX 를 PDF 로 바꿔 보기 (변환기를 받음)": "将 DOC · DOCX · HWP · XLS · XLSX 转为 PDF 查看 (需下载转换器)",
|
||||
"DoH 서버 ({0}) 가 HTTP {1} 로 답했습니다": "DoH 服务器 ({0}) 返回 HTTP {1}",
|
||||
"DoH 서버 ({0}) 에 닿지 않습니다: {1}": "无法连接 DoH 服务器 ({0}): {1}",
|
||||
|
|
@ -364,6 +368,7 @@
|
|||
"lsync (실시간 동기화)": "lsync (实时同步)",
|
||||
"lsync 로 이동": "移到 lsync",
|
||||
"quit 시작": "开始退出",
|
||||
"robocopy 복사 · 이동: 원본 안의 링크 · junction 은 따라가지 않고 건너뜁니다 (/XJ - 예전에는 링크가 가리키는 바깥 폴더의 파일까지 복사 · 이동했습니다). 링크째 복사하려면 robocopy 옵션 칸에 /SJ 를 넣으세요": "robocopy 复制 · 移动:源中的链接 · 联接不再跟随,而是跳过(/XJ - 以前会连链接指向的外部文件夹中的文件一起复制 · 移动)。要按链接本身复制,请在 robocopy 选项栏中加入 /SJ",
|
||||
"robocopy 옵션": "robocopy 选项",
|
||||
"robocopy 종료 코드 {0}": "robocopy 退出代码 {0}",
|
||||
"rsync --delete · robocopy /PURGE. 끄면 대상에 더하기 · 바꾸기만": "rsync --delete · robocopy /PURGE。关闭时只在目标中添加 · 更新",
|
||||
|
|
@ -403,6 +408,7 @@
|
|||
"yt-dlp 의 YouTube 화질 목록 추출": "提取 yt-dlp 的 YouTube 画质列表",
|
||||
"{0} (AI 번역 ← {1})": "{0}(AI 翻译 ← {1})",
|
||||
"{0} (기본): {1}": "{0}(默认): {1}",
|
||||
"{0} (동영상 {1})": "{0}(视频 {1})",
|
||||
"{0} - {1} (약 {2}MB)": "{0} - {1}(约 {2}MB)",
|
||||
"{0} / {1}장": "{0} / {1} 张",
|
||||
"{0} · {1}{2} (메인 화면 상단에서 변경)": "{0} · {1}{2}(在主界面顶部更改)",
|
||||
|
|
@ -532,6 +538,8 @@
|
|||
"가져온 즐겨찾기": "导入的书签",
|
||||
"가져온 즐겨찾기 ({0})": "导入的书签({0})",
|
||||
"가져올 즐겨찾기가 없습니다.": "没有可导入的书签。",
|
||||
"감지한 언어: {0} (자동 감지)": "检测到的语言:{0}(自动检测)",
|
||||
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "检测到的语言:{0} - 如有误,请用其他语言重新生成",
|
||||
"같은 시리즈 (번호만 다른 파일)": "同一系列(仅编号不同的文件)",
|
||||
"같은 이름이 이미 있습니다": "已存在同名项目",
|
||||
"같은 이름이 이미 있습니다: {0}": "已存在同名项目: {0}",
|
||||
|
|
@ -746,6 +754,7 @@
|
|||
"다른 앱에서 동영상을 열 때": "从其他应用打开视频时",
|
||||
"다른 앱에서 열기: {0}": "从其他应用打开: {0}",
|
||||
"다른 앱으로 열기": "用其他应用打开",
|
||||
"다른 언어로 다시": "用其他语言重做",
|
||||
"다른 언어로 된 페이지를 화면 언어 ({0}) 로 번역합니다. 페이지의 글을 Google 번역으로 보냅니다. 주소창 옆 번역 버튼으로 원문 · 번역을 바꿀 수 있습니다.": "将其他语言的页面翻译为界面语言 ({0})。页面文字会发送到 Google 翻译。可用地址栏旁的翻译按钮切换原文 · 译文。",
|
||||
"다른 언어로 번역 (AI · 이 {0}에서)": "翻译为其他语言(AI · 在此{0}上)",
|
||||
"다른 이름으로 저장": "另存为",
|
||||
|
|
@ -798,7 +807,7 @@
|
|||
"다음": "下一个",
|
||||
"다음 (N)": "下一个(N)",
|
||||
"다음 {0}개 기다림": "另有 {0} 个等待中",
|
||||
"다음 페이지 (Alt+→)": "下一页(Alt+→)",
|
||||
"다음 페이지": "下一页",
|
||||
"다음부터 묻지 않기 (환경 설정 > 실행 에서 바꿀 수 있음)": "下次不再询问(可在 设置 > 运行 中更改)",
|
||||
"단계": "步数",
|
||||
"단축키 해제": "注销快捷键",
|
||||
|
|
@ -888,7 +897,6 @@
|
|||
"두 창으로": "双窗格",
|
||||
"두 창으로 보기 (좌우)": "以双窗格显示 (左右)",
|
||||
"뒤로": "后退",
|
||||
"뒤로 (Alt+←)": "后退 (Alt+←)",
|
||||
"뒤로 보내고 계속": "转到后台继续",
|
||||
"뒤에서 계속": "在后台继续",
|
||||
"드라이브의 맨 위 폴더는 지울 수 없습니다": "无法删除驱动器的根文件夹",
|
||||
|
|
@ -1112,6 +1120,7 @@
|
|||
"복사 · 이동 {0}개": "复制 · 移动 {0} 个",
|
||||
"복사 · 이동 {0}개가 아직 끝나지 않았습니다. 끝내면 멈추고, 복사하던 파일은 완성되지 않은 채로 남지 않게 지웁니다.": "{0} 个复制 · 移动尚未完成。退出会停止它们,并删除正在复制的文件,以免留下不完整的文件。",
|
||||
"복사 · 이동 중입니다": "正在复制 · 移动",
|
||||
"복사 · 이동: 받는 쪽 파일이 더 새것이면 건너뜁니다 (예전에는 예전 원본으로 덮어쓰고, 이동이면 원본도 지웠습니다). 건너뛴 파일은 원본에 남고 끝 알림에 그 수가 나옵니다. 되돌리기: 환경 설정 > 파일 탐색기 (또는 Rsync) > 받는 쪽이 더 새것이면 건너뛰기": "复制 · 移动:接收端文件较新时跳过(以前会用旧的源文件覆盖,移动时还会删除源)。跳过的文件留在源中,完成通知中会显示数量。恢复:设置 > 文件浏览器(或 Rsync)> 接收端较新时跳过",
|
||||
"복사 · 이동은 두 창에서 씁니다 (창 배치 > 두 창).": "复制 · 移动需在双窗格中使用 (窗格布局 > 双窗格)。",
|
||||
"복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "目标文件夹中已有同名项目时 (当前方式 · WebDAV)",
|
||||
"복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "请选择要复制 · 移动的项目 (点按,或用右侧圆圈标记)。",
|
||||
|
|
@ -1199,7 +1208,7 @@
|
|||
"새 화면 \"AI 그림\" 을 위쪽 이동 버튼에 넣었습니다 (글 → 그림 · 그림 → 그림, 모델은 환경 설정에서 받기). 끄기: 환경 설정 > 컴포넌트": "已将新画面“AI 图片”加入顶部导航按钮 (文字 → 图片 · 图片 → 图片,模型在设置中下载)。关闭: 设置 > 组件",
|
||||
"새로 고침": "刷新",
|
||||
"새로 넣은 비밀번호는 아직 저장되지 않았습니다. 앱을 끄면 사라집니다.": "输入的密码尚未保存。关闭应用后会丢失。",
|
||||
"새로고침 (F5)": "刷新(F5)",
|
||||
"새로고침": "刷新",
|
||||
"색 보정": "色彩校正",
|
||||
"색온도": "色温",
|
||||
"서버 · 서비스 (기기 밖)": "服务器 · 服务 (设备外)",
|
||||
|
|
@ -1301,7 +1310,7 @@
|
|||
"시작 · 웹 브라우저": "启动 · 网页浏览器",
|
||||
"시작 메뉴에 등록": "添加到开始菜单",
|
||||
"시작 안 함 (모니터링에서 시작)": "不开始 (在监控中开始)",
|
||||
"시작: {0} → {1}\\{2}{3}": "开始: {0} → {1}\\{2}{3}",
|
||||
"시작: {0} → {1}{2}": "开始: {0} → {1}{2}",
|
||||
"시작하는 중…": "正在开始…",
|
||||
"시작하지 못했습니다: {0}": "无法开始:{0}",
|
||||
"시작할 동기화를 고르세요. 고르지 않은 것은 이번 실행 동안 멈춥니다 (모니터링 > lsync 에서 시작).": "请选择要开始的同步。未选的在本次运行期间暂停 (可在 监控 > lsync 中开始)。",
|
||||
|
|
@ -1362,7 +1371,7 @@
|
|||
"압축 파일 안에 없습니다": "压缩文件中没有",
|
||||
"압축 파일 안에 프로그램이 없습니다.": "压缩文件中没有程序。",
|
||||
"압축을 풀 수 없습니다: {0}": "无法解压: {0}",
|
||||
"앞으로 (Alt+→)": "前进 (Alt+→)",
|
||||
"앞으로": "前进",
|
||||
"앞의 rsync 가 끝난 뒤에 하세요.": "请等上一个 rsync 结束后再运行。",
|
||||
"앞의 복사 · 이동이 끝난 뒤에 하세요.": "请等待前一个复制 · 移动完成。",
|
||||
"앱 목록 · 홈 화면과 앱 안 왼쪽 위 버튼의 아이콘입니다. 바꾸면 홈 화면에 둔 아이콘이 없어질 수 있어 앱 목록에서 다시 끌어다 놓아야 할 수 있습니다": "应用列表、主屏幕以及应用内左上角按钮的图标。更改后主屏幕上的图标可能会消失,可能需要从应用列表重新拖放",
|
||||
|
|
@ -1388,7 +1397,7 @@
|
|||
"앱이 켜져 있는 동안 늘 동기화합니다.": "应用运行期间始终同步。",
|
||||
"약 {0} 남음": "约剩 {0}",
|
||||
"약 {0}~{1}분": "约 {0}~{1} 分钟",
|
||||
"약 {0}~{1}분 (동영상 {2})": "约 {0}~{1} 分钟(视频 {2})",
|
||||
"약 {0}분": "约 {0} 分钟",
|
||||
"양쪽 (⇄) 에서는 원본 파일을 지우지 않습니다 (옵션의 --remove-source-files 는 쓰지 않음).": "双向 (⇄) 不会删除源文件(不使用选项中的 --remove-source-files)。",
|
||||
"양쪽을 함께: 받는 쪽이 더 새 파일은 덮어쓰지 않습니다 (-u).": "双向: 接收端较新的文件不会被覆盖 (-u)。",
|
||||
"어둡게": "调暗",
|
||||
|
|
@ -1543,6 +1552,7 @@
|
|||
"원어({0})와 같은 언어로는 번역하지 않습니다.": "不会翻译成与原语言({0})相同的语言。",
|
||||
"원어: {0} ({1})": "原语言: {0}({1})",
|
||||
"원어: 자동 감지 (글자로 추정)": "原语言: 自动检测(根据文字推测)",
|
||||
"원어를 골라 다시 만들기": "选择原语言并重新生成",
|
||||
"원인: {0}": "原因: {0}",
|
||||
"월": "一",
|
||||
"웹 뷰 프록시 문 닫힘: {0} ({1})": "WebView 代理入口已关闭:{0}({1})",
|
||||
|
|
@ -1595,6 +1605,7 @@
|
|||
"이 기기에서는 AI 번역을 쓸 수 없습니다.": "此设备无法使用 AI 翻译。",
|
||||
"이 기기에서는 AI 엔진을 찾지 못했습니다. 앱을 다시 설치해 보세요": "在此设备上找不到 AI 引擎。请尝试重新安装应用",
|
||||
"이 기기에서는 쓸 수 없는 컴포넌트입니다": "此组件在本设备上不可用",
|
||||
"이 기기에서는 적게 · 보통 · 많이 가 모두 같습니다: {0} (메모리가 작아 가장 작은 타일)": "在此设备上,少 · 普通 · 多 都相同:{0}(内存较小,使用最小的分块)",
|
||||
"이 기기용 파일 없음": "没有此设备的文件",
|
||||
"이 기기의 CPU 가 이 AI 엔진을 지원하지 않습니다": "此设备的 CPU 不支持该 AI 引擎",
|
||||
"이 기기의 안전 저장소를 쓸 수 없어 비밀번호를 저장하지 못했습니다": "本设备的安全存储不可用,无法保存密码",
|
||||
|
|
@ -1693,7 +1704,7 @@
|
|||
"이전": "上一个",
|
||||
"이전 (P)": "上一个(P)",
|
||||
"이전 설정을 되살렸습니다": "已恢复之前的设置",
|
||||
"이전 페이지 (Alt+←)": "上一页(Alt+←)",
|
||||
"이전 페이지": "上一页",
|
||||
"이탈리아어": "意大利语",
|
||||
"인도네시아어": "印尼语",
|
||||
"인식된 말이 없습니다.": "未识别到语音。",
|
||||
|
|
@ -1775,7 +1786,7 @@
|
|||
"작업 취소": "取消任务",
|
||||
"작업 현황": "任务状态",
|
||||
"작업 현황 닫기": "关闭任务状态",
|
||||
"작업 현황 보기 · 화면 분할 (Ctrl+Shift+J)": "显示任务状态 · 分屏(Ctrl+Shift+J)",
|
||||
"작업 현황 보기 · 화면 분할": "显示任务状态 · 分屏",
|
||||
"작업 확인 (진행 중인 작업 없음)": "任务检查(没有进行中的任务)",
|
||||
"작업이 진행 중입니다": "任务正在进行",
|
||||
"작업하다 남은 임시 파일 · 받다 만 다운로드 (.part 등) · 받다 만 AI 모델 · 업데이트하고 남은 파일 · 지난 작업 기록을 찾아 지웁니다. 받은 동영상 · 만든 MKV · 자막은 지우지 않고, 진행 중인 작업 · 다운로드가 쓰는 것은 건너뜁니다": "查找并删除任务残留的临时文件 · 未完成的下载(.part 等)· 未下载完的 AI 模型 · 更新残留 · 旧任务记录。不会删除已下载的视频 · 制作的 MKV · 字幕,正在进行的任务 · 下载所用的文件会跳过",
|
||||
|
|
@ -1792,7 +1803,7 @@
|
|||
"재생 속도": "播放速度",
|
||||
"재생 오류: {0}": "播放错误: {0}",
|
||||
"재생/일시정지 (Space)": "播放/暂停(Space)",
|
||||
"재생/정지 (Ctrl+Space)": "播放/停止(Ctrl+Space)",
|
||||
"재생/정지": "播放/停止",
|
||||
"재생목록 불러오는 중… {0}": "正在加载播放列表… {0}",
|
||||
"재생목록 주소면 목록 전체 받기": "如果是播放列表地址则下载整个列表",
|
||||
"재생목록을 읽을 수 없습니다: {0}": "无法读取播放列表: {0}",
|
||||
|
|
@ -1884,7 +1895,7 @@
|
|||
"주소 (http · https · 마그넷) 를 찾지 못했거나 이미 받는 중입니다.": "未找到地址 (http · https · 磁力),或已在下载。",
|
||||
"주소 이름 (예: youtube.com) 을 찾을 때 물어볼 서버. 직접 지정하면 기기의 DNS 대신 이 서버만 씁니다. 서버에 닿지 않으면 기기 DNS 로 몰래 바꾸지 않고 알립니다.": "解析主机名 (例: youtube.com) 时询问的服务器。手动指定时只使用此服务器而不使用设备 DNS。无法连接服务器时会提示,而不会悄悄切换到设备 DNS。",
|
||||
"주소 이름이 너무 깁니다: {0}": "主机名过长: {0}",
|
||||
"주소 입력 또는 검색 (Ctrl+L)": "输入地址或搜索(Ctrl+L)",
|
||||
"주소 입력 또는 검색": "输入地址或搜索",
|
||||
"주소 입력 또는 검색 (DuckDuckGo)": "输入地址或搜索 (DuckDuckGo)",
|
||||
"주소로 열기": "按地址打开",
|
||||
"주소를 https 로 바꾸고 다시 확인": "将地址改为 https 并重新检查",
|
||||
|
|
@ -1902,15 +1913,11 @@
|
|||
"즐겨찾기 HTML 가져오기": "导入书签 HTML",
|
||||
"즐겨찾기 검색 (이름 · 주소)": "搜索书签(名称 · 地址)",
|
||||
"즐겨찾기 관리": "管理书签",
|
||||
"즐겨찾기 관리 (Ctrl+Shift+B)": "管理书签(Ctrl+Shift+B)",
|
||||
"즐겨찾기 관리자": "书签管理器",
|
||||
"즐겨찾기 관리자 (Ctrl+Shift+O)": "书签管理器(Ctrl+Shift+O)",
|
||||
"즐겨찾기 관리자에서 보기": "在书签管理器中显示",
|
||||
"즐겨찾기 내보내기 (HTML)": "导出书签(HTML)",
|
||||
"즐겨찾기 수정": "编辑书签",
|
||||
"즐겨찾기 수정 (Ctrl+D)": "编辑书签(Ctrl+D)",
|
||||
"즐겨찾기 추가": "添加书签",
|
||||
"즐겨찾기 추가 (Ctrl+D)": "添加书签(Ctrl+D)",
|
||||
"즐겨찾기 추가…": "添加书签…",
|
||||
"즐겨찾기 추가됨": "已添加书签",
|
||||
"즐겨찾기 표시줄": "书签栏",
|
||||
|
|
@ -2005,6 +2012,7 @@
|
|||
"처음 쓸 때 내려받기 (기본)": "首次使用时下载 (默认)",
|
||||
"처음 아이콘 (파랑)": "最初的图标(蓝色)",
|
||||
"처음대로": "恢复默认",
|
||||
"처음부터 정하려면 AI 자막 창의 \"원어 (영상 속 언어)\" 에서 고르세요.": "如需一开始就指定,请在 AI 字幕窗口的“原语言(视频中的语言)”中选择。",
|
||||
"처음으로: {0}": "回到第一个: {0}",
|
||||
"첫 장입니다.": "已是第一页。",
|
||||
"첫 줄 추가": "添加第一行",
|
||||
|
|
@ -2096,6 +2104,7 @@
|
|||
"파일 탐색기 두 창 배치: 화면 모양 따라 → 좌우. 되돌리기: 파일 탐색기의 [좌우 ⇆ / 위아래 ⇅] 버튼 또는 창 배치": "文件浏览器双窗格布局: 跟随屏幕形状 → 左右。恢复: 文件浏览器中的 [左右 ⇆ / 上下 ⇅] 按钮或窗格布局",
|
||||
"파일 탐색기 위쪽 ⋮ 메뉴에서도 바꿀 수 있습니다 (좌우 · 위아래 · 버튼 줄 위치 · 버튼 구성)": "也可以在文件浏览器顶部的 ⋮ 菜单中更改 (左右 · 上下 · 按钮栏位置 · 按钮配置)",
|
||||
"파일 탐색기 창: 두 창 → 화면 크기 따라 (폰 세로는 한 창). 되돌리기: 환경 설정 > 파일 탐색기 > 창 배치": "文件浏览器窗格: 双窗格 → 按屏幕大小 (竖屏手机为单窗格)。恢复: 设置 > 文件浏览器 > 窗格布局",
|
||||
"파일 탐색기: 파일을 한 번 누르면 바로 엽니다 (고르기 · 메뉴는 길게 누르기). 바꾸기: 환경 설정 > 파일 탐색기 > 누르기": "文件浏览器:单击文件会立即打开(选择 · 菜单请长按)。更改:设置 > 文件浏览器 > 点按",
|
||||
"파일 폴더": "文件夹",
|
||||
"파일 확인 중…": "正在检查文件…",
|
||||
"파일만 골랐을 때": "只选择文件时",
|
||||
|
|
@ -2225,6 +2234,7 @@
|
|||
"화면 · 색 보정": "画面 · 色彩",
|
||||
"화면 가득 (시스템 막대 숨기기)": "全屏 (隐藏系统栏)",
|
||||
"화면 가운데를 왼쪽으로 밀면 다음 화면, 오른쪽으로 밀면 이전 화면 (마지막 다음은 처음으로).": "在屏幕中间向左滑动进入下一个界面,向右滑动返回上一个界面 (最后一个之后回到第一个)。",
|
||||
"화면 가운데를 좌우로 밀면 다른 화면 (파일 탐색기 · 다운로드 등) 으로 넘어갑니다. 끄기: 환경 설정 > 컴포넌트 > 좌우로 밀어 화면 이동": "在屏幕中间左右滑动会切换到其他屏幕(文件浏览器 · 下载等)。关闭:设置 > 组件 > 左右滑动切换界面",
|
||||
"화면 글자 전체를 이 기기에서 번역합니다. 몇 분 걸릴 수 있습니다.": "将在此设备上翻译所有界面文字。可能需要几分钟。",
|
||||
"화면 모양 따라": "跟随屏幕形状",
|
||||
"화면 방향": "屏幕方向",
|
||||
|
|
|
|||
|
|
@ -92,6 +92,26 @@ int androidUpscaleTile({int? memTotalMb, int? longSide, double share = 0.30}) {
|
|||
return 192;
|
||||
}
|
||||
|
||||
/// 176 · 192: 환경 설정 "해상도 올리기 메모리" 의 설명 줄 - 이 기기에서 적게 · 보통 · 많이 가 고르는 타일 · 메모리.
|
||||
/// 메모리가 작은 기기 (P11 4GB 등) 는 셋 다 가장 작은 타일이라 같은 값이 세 번 보였다 - 같으면 그렇다고 알린다
|
||||
List<String> upscaleMemoryLines(int? memTotalMb) {
|
||||
int tile(String id) => androidUpscaleTile(memTotalMb: memTotalMb, share: upscaleMemoryShare(id));
|
||||
String text(int t) => trf('타일 {0} · 약 {1}GB', [t, (upscaleTileMemoryMb(t) / 1024).toStringAsFixed(1)]);
|
||||
final low = tile('low'), normal = tile('normal'), high = tile('high');
|
||||
final same = tr(' (보통과 같음)');
|
||||
return [
|
||||
if (memTotalMb != null) trf('이 기기 메모리 {0}GB 기준:', [(memTotalMb / 1024).toStringAsFixed(0)]),
|
||||
if (low == normal && normal == high)
|
||||
trf('이 기기에서는 적게 · 보통 · 많이 가 모두 같습니다: {0} (메모리가 작아 가장 작은 타일)', [text(normal)])
|
||||
else ...[
|
||||
trf('적게 (느림): {0}', [text(low)]) + (low == normal ? same : ''),
|
||||
trf('보통: {0}', [text(normal)]),
|
||||
trf('많이 (빠름): {0} - 다른 앱이 많이 켜져 있으면 Android 가 이 앱을 끌 수 있습니다', [text(high)]) + (high == normal ? same : ''),
|
||||
],
|
||||
tr('타일이 작을수록 느립니다 (예: 16GB 폰에서 1024×768 을 2배로 - 512 약 4분 · 320 약 9분 30초).'),
|
||||
];
|
||||
}
|
||||
|
||||
/// 타일 크기 → 엔진이 쓸 메모리 어림 (MB, S10 실측 512 → 6.6GB 에서 넓이 비례)
|
||||
int upscaleTileMemoryMb(int tile) => (6600 * (tile / 512) * (tile / 512)).round();
|
||||
|
||||
|
|
|
|||
|
|
@ -943,6 +943,8 @@ class AppController extends ChangeNotifier {
|
|||
? opts.source
|
||||
: detectLanguage(cues.map((c) => c.text).join(' '));
|
||||
_log(trf('음성인식 완료: {0}줄, 원어 {1}({2})', [cues.length, src.name, src.code]));
|
||||
// 198: 자동 감지가 틀릴 수 있다 (영어를 한국어로 잡아 영어 발음을 한글로 적음) - 끝난 뒤 알리고 다른 언어로 다시 할 수 있게
|
||||
v.aiDetected = opts.source == undetermined ? src.code : null;
|
||||
|
||||
// 5. 파일명_AI.srt (원본)
|
||||
await storage.ensureDirectory(outputDirFor(v.path));
|
||||
|
|
@ -990,7 +992,8 @@ class AppController extends ChangeNotifier {
|
|||
..status = JobStatus.ready
|
||||
..phase = null
|
||||
..progress = 0;
|
||||
_log(trf('AI 자막 완료: {0} → {1}\\{2}_AI.srt 외 {3}개', [v.fileName, outputFolderName, v.baseName, langs.length]));
|
||||
// 196: 경로는 기기의 구분자로 (Android 에서도 "jj_mkv\이름" 으로 보였다)
|
||||
_log(trf('AI 자막 완료: {0} → {1} 외 {2}개', [v.fileName, p.join(outputFolderName, '${v.baseName}_AI.srt'), langs.length]));
|
||||
} on AiCancelled {
|
||||
v
|
||||
..status = JobStatus.ready
|
||||
|
|
@ -1388,7 +1391,7 @@ class AppController extends ChangeNotifier {
|
|||
..progress = 0
|
||||
..message = null;
|
||||
notifyListeners();
|
||||
_log(trf('시작: {0} → {1}\\{2}' '{3}', [v.fileName, outputFolderName, p.basename(out), encode.reencode ? ' [${encode.codec.label} · ${encode.resolution.label} · ${encode.quality.label}${encode.adjusts ? ' · ${encode.adjustSummary}' : ''}]' : '']));
|
||||
_log(trf('시작: {0} → {1}{2}', [v.fileName, p.join(outputFolderName, p.basename(out)), encode.reencode ? ' [${encode.codec.label} · ${encode.resolution.label} · ${encode.quality.label}${encode.adjusts ? ' · ${encode.adjustSummary}' : ''}]' : '']));
|
||||
final copies = <SubtitleEntry, String>{};
|
||||
var started = false; // FFmpeg 가 출력 파일을 쓰기 시작했는지
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -732,6 +732,7 @@ class AppSettings {
|
|||
'rsyncPaths': rsyncPaths,
|
||||
'components': components,
|
||||
'aiImageV1': true,
|
||||
'robocopyLinksV1': true,
|
||||
'navOrder': navOrder,
|
||||
'swipeNav': swipeNav,
|
||||
'imageExts': imageExts,
|
||||
|
|
@ -1107,8 +1108,29 @@ class AppSettings {
|
|||
if (j['zipComicV2'] != true && j['zipComic'] != false && j.containsKey('imageExts') && !s.zipComic) 'zipComic',
|
||||
if (j['backgroundV2'] != true && j['runInBackground'] == false && s.runInBackground && Platform.isAndroid)
|
||||
'background',
|
||||
// 193: 그 설정이 생기기 전 판 (설정 파일은 있는데 그 항목이 없음 - 예: 10.03) 에서 올라온 사람이 바로 겪는 동작 변화.
|
||||
// 예전 판에는 키가 없어 위의 "예전 값 → 새 값" 조건에 걸리지 않았다 (P11: 탐색기에서 한 번 눌렀는데 바로 열려 놀람)
|
||||
if (j.isNotEmpty && !j.containsKey('explorerClick') && s.explorerClick == 'open') 'explorerClickNew',
|
||||
if (j.isNotEmpty && !j.containsKey('screenOrientation') && s.screenOrientation == 'auto' && Platform.isAndroid) 'orientation',
|
||||
if (j.isNotEmpty && !j.containsKey('swipeNav') && s.swipeNav) 'swipeNav',
|
||||
if (j.isNotEmpty && !j.containsKey('runInBackground') && s.runInBackground && Platform.isAndroid) 'background',
|
||||
// DNS 강제 (사용자 요청 10/10, 처음 값 직접 지정 8.8.8.8 · 8.8.4.4) 가 없던 판에서 올라오면 이름을 묻는 서버가 바뀐다 - 193 과 같이 한 번 알림
|
||||
if (j.isNotEmpty && !j.containsKey('dnsMode') && s.dnsMode == 'custom') 'dnsForced',
|
||||
// 193 · 229: 예전 판을 쓰던 사람 (설정 파일이 있는데 이 항목이 없음) 에게 복사 · 이동이 받는 쪽의 더 새 파일을 건너뛰게 바뀐 것을 한 번
|
||||
if (j.isNotEmpty && !j.containsKey('copySkipNewer')) 'copySkipNewer',
|
||||
// 193: robocopy 를 쓰던 사람 (Windows) 에게 링크 · junction 을 따라가지 않게 (/XJ) 바뀐 것을 한 번
|
||||
if (j['robocopyLinksV1'] != true && Platform.isWindows && _usedRobocopy(j)) 'robocopyLinks',
|
||||
];
|
||||
|
||||
/// 193: 예전 설정에서 robocopy 를 쓰고 있었는지 (복사 방법 · 기억한 복사 · 실시간 동기화 쌍)
|
||||
static bool _usedRobocopy(Map<String, dynamic> j) {
|
||||
bool robo(Object? x) => x is Map && x['method'] == 'robocopy';
|
||||
return j['copyMethodFile'] == 'robocopy' ||
|
||||
j['copyMethodFolder'] == 'robocopy' ||
|
||||
((j['copyTasks'] as List?) ?? const []).any(robo) ||
|
||||
((j['liveSyncPairs'] as List?) ?? const []).any(robo);
|
||||
}
|
||||
|
||||
/// 다운로드 기본 위치: 프로그램 폴더 (쓸 수 없으면 사용자 다운로드 폴더)
|
||||
String resolvedDownloadRoot() {
|
||||
if (downloadRoot != null && downloadRoot!.isNotEmpty) return downloadRoot!;
|
||||
|
|
|
|||
|
|
@ -99,6 +99,9 @@ class VideoItem {
|
|||
String? message;
|
||||
String? outputPath;
|
||||
|
||||
/// 198: 마지막 AI 자막에서 원어를 자동 감지했으면 그 언어 코드 (원어를 직접 골랐으면 null)
|
||||
String? aiDetected;
|
||||
|
||||
VideoItem(this.path);
|
||||
|
||||
String get fileName => p.basename(path);
|
||||
|
|
|
|||
|
|
@ -16,8 +16,16 @@ import '../l10n/tr.dart';
|
|||
Future<void> showAiDialog(BuildContext context, AppController c, VideoItem current,
|
||||
{List<VideoItem>? targets, bool thenBuild = false}) async {
|
||||
final list = targets ?? [current];
|
||||
Future<void> run(List<VideoItem> v, AiOptions o) =>
|
||||
thenBuild ? c.aiThenBuild(v, o) : c.generateAiSubtitles(v, o);
|
||||
// 198: 끝난 뒤 알림 · 다시 하기 창을 띄울 곳 (이 화면이 닫혀도 남는 것)
|
||||
final messenger = ScaffoldMessenger.maybeOf(context);
|
||||
final overlay = Navigator.maybeOf(context)?.overlay;
|
||||
Future<void> run(List<VideoItem> v, AiOptions o) async {
|
||||
await (thenBuild ? c.aiThenBuild(v, o) : c.generateAiSubtitles(v, o));
|
||||
if (o.source == undetermined && messenger != null) {
|
||||
showDetectedLanguage(messenger, overlay, v, onRetry: (lang) => run(v, o.copyWith(source: lang)));
|
||||
}
|
||||
}
|
||||
|
||||
Future<(AiOptions, bool)?> full() => showDialog<(AiOptions, bool)>(
|
||||
context: context,
|
||||
builder: (_) => _AiDialog(c: c, videos: list, videoCount: targets == null ? c.videos.length : 1, thenBuild: thenBuild),
|
||||
|
|
@ -43,6 +51,52 @@ Future<void> showAiDialog(BuildContext context, AppController c, VideoItem curre
|
|||
await run(all ? List.of(c.videos) : list, opts);
|
||||
}
|
||||
|
||||
/// 198: 원어를 자동 감지했으면 끝난 뒤 "감지한 언어: …" 와 [다른 언어로 다시] (언어 고르기 → 그 원어로 다시 만듦)
|
||||
void showDetectedLanguage(ScaffoldMessengerState messenger, OverlayState? overlay, List<VideoItem> videos,
|
||||
{required Future<void> Function(Language) onRetry}) {
|
||||
final found = [for (final v in videos) if (v.aiDetected != null) (v, languageOf(v.aiDetected))];
|
||||
if (found.isEmpty) return;
|
||||
final names = found.length == 1
|
||||
? found.single.$2.name
|
||||
: found.map((x) => '${x.$2.name} (${x.$1.fileName})').join(' · ');
|
||||
messenger.showSnackBar(SnackBar(
|
||||
// 248 과 같게: 버튼이 있는 안내는 사용자가 닫을 때까지 ([✕]). 나중에는 MKV 목록의 그 동영상 세부 정보에서도
|
||||
persist: true,
|
||||
showCloseIcon: true,
|
||||
content: Text(trf('감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요', [names])),
|
||||
action: overlay == null
|
||||
? null
|
||||
: SnackBarAction(
|
||||
label: tr('다른 언어로 다시'),
|
||||
onPressed: () async {
|
||||
if (!overlay.mounted) return;
|
||||
final lang = await pickSourceLanguage(overlay.context, found.first.$2);
|
||||
if (lang != null) await onRetry(lang);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
/// 198: 원어를 골라 다시 만들 때의 언어 고르기 (원어를 처음부터 정하는 곳도 알린다)
|
||||
Future<Language?> pickSourceLanguage(BuildContext context, Language detected) => showDialog<Language>(
|
||||
context: context,
|
||||
builder: (ctx) => SimpleDialog(
|
||||
title: Text(tr('원어를 골라 다시 만들기')),
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 8),
|
||||
child: Text(tr('처음부터 정하려면 AI 자막 창의 "원어 (영상 속 언어)" 에서 고르세요.'),
|
||||
style: const TextStyle(fontSize: 12, color: JjColors.textDim)),
|
||||
),
|
||||
for (final l in languages)
|
||||
SimpleDialogOption(
|
||||
onPressed: () => Navigator.pop(ctx, l),
|
||||
child: Text('${l.name} (${l.code})${l == detected ? ' ${tr('- 감지한 언어')}' : ''}'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
/// 138: "매번 묻기" 를 껐을 때 시작 전에 [취소] 할 수 있는 시간
|
||||
const aiStartDelay = Duration(seconds: 3);
|
||||
|
||||
|
|
@ -50,7 +104,7 @@ const aiStartDelay = Duration(seconds: 3);
|
|||
String aiStartNotice(List<VideoItem> videos, AiOptions o, {required bool thenBuild}) {
|
||||
final known = videos.map((v) => v.info?.duration).whereType<Duration>().toList();
|
||||
final est = known.length == videos.length ? aiEstimateMinutes(known.fold(Duration.zero, (a, b) => a + b), aiTranslateCount(o)) : null;
|
||||
final what = [trf('동영상 {0}개', [videos.length]), if (est != null) trf('약 {0}~{1}분', [est.$1, est.$2])].join(' · ');
|
||||
final what = [trf('동영상 {0}개', [videos.length]), if (est != null) aiEstimateText(est)].join(' · ');
|
||||
return thenBuild ? trf('AI 자막 → MKV ({0}) 을 시작합니다', [what]) : trf('AI 자막 ({0}) 을 시작합니다', [what]);
|
||||
}
|
||||
|
||||
|
|
@ -64,6 +118,14 @@ const aiColor = Color(0xFFB388FF);
|
|||
return ((h * (15 + 10 * translateLanguages)).ceil(), (h * (30 + 20 * translateLanguages)).ceil());
|
||||
}
|
||||
|
||||
/// 197: 예상 시간 글 - 짧은 동영상은 "약 1~1분" 처럼 같은 수가 두 번 보였다
|
||||
String aiEstimateText((int, int) est) {
|
||||
final (lo, hi) = est;
|
||||
if (hi <= 1) return tr('1분 안');
|
||||
if (lo == hi) return trf('약 {0}분', [lo]);
|
||||
return trf('약 {0}~{1}분', [lo, hi]);
|
||||
}
|
||||
|
||||
/// 번역할 언어 수 (원어와 같은 언어는 번역하지 않음, 원어 자동 감지면 하나는 원어로 본다)
|
||||
int aiTranslateCount(AiOptions o) => o.source == undetermined
|
||||
? (o.targets.length - 1).clamp(0, 99)
|
||||
|
|
@ -90,7 +152,7 @@ class AiPlanSummary extends StatelessWidget {
|
|||
tr('예상 시간'),
|
||||
est == null
|
||||
? tr('동영상 길이를 몰라 셀 수 없습니다 (영상 1시간 ≈ 음성인식 15~30분 + 언어당 번역 10~20분)')
|
||||
: trf('약 {0}~{1}분 (동영상 {2})', [est.$1, est.$2, hm(total)]),
|
||||
: trf('{0} (동영상 {1})', [aiEstimateText(est), hm(total)]),
|
||||
),
|
||||
];
|
||||
return Container(
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import 'folder_picker.dart';
|
|||
import 'license_texts.dart' show showLicenseDocument;
|
||||
import 'setting_tile.dart';
|
||||
import 'theme.dart';
|
||||
import '../app/ai_upscale.dart' show androidUpscaleTile, upscaleMemoryShare, upscaleTileMemoryMb, deviceMemTotalMb;
|
||||
import '../app/ai_upscale.dart' show deviceMemTotalMb, upscaleMemoryLines;
|
||||
|
||||
/// 기기 안에서 그리는 데 아직 받지 않은 파일 (Windows 는 실행 파일까지, TAESD 포함) - AI 그림 화면 · 받기 화면이 같은 값을 보인다 (139)
|
||||
List<AiFile> aiMissingFiles(AiStore store) => [
|
||||
|
|
@ -75,21 +75,10 @@ class _AiSettingsState extends State<AiSettings> {
|
|||
/// 176: 해상도 올리기 메모리 (적게 · 보통 · 많이) - 이 기기에서의 타일 · 예상 메모리
|
||||
Widget _upMemoryTile() {
|
||||
final mem = deviceMemTotalMb();
|
||||
String level(String id) {
|
||||
final t = androidUpscaleTile(memTotalMb: mem, share: upscaleMemoryShare(id));
|
||||
return trf('타일 {0} · 약 {1}GB', [t, (upscaleTileMemoryMb(t) / 1024).toStringAsFixed(1)]);
|
||||
}
|
||||
|
||||
return SettingTile(
|
||||
leading: const Icon(Icons.memory),
|
||||
title: Text(tr('해상도 올리기 메모리')),
|
||||
subtitle: Text([
|
||||
if (mem != null) trf('이 기기 메모리 {0}GB 기준:', [(mem / 1024).toStringAsFixed(0)]),
|
||||
trf('적게 (느림): {0}', [level('low')]),
|
||||
trf('보통: {0}', [level('normal')]),
|
||||
trf('많이 (빠름): {0} - 다른 앱이 많이 켜져 있으면 Android 가 이 앱을 끌 수 있습니다', [level('high')]),
|
||||
tr('타일이 작을수록 느립니다 (예: 16GB 폰에서 1024×768 을 2배로 - 512 약 4분 · 320 약 9분 30초).'),
|
||||
].join('\n')),
|
||||
subtitle: Text(upscaleMemoryLines(mem).join('\n')),
|
||||
isThreeLine: true,
|
||||
trailing: DropdownButton<String>(
|
||||
value: c.settings.aiUpMemory,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import 'bookmark_ui.dart';
|
|||
import 'cef_setup.dart' show confirmCefWhenElevated;
|
||||
import 'confirm.dart';
|
||||
import 'downloads_page.dart';
|
||||
import 'key_hint.dart';
|
||||
import 'settings_page.dart';
|
||||
import 'tor_page.dart';
|
||||
import 'theme.dart';
|
||||
|
|
@ -759,11 +760,11 @@ class _BrowserPageState extends State<BrowserPage> with RouteAware {
|
|||
const SizedBox(width: 4),
|
||||
],
|
||||
// 웹 페이지 이동 (앱 화면 이동인 왼쪽 버튼과 구분되는 모양)
|
||||
btn(Icons.arrow_back_ios_new, tr('이전 페이지 (Alt+←)'), _canBack ? () => _nav?.back() : null),
|
||||
btn(Icons.arrow_forward_ios, tr('다음 페이지 (Alt+→)'), _canFwd ? () => _nav?.forward() : null),
|
||||
btn(Icons.arrow_back_ios_new, keyHint(tr('이전 페이지'), 'Alt+←'), _canBack ? () => _nav?.back() : null),
|
||||
btn(Icons.arrow_forward_ios, keyHint(tr('다음 페이지'), 'Alt+→'), _canFwd ? () => _nav?.forward() : null),
|
||||
_progress < 1
|
||||
? btn(Icons.close, tr('중지'), () => _nav?.stop())
|
||||
: btn(Icons.refresh, tr('새로고침 (F5)'), () => _nav?.reload()),
|
||||
: btn(Icons.refresh, keyHint(tr('새로고침'), 'F5'), () => _nav?.reload()),
|
||||
if (!compact) btn(Icons.home_outlined, tr('홈'), () => _go(widget.c.settings.homeUrl)),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
|
|
@ -775,12 +776,12 @@ class _BrowserPageState extends State<BrowserPage> with RouteAware {
|
|||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: JjColors.bg,
|
||||
hintText: tr('주소 입력 또는 검색 (Ctrl+L)'),
|
||||
hintText: keyHint(tr('주소 입력 또는 검색'), 'Ctrl+L'),
|
||||
prefixIcon: Icon(_url.startsWith('https') ? Icons.lock_outline : Icons.public, size: 16),
|
||||
prefixIconConstraints: const BoxConstraints(minWidth: 32),
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(18), borderSide: BorderSide.none),
|
||||
suffixIcon: IconButton(
|
||||
tooltip: starred ? tr('즐겨찾기 수정 (Ctrl+D)') : tr('즐겨찾기 추가 (Ctrl+D)'),
|
||||
tooltip: starred ? keyHint(tr('즐겨찾기 수정'), 'Ctrl+D') : keyHint(tr('즐겨찾기 추가'), 'Ctrl+D'),
|
||||
icon: Icon(starred ? Icons.star : Icons.star_border, size: 18,
|
||||
color: starred ? Colors.amber : JjColors.textDim),
|
||||
onPressed: _star,
|
||||
|
|
@ -842,10 +843,10 @@ class _BrowserPageState extends State<BrowserPage> with RouteAware {
|
|||
),
|
||||
),
|
||||
if (!compact)
|
||||
btn(_work ? Icons.view_sidebar : Icons.view_sidebar_outlined, tr('작업 현황 보기 · 화면 분할 (Ctrl+Shift+J)'),
|
||||
btn(_work ? Icons.view_sidebar : Icons.view_sidebar_outlined, keyHint(tr('작업 현황 보기 · 화면 분할'), 'Ctrl+Shift+J'),
|
||||
_toggleWork, color: widget.c.busy ? JjColors.accent : null),
|
||||
if (!compact)
|
||||
btn(_panel ? Icons.bookmarks : Icons.bookmarks_outlined, tr('즐겨찾기 관리 (Ctrl+Shift+B)'),
|
||||
btn(_panel ? Icons.bookmarks : Icons.bookmarks_outlined, keyHint(tr('즐겨찾기 관리'), 'Ctrl+Shift+B'),
|
||||
() => setState(() => _panel = !_panel))
|
||||
else
|
||||
PopupMenuButton<String>(
|
||||
|
|
@ -1695,7 +1696,7 @@ class _BookmarkPanelState extends State<BookmarkPanel> {
|
|||
const Spacer(),
|
||||
if (widget.onOpenManager != null)
|
||||
IconButton(
|
||||
tooltip: tr('즐겨찾기 관리자 (Ctrl+Shift+O)'),
|
||||
tooltip: keyHint(tr('즐겨찾기 관리자'), 'Ctrl+Shift+O'),
|
||||
iconSize: 18,
|
||||
icon: const Icon(Icons.open_in_full),
|
||||
onPressed: () => widget.onOpenManager!(folderId: _folderId),
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import '../core/webdav.dart' show DavRegistry;
|
|||
import '../platform/android/android_storage.dart';
|
||||
import 'app_actions.dart';
|
||||
import 'explorer_look.dart';
|
||||
import 'key_hint.dart';
|
||||
import 'monitor_page.dart';
|
||||
import 'player_page.dart';
|
||||
import 'rsync_setup.dart';
|
||||
|
|
@ -3164,13 +3165,13 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
List<Widget> _headerStart(_Pane pane) => [
|
||||
// 75: 이 창의 뒤로 · 앞으로 (가 본 폴더)
|
||||
IconButton(
|
||||
tooltip: tr('뒤로 (Alt+←)'),
|
||||
tooltip: keyHint(tr('뒤로'), 'Alt+←'),
|
||||
visualDensity: VisualDensity.compact,
|
||||
icon: const Icon(Icons.arrow_back, size: 16),
|
||||
onPressed: pane.back.isEmpty ? null : () => _travel(pane, forward: false),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: tr('앞으로 (Alt+→)'),
|
||||
tooltip: keyHint(tr('앞으로'), 'Alt+→'),
|
||||
visualDensity: VisualDensity.compact,
|
||||
icon: const Icon(Icons.arrow_forward, size: 16),
|
||||
onPressed: pane.forward.isEmpty ? null : () => _travel(pane, forward: true),
|
||||
|
|
|
|||
|
|
@ -1066,6 +1066,23 @@ class _VideoDetail extends StatelessWidget {
|
|||
],
|
||||
_Chip(trf('음성 {0}개', [audioCount])),
|
||||
]),
|
||||
// 198: 마지막 AI 자막의 원어를 자동 감지했으면 - 알림을 놓쳐도 여기서 다른 언어로 다시 만들 수 있게
|
||||
if (v.aiDetected != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
Wrap(crossAxisAlignment: WrapCrossAlignment.center, spacing: 8, children: [
|
||||
Text(trf('감지한 언어: {0} (자동 감지)', [languageOf(v.aiDetected).name]),
|
||||
style: const TextStyle(fontSize: 12, color: JjColors.textDim)),
|
||||
TextButton(
|
||||
onPressed: c.busy
|
||||
? null
|
||||
: () async {
|
||||
final lang = await pickSourceLanguage(context, languageOf(v.aiDetected));
|
||||
if (lang != null) await c.generateAiSubtitles([v], c.aiOptions.copyWith(source: lang));
|
||||
},
|
||||
child: Text(tr('다른 언어로 다시')),
|
||||
),
|
||||
]),
|
||||
],
|
||||
if (v.message != null) ...[
|
||||
const SizedBox(height: 12),
|
||||
Container(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
/// 194: 단축키 안내 "(Alt+←)" 는 키보드를 쓰는 PC 에서만 붙인다.
|
||||
/// 태블릿 · 폰에서는 이름만 (누를 키가 없고, TalkBack 도 "Alt 왼쪽 화살표" 까지 읽었다)
|
||||
String keyHint(String text, String keys) => Platform.isAndroid ? text : '$text ($keys)';
|
||||
|
|
@ -24,6 +24,16 @@ Future<void> showMigrationNotice(BuildContext context, AppController c) async {
|
|||
'zipComic' => tr('ZIP · CBZ 두 번 누르기: 만화 보기 → 목록. 되돌리기: 환경 설정 > 파일 탐색기 > ZIP · CBZ 를 만화로 보기'),
|
||||
'background' =>
|
||||
tr('백그라운드로 실행: 꺼짐 → 켜짐 (← 나 최근 앱에서 밀어도 작업이 계속됨). 되돌리기: 환경 설정 > Rsync > 백그라운드로 실행'),
|
||||
'explorerClickNew' => tr('파일 탐색기: 파일을 한 번 누르면 바로 엽니다 (고르기 · 메뉴는 길게 누르기). '
|
||||
'바꾸기: 환경 설정 > 파일 탐색기 > 누르기'),
|
||||
'dnsForced' => tr('DNS: 기기 DNS → 직접 지정 (8.8.8.8 · 8.8.4.4). 앱의 인터넷 연결 (브라우저 · 다운로드 · 업데이트) 은 이 서버로 주소를 찾습니다. '
|
||||
'되돌리기: 환경 설정 > 네트워크 · DNS > 시스템 DNS (끄기)'),
|
||||
'swipeNav' => tr('화면 가운데를 좌우로 밀면 다른 화면 (파일 탐색기 · 다운로드 등) 으로 넘어갑니다. '
|
||||
'끄기: 환경 설정 > 컴포넌트 > 좌우로 밀어 화면 이동'),
|
||||
'copySkipNewer' => tr('복사 · 이동: 받는 쪽 파일이 더 새것이면 건너뜁니다 (예전에는 예전 원본으로 덮어쓰고, 이동이면 원본도 지웠습니다). '
|
||||
'건너뛴 파일은 원본에 남고 끝 알림에 그 수가 나옵니다. 되돌리기: 환경 설정 > 파일 탐색기 (또는 Rsync) > 받는 쪽이 더 새것이면 건너뛰기'),
|
||||
'robocopyLinks' => tr('robocopy 복사 · 이동: 원본 안의 링크 · junction 은 따라가지 않고 건너뜁니다 (/XJ - 예전에는 링크가 가리키는 바깥 폴더의 파일까지 '
|
||||
'복사 · 이동했습니다). 링크째 복사하려면 robocopy 옵션 칸에 /SJ 를 넣으세요'),
|
||||
_ => id,
|
||||
};
|
||||
final open = await showDialog<bool>(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import '../core/srt.dart';
|
|||
import '../core/text_codec.dart';
|
||||
import '../services/preview_player.dart';
|
||||
import 'app_actions.dart';
|
||||
import 'key_hint.dart';
|
||||
import 'theme.dart';
|
||||
import 'timeline.dart';
|
||||
import '../l10n/tr.dart';
|
||||
|
|
@ -428,7 +429,7 @@ class _SubtitleEditorPageState extends State<SubtitleEditorPage> {
|
|||
onPressed: () => _seekBy(-5000),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: tr('재생/정지 (Ctrl+Space)'),
|
||||
tooltip: keyHint(tr('재생/정지'), 'Ctrl+Space'),
|
||||
iconSize: 30,
|
||||
icon: Icon(_playing ? Icons.pause_circle : Icons.play_circle,
|
||||
color: JjColors.accent),
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import '../core/web_address.dart';
|
|||
import '../platform/windows/com_guard.dart';
|
||||
import '../l10n/tr.dart';
|
||||
import 'app_actions.dart';
|
||||
import 'key_hint.dart';
|
||||
import 'settings_page.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
|
|
@ -501,11 +502,11 @@ class _TorPageState extends State<TorPage> with WebProxyVisibility {
|
|||
middle: LayoutBuilder(builder: (context, box) {
|
||||
final compact = box.maxWidth < 560;
|
||||
return Row(children: [
|
||||
btn(Icons.arrow_back_ios_new, tr('이전 페이지 (Alt+←)'), ready && _canBack ? () => _nav?.back() : null),
|
||||
btn(Icons.arrow_forward_ios, tr('다음 페이지 (Alt+→)'), ready && _canFwd ? () => _nav?.forward() : null),
|
||||
btn(Icons.arrow_back_ios_new, keyHint(tr('이전 페이지'), 'Alt+←'), ready && _canBack ? () => _nav?.back() : null),
|
||||
btn(Icons.arrow_forward_ios, keyHint(tr('다음 페이지'), 'Alt+→'), ready && _canFwd ? () => _nav?.forward() : null),
|
||||
_progress < 1
|
||||
? btn(Icons.close, tr('중지'), ready ? () => _nav?.stop() : null)
|
||||
: btn(Icons.refresh, tr('새로고침 (F5)'), ready ? () => _nav?.reload() : null),
|
||||
: btn(Icons.refresh, keyHint(tr('새로고침'), 'F5'), ready ? () => _nav?.reload() : null),
|
||||
if (!compact) btn(Icons.home_outlined, tr('홈'), ready ? () => _go(widget.c.settings.torHomeUrl) : null),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ void main() {
|
|||
expect(aiEstimateMinutes(const Duration(hours: 1), 0), (15, 30));
|
||||
expect(aiEstimateMinutes(const Duration(hours: 2), 2), (70, 140));
|
||||
expect(aiEstimateMinutes(Duration.zero, 2), isNull);
|
||||
// 197: 짧은 동영상은 '약 1~1분' 이 아니라 '1분 안', 같은 수면 하나만
|
||||
expect(aiEstimateText(aiEstimateMinutes(const Duration(seconds: 30), 0)!), '1분 안');
|
||||
expect(aiEstimateText((3, 3)), '약 3분');
|
||||
expect(aiEstimateText((15, 30)), '약 15~30분');
|
||||
final ko = languageOf('ko'), en = languageOf('en'), ja = languageOf('ja');
|
||||
expect(aiTranslateCount(AiOptions(source: ko, targets: {ko, en, ja}, whisper: whisperModels.first)), 2);
|
||||
expect(aiTranslateCount(AiOptions(targets: {ko, en, ja}, whisper: whisperModels.first)), 2, reason: '자동 감지면 하나는 원어로');
|
||||
|
|
@ -75,4 +79,32 @@ void main() {
|
|||
await done;
|
||||
expect(c.busy, isFalse);
|
||||
});
|
||||
testWidgets('198: 원어를 자동 감지했으면 끝난 뒤 "감지한 언어" 와 [다른 언어로 다시] (고른 원어로 다시)', (tester) async {
|
||||
final key = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(MaterialApp(navigatorKey: key, home: const Scaffold(body: SizedBox())));
|
||||
final v = VideoItem(r'D:\v\a.mp4')..aiDetected = 'ko';
|
||||
Language? again;
|
||||
showDetectedLanguage(tester.state<ScaffoldMessengerState>(find.byType(ScaffoldMessenger)), key.currentState!.overlay, [v],
|
||||
onRetry: (l) async => again = l);
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 800)); // 알림이 다 올라올 때까지
|
||||
expect(find.text('감지한 언어: 한국어 - 틀렸으면 다른 언어로 다시 만드세요'), findsOneWidget);
|
||||
// 248 과 같게: 닫을 때까지 남는다 ([✕])
|
||||
await tester.pump(const Duration(minutes: 1));
|
||||
expect(find.text('감지한 언어: 한국어 - 틀렸으면 다른 언어로 다시 만드세요'), findsOneWidget);
|
||||
expect(find.byIcon(Icons.close), findsOneWidget);
|
||||
await tester.tap(find.text('다른 언어로 다시'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('원어를 골라 다시 만들기'), findsOneWidget);
|
||||
expect(find.textContaining('- 감지한 언어'), findsOneWidget);
|
||||
await tester.tap(find.textContaining('영어 (en)'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(again?.code, 'en');
|
||||
// 원어를 직접 고른 동영상 (감지 안 함) 만 있으면 알리지 않는다
|
||||
final w = VideoItem(r'D:\v\b.mp4');
|
||||
showDetectedLanguage(tester.state<ScaffoldMessengerState>(find.byType(ScaffoldMessenger)), key.currentState!.overlay, [w],
|
||||
onRetry: (_) async {});
|
||||
await tester.pump(const Duration(seconds: 13));
|
||||
expect(find.textContaining('감지한 언어:'), findsNothing);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -293,6 +293,23 @@ void main() {
|
|||
reason: '${v1.message} ${v2.message} ${v3.message}');
|
||||
});
|
||||
|
||||
testWidgets('198: 원어를 자동 감지한 동영상은 세부 정보에 감지한 언어 · [다른 언어로 다시] (알림을 놓쳐도)', (tester) async {
|
||||
tester.view.physicalSize = const Size(1600, 900);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.reset);
|
||||
final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()));
|
||||
c.videos.add(VideoItem(r'D:\v\a.mp4')..aiDetected = 'ko');
|
||||
c.selected = c.videos.first;
|
||||
await tester.pumpWidget(MaterialApp(home: HomePage(c: c)));
|
||||
expect(find.text('감지한 언어: 한국어 (자동 감지)'), findsOneWidget);
|
||||
expect(find.widgetWithText(TextButton, '다른 언어로 다시'), findsOneWidget);
|
||||
// 원어를 직접 고르면 (null) 보이지 않는다
|
||||
c.videos.first.aiDetected = null;
|
||||
c.selected = c.videos.first;
|
||||
await tester.pumpWidget(MaterialApp(key: UniqueKey(), home: HomePage(c: c)));
|
||||
expect(find.textContaining('감지한 언어'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('MKV 화면: 체크 → "자막 만들기 (2)" · "MKV 만들기 (2)" 글, 전체 선택', (tester) async {
|
||||
tester.view.physicalSize = const Size(1600, 900); // 위쪽 버튼 글이 다 보이는 너비
|
||||
tester.view.devicePixelRatio = 1;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:jj_mkvmaker/ui/key_hint.dart';
|
||||
|
||||
/// 194: 단축키 안내는 PC 에서만 (태블릿 · 폰은 이름만 - TalkBack 도 이름만 읽게)
|
||||
void main() {
|
||||
test('194: keyHint - PC 는 "이름 (키)", Android 는 이름만', () {
|
||||
expect(keyHint('뒤로', 'Alt+←'), Platform.isAndroid ? '뒤로' : '뒤로 (Alt+←)');
|
||||
});
|
||||
}
|
||||
|
|
@ -84,4 +84,34 @@ void main() {
|
|||
// 처음 설치 (빈 설정) 는 알릴 것 없음
|
||||
expect(AppSettings.fromJson({}).migrated, isEmpty);
|
||||
});
|
||||
|
||||
test('193: 예전 판에서 올라오면 바뀐 동작 (229 받는 쪽이 더 새것이면 건너뜀 · robocopy 링크) 을 한 번 알린다', () {
|
||||
final old = AppSettings.fromJson({'copyMethodFolder': 'robocopy', 'explorerV2': true});
|
||||
expect(old.migrated, contains('copySkipNewer'));
|
||||
expect(old.migrated.contains('robocopyLinks'), Platform.isWindows, reason: 'robocopy 는 Windows 만');
|
||||
// 저장 뒤 다시 읽으면 알리지 않음
|
||||
final again = AppSettings.fromJson(old.toJson());
|
||||
expect(again.migrated, isNot(contains('copySkipNewer')));
|
||||
expect(again.migrated, isNot(contains('robocopyLinks')));
|
||||
// robocopy 를 쓰지 않던 사람에게는 링크 알림 없음
|
||||
expect(AppSettings.fromJson({'explorerV2': true}).migrated, isNot(contains('robocopyLinks')));
|
||||
});
|
||||
|
||||
test('193: 그 설정이 없던 예전 판 (10.03 모양 - 키 없음) 에서 올라오면 바로 겪는 동작 변화를 알린다 · 처음 설치는 없음', () {
|
||||
// 10.03 의 설정 파일: 탐색기 · 화면 이동 · 백그라운드 설정이 아직 없던 때 (있는 것은 그때의 항목들)
|
||||
final old = AppSettings.fromJson({'theme': 'dark', 'outputFolderName': 'jj_mkv'});
|
||||
expect(old.migrated, contains('swipeNav'));
|
||||
// DNS 강제가 없던 판 (10.10 까지) 에서 올라오면 처음 값 직접 지정으로 바뀐 것을 알림 · 이미 고른 사람은 알리지 않음
|
||||
expect(old.migrated, contains('dnsForced'));
|
||||
expect(AppSettings.fromJson({'theme': 'dark', 'dnsMode': 'system'}).migrated, isNot(contains('dnsForced')));
|
||||
if (Platform.isAndroid) {
|
||||
expect(old.migrated, containsAll(['explorerClickNew', 'orientation', 'background']));
|
||||
} else {
|
||||
expect(old.migrated, isNot(contains('explorerClickNew')), reason: 'PC 는 처음 값이 한 번 누르면 고르기 (바뀐 것 없음)');
|
||||
}
|
||||
// 저장 뒤 다시 읽으면 알리지 않음
|
||||
expect(AppSettings.fromJson(old.toJson()).migrated, isEmpty);
|
||||
// 처음 설치 (설정 파일 없음) 는 알릴 것 없음
|
||||
expect(AppSettings.fromJson({}).migrated, isEmpty);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,14 @@ void main() {
|
|||
expect(androidUpscaleTile(memTotalMb: 40000, share: 0.20), 512);
|
||||
expect(androidUpscaleTile(memTotalMb: 6000, share: 0.20), 192);
|
||||
expect(androidUpscaleTile(longSide: 1024), 256);
|
||||
// 192: 메모리가 작은 기기 (P11 4GB, MemTotal 약 3.5GB) 는 셋 다 가장 작은 타일 - 같은 값을 세 번 보이지 않고 같다고 알린다
|
||||
final small = upscaleMemoryLines(3500);
|
||||
expect(small.where((l) => l.contains('모두 같습니다')), hasLength(1));
|
||||
expect(small.where((l) => l.startsWith('적게') || l.startsWith('많이')), isEmpty);
|
||||
// 16GB 는 셋이 다르다
|
||||
expect(upscaleMemoryLines(15000).where((l) => l.contains('같')), isEmpty);
|
||||
// 일부만 같으면 그 줄에 (보통과 같음)
|
||||
expect(upscaleMemoryLines(5000).where((l) => l.contains('(보통과 같음)')), isNotEmpty);
|
||||
expect(androidUpscaleTile(longSide: 800), 512);
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue