mirror of
https://github.com/mifi/lossless-cut.git
synced 2024-11-22 10:22:31 +01:00
add more translatables
This commit is contained in:
parent
1a5e80515c
commit
1340885ecf
@ -143,12 +143,14 @@
|
||||
"Output name(s):": "Output name(s):",
|
||||
"Preview": "Preview",
|
||||
"Reset": "Reset",
|
||||
"There is an error in the file name template:": "There is an error in the file name template:",
|
||||
"Variables": "Variables",
|
||||
"Toggle advanced view": "Toggle advanced view",
|
||||
"Show export options screen before exporting?": "Show export options screen before exporting?",
|
||||
"Default": "Default",
|
||||
"Done": "Done",
|
||||
"Set custom start time offset": "Set custom start time offset",
|
||||
"Instead of video apparently starting at 0, you can offset by a specified value. This only applies to the preview inside LosslessCut and does not modify the file in any way. Useful for viewing/cutting videos according to timecodes)": "Instead of video apparently starting at 0, you can offset by a specified value. This only applies to the preview inside LosslessCut and does not modify the file in any way. Useful for viewing/cutting videos according to timecodes)",
|
||||
"Instead of video apparently starting at 0, you can offset by a specified value. This only applies to the preview inside LosslessCut and does not modify the file in any way. (Useful for viewing/cutting videos according to timecodes)": "Instead of video apparently starting at 0, you can offset by a specified value. This only applies to the preview inside LosslessCut and does not modify the file in any way. (Useful for viewing/cutting videos according to timecodes)",
|
||||
"Fastest: Low playback speed (no audio)": "Fastest: Low playback speed (no audio)",
|
||||
"Fastest: Low playback speed": "Fastest: Low playback speed",
|
||||
"Fast: Full quality remux (no audio), likely to fail": "Fast: Full quality remux (no audio), likely to fail",
|
||||
@ -194,10 +196,21 @@
|
||||
"Copy to YouTube description/comment:": "Copy to YouTube description/comment:",
|
||||
"Label current segment": "Label current segment",
|
||||
"Max length": "Max length",
|
||||
"Try one of the following before exporting again:": "Try one of the following before exporting again:",
|
||||
"Change output <1>Format</1> from <3>MP4</3> to <5>MOV</5>": "Change output <1>Format</1> from <3>MP4</3> to <5>MOV</5>",
|
||||
"Select a different output <1>Format</1> (<3>matroska</3> and <5>mp4</5> support most codecs)": "Select a different output <1>Format</1> (<3>matroska</3> and <5>mp4</5> support most codecs)",
|
||||
"Disable unnecessary <1>Tracks</1>": "Disable unnecessary <1>Tracks</1>",
|
||||
"Try both <1>Normal cut</1> and <3>Keyframe cut</3>": "Try both <1>Normal cut</1> and <3>Keyframe cut</3>",
|
||||
"Set a different <1>Working directory</1>": "Set a different <1>Working directory</1>",
|
||||
"Try with a <1>Different file</1>": "Try with a <1>Different file</1>",
|
||||
"See <1>Help</1>": "See <1>Help</1>",
|
||||
"If nothing helps, you can send an <1>Error report</1>": "If nothing helps, you can send an <1>Error report</1>",
|
||||
"No rows found": "No rows found",
|
||||
"One or more rows does not have 3 columns": "One or more rows does not have 3 columns",
|
||||
"Invalid start or end value. Must contain a number of seconds": "Invalid start or end value. Must contain a number of seconds",
|
||||
"Invalid EDL data found": "Invalid EDL data found",
|
||||
"Something went wrong": "Something went wrong",
|
||||
"Report error": "Report error",
|
||||
"Preserve all MOV/MP4 metadata tags (e.g. EXIF, GPS position etc.) from source file? Note that some players have trouble playing back files where all metadata is preserved, like iTunes and other Apple software": "Preserve all MOV/MP4 metadata tags (e.g. EXIF, GPS position etc.) from source file? Note that some players have trouble playing back files where all metadata is preserved, like iTunes and other Apple software",
|
||||
"Enable this to allow faster playback of the resulting file. This may cause processing to take a little longer": "Enable this to allow faster playback of the resulting file. This may cause processing to take a little longer",
|
||||
"Defaults to same format as input file. You can losslessly change the file format (container) of the file with this option. Not all formats support all codecs. Matroska/MP4/MOV support the most common codecs. Sometimes it's even impossible to export to the same output format as input.": "Defaults to same format as input file. You can losslessly change the file format (container) of the file with this option. Not all formats support all codecs. Matroska/MP4/MOV support the most common codecs. Sometimes it's even impossible to export to the same output format as input.",
|
||||
@ -281,6 +294,8 @@
|
||||
"Last ffmpeg commands": "Last ffmpeg commands",
|
||||
"The last executed ffmpeg commands will show up here after you run operations. You can copy them to clipboard and modify them to your needs before running on your command line.": "The last executed ffmpeg commands will show up here after you run operations. You can copy them to clipboard and modify them to your needs before running on your command line.",
|
||||
"<0>Note:</0> Keyframe cut and Merge cuts buttons have been moved to the export panel (press Export to see it.)": "<0>Note:</0> Keyframe cut and Merge cuts buttons have been moved to the export panel (press Export to see it.)",
|
||||
"Try to set the <1>start-</1>cutpoint a <3>few frames before or after</3> the nearest keyframe (may also solve audio sync issues)": "Try to set the <1>start-</1>cutpoint a <3>few frames before or after</3> the nearest keyframe (may also solve audio sync issues)",
|
||||
"Try to enable the <1>Experimental Flag</1> in Settings": "Try to enable the <1>Experimental Flag</1> in Settings",
|
||||
"Unable to save your preferences. Try to disable any anti-virus": "Unable to save your preferences. Try to disable any anti-virus",
|
||||
"When you export, selected segments on the timeline will be REMOVED - the surrounding areas will be KEPT": "When you export, selected segments on the timeline will be REMOVED - the surrounding areas will be KEPT",
|
||||
"When you export, selected segments on the timeline will be KEPT - the surrounding areas will be REMOVED.": "When you export, selected segments on the timeline will be KEPT - the surrounding areas will be REMOVED.",
|
||||
@ -296,7 +311,14 @@
|
||||
"Include all tracks?": "Include all tracks?",
|
||||
"If this is checked, all audio/video/subtitle/data tracks will be included. This may not always work for all file types. If not checked, only default streams will be included.": "If this is checked, all audio/video/subtitle/data tracks will be included. This may not always work for all file types. If not checked, only default streams will be included.",
|
||||
"DROP FILE(S)": "DROP FILE(S)",
|
||||
"to show advanced view": "to show advanced view",
|
||||
"to show simple view": "to show simple view",
|
||||
"Press <1>H</1> for help": "Press <1>H</1> for help",
|
||||
"<0></0> <2></2> or <4>I</4> <6>O</6> to set cutpoints": "<0></0> <2></2> or <4>I</4> <6>O</6> to set cutpoints",
|
||||
"Send problem report": "Send problem report",
|
||||
"Please send an email to <1>losslesscut@yankee.no</1> where you describe what you were doing.": "Please send an email to <1>losslesscut@yankee.no</1> where you describe what you were doing.",
|
||||
"Please create an issue at <1>https://github.com/mifi/lossless-cut/issues</1> where you describe what you were doing.": "Please create an issue at <1>https://github.com/mifi/lossless-cut/issues</1> where you describe what you were doing.",
|
||||
"Include the following text:": "Include the following text:",
|
||||
"Set output rotation. Current: ": "Set output rotation. Current: ",
|
||||
"Don't modify": "Don't modify",
|
||||
"Close file and clean up": "Close file and clean up",
|
||||
@ -320,6 +342,7 @@
|
||||
"Invalid number entered": "Invalid number entered",
|
||||
"Segments total:": "Segments total:",
|
||||
"Close sidebar": "Close sidebar",
|
||||
"<0>{{durationMsFormatted}}</0> ms, <2>{{frameCount}}</2> frames": "<0>{{durationMsFormatted}}</0> ms, <2>{{frameCount}}</2> frames",
|
||||
"System language": "System language",
|
||||
"Working directory": "Working directory",
|
||||
"This is where working files, exported files, project files (CSV) are stored.": "This is where working files, exported files, project files (CSV) are stored.",
|
||||
@ -329,6 +352,8 @@
|
||||
"Source file's time": "Source file's time",
|
||||
"Current time": "Current time",
|
||||
"Keyframe cut mode": "Keyframe cut mode",
|
||||
"Cut at the nearest keyframe (not accurate time.) Equiv to": "Cut at the nearest keyframe (not accurate time.) Equiv to",
|
||||
"Accurate time but could leave an empty portion at the beginning of the video. Equiv to": "Accurate time but could leave an empty portion at the beginning of the video. Equiv to",
|
||||
"Choose cutting mode: Remove or keep selected segments from video when exporting?": "Choose cutting mode: Remove or keep selected segments from video when exporting?",
|
||||
"Keep": "Keep",
|
||||
"The video inside segments will be kept, while the video outside will be discarded.": "The video inside segments will be kept, while the video outside will be discarded.",
|
||||
|
@ -1,4 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
|
||||
import { openSendReportDialog } from './reporting';
|
||||
|
||||
class ErrorBoundary extends Component {
|
||||
@ -20,9 +22,9 @@ class ErrorBoundary extends Component {
|
||||
if (error) {
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
|
||||
<h1>Something went wrong</h1>
|
||||
<h1><Trans>Something went wrong</Trans></h1>
|
||||
<div style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all' }}>{error.message}</div>
|
||||
<p><button type="button" onClick={() => openSendReportDialog(error)} style={{ padding: 10, fontSize: 20 }}>Report error</button></p>
|
||||
<p><button type="button" onClick={() => openSendReportDialog(error)} style={{ padding: 10, fontSize: 20 }}><Trans>Report error</Trans></button></p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -23,11 +23,11 @@ const HelpSheet = memo(({ visible, onTogglePress, ffmpegCommandLog, currentCutSe
|
||||
{t('Lossless cutting is not an exact science. For some codecs and files it just works. For others you may need to trial and error depending on the codec, keyframes etc to get the best cut.')}
|
||||
</p>
|
||||
<ol>
|
||||
<li>Try both <b>Keyframe cut</b> and <b>Normal cut</b> modes</li>
|
||||
<li>Try to set the <b>start-</b>cutpoint a <b>few frames before or after</b> the nearest keyframe (may also solve audio sync issues)</li>
|
||||
<li>Try to disable some <b>Tracks</b></li>
|
||||
<li>Try a different <b>Output format</b></li>
|
||||
<li>Try to enable the <b>Experimental Flag</b> in Settings</li>
|
||||
<li><Trans>Try both <b>Normal cut</b> and <b>Keyframe cut</b></Trans></li>
|
||||
<li><Trans>Try to set the <b>start-</b>cutpoint a <b>few frames before or after</b> the nearest keyframe (may also solve audio sync issues)</Trans></li>
|
||||
<li><Trans>Disable unnecessary <b>Tracks</b></Trans></li>
|
||||
<li><Trans>Select a different output <b>Format</b> (<b>matroska</b> and <b>mp4</b> support most codecs)</Trans></li>
|
||||
<li><Trans>Try to enable the <b>Experimental Flag</b> in Settings</Trans></li>
|
||||
</ol>
|
||||
|
||||
<p style={{ fontWeight: 'bold' }}>
|
||||
|
@ -1,7 +1,8 @@
|
||||
import React, { memo } from 'react';
|
||||
import { FaHandPointRight, FaHandPointLeft } from 'react-icons/fa';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next';
|
||||
|
||||
import SetCutpointButton from './components/SetCutpointButton';
|
||||
import SimpleModeButton from './components/SimpleModeButton';
|
||||
@ -16,15 +17,15 @@ const NoFileLoaded = memo(({ topBarHeight, bottomBarHeight, mifiLink, toggleHelp
|
||||
<div style={{ fontSize: '6vmin', textTransform: 'uppercase' }}>{t('DROP FILE(S)')}</div>
|
||||
|
||||
<div style={{ fontSize: '4vmin', color: '#777', cursor: 'pointer' }} role="button" onClick={toggleHelp}>
|
||||
Press <kbd>H</kbd> for help
|
||||
<Trans>Press <kbd>H</kbd> for help</Trans>
|
||||
</div>
|
||||
|
||||
<div style={{ fontSize: '3vmin', color: '#ccc' }}>
|
||||
<SetCutpointButton currentCutSeg={currentCutSeg} side="start" Icon={FaHandPointLeft} style={{ verticalAlign: 'middle' }} /> <SetCutpointButton currentCutSeg={currentCutSeg} side="end" Icon={FaHandPointRight} style={{ verticalAlign: 'middle' }} /> or <kbd>I</kbd> <kbd>O</kbd> to set cutpoints
|
||||
<Trans><SetCutpointButton currentCutSeg={currentCutSeg} side="start" Icon={FaHandPointLeft} style={{ verticalAlign: 'middle' }} /> <SetCutpointButton currentCutSeg={currentCutSeg} side="end" Icon={FaHandPointRight} style={{ verticalAlign: 'middle' }} /> or <kbd>I</kbd> <kbd>O</kbd> to set cutpoints</Trans>
|
||||
</div>
|
||||
|
||||
<div style={{ fontSize: '3vmin', color: '#ccc', cursor: 'pointer' }} role="button" onClick={toggleSimpleMode}>
|
||||
<SimpleModeButton simpleMode={simpleMode} toggleSimpleMode={toggleSimpleMode} style={{ verticalAlign: 'middle' }} size={16} /> {simpleMode ? 'to show advanced view' : 'to show simple view'}
|
||||
<SimpleModeButton simpleMode={simpleMode} toggleSimpleMode={toggleSimpleMode} style={{ verticalAlign: 'middle' }} size={16} /> {simpleMode ? i18n.t('to show advanced view') : i18n.t('to show simple view')}
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { FaSave, FaPlus, FaMinus, FaTag, FaSortNumericDown, FaAngleRight, FaChec
|
||||
import { AiOutlineSplitCells } from 'react-icons/ai';
|
||||
import { motion } from 'framer-motion';
|
||||
import Swal from 'sweetalert2';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useTranslation, Trans } from 'react-i18next';
|
||||
import { ReactSortable } from 'react-sortablejs';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import useDebounce from 'react-use/lib/useDebounce';
|
||||
@ -78,6 +78,9 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou
|
||||
jumpSegStart();
|
||||
}
|
||||
|
||||
const durationMsFormatted = Math.floor(durationMs);
|
||||
const frameCount = getFrameCount(duration);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
ref={ref}
|
||||
@ -99,7 +102,7 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou
|
||||
{t('Duration')} {prettyMs(durationMs)}
|
||||
</div>
|
||||
<div style={{ fontSize: 12 }}>
|
||||
({Math.floor(durationMs)} ms, {getFrameCount(duration)} frames)
|
||||
<Trans>{{ durationMsFormatted }} ms, {{ frameCount }} frames</Trans>
|
||||
</div>
|
||||
|
||||
{!enabled && !invertCutSegments && (
|
||||
|
@ -82,8 +82,8 @@ const Settings = memo(({
|
||||
<Row>
|
||||
<KeyCell>
|
||||
{t('Keyframe cut mode')}<br />
|
||||
<b>{t('Keyframe cut')}</b>: Cut at the nearest keyframe (not accurate time.) Equiv to <i>ffmpeg -ss -i ...</i><br />
|
||||
<b>{t('Normal cut')}</b>: Accurate time but could leave an empty portion at the beginning of the video. Equiv to <i>ffmpeg -i -ss ...</i><br />
|
||||
<b>{t('Keyframe cut')}</b>: {t('Cut at the nearest keyframe (not accurate time.) Equiv to')} <i>ffmpeg -ss -i ...</i><br />
|
||||
<b>{t('Normal cut')}</b>: {t('Accurate time but could leave an empty portion at the beginning of the video. Equiv to')} <i>ffmpeg -i -ss ...</i><br />
|
||||
</KeyCell>
|
||||
<Table.TextCell>
|
||||
<SegmentedControl
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { memo, useState, useEffect } from 'react';
|
||||
import { useDebounce } from 'use-debounce';
|
||||
import i18n from 'i18next';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Alert } from 'evergreen-ui';
|
||||
import Swal from 'sweetalert2';
|
||||
@ -77,9 +78,9 @@ const OutSegTemplateEditor = memo(({ helpIcon, outSegTemplate, setOutSegTemplate
|
||||
<Button height={20} onClick={onToggleClick} style={{ marginLeft: 5 }} intent="success">{t('Close')}</Button>
|
||||
</div>
|
||||
<div>
|
||||
{error != null && <Alert intent="danger" appearance="card">{`There is an error in the file name template: ${error}`}</Alert>}
|
||||
{error != null && <Alert intent="danger" appearance="card">{`${i18n.t('There is an error in the file name template:')} ${error}`}</Alert>}
|
||||
{/* eslint-disable-next-line no-template-curly-in-string */}
|
||||
<div style={{ fontSize: '.8em', color: 'rgba(255,255,255,0.7)' }}>{'Variables: ${FILENAME} ${CUT_FROM} ${CUT_TO} ${SEG_NUM} ${SEG_LABEL} ${SEG_SUFFIX} ${EXT}'}</div>
|
||||
<div style={{ fontSize: '.8em', color: 'rgba(255,255,255,0.7)' }}>{`${i18n.t('Variables')}`} {'${FILENAME} ${CUT_FROM} ${CUT_TO} ${SEG_NUM} ${SEG_LABEL} ${SEG_SUFFIX} ${EXT}'}</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import Swal from 'sweetalert2';
|
||||
import i18n from 'i18next';
|
||||
import { Trans } from 'react-i18next';
|
||||
import withReactContent from 'sweetalert2-react-content';
|
||||
|
||||
import { parseDuration } from './util/duration';
|
||||
@ -16,7 +17,7 @@ const ReactSwal = withReactContent(Swal);
|
||||
export async function promptTimeOffset(inputValue) {
|
||||
const { value } = await Swal.fire({
|
||||
title: i18n.t('Set custom start time offset'),
|
||||
text: i18n.t('Instead of video apparently starting at 0, you can offset by a specified value. This only applies to the preview inside LosslessCut and does not modify the file in any way. Useful for viewing/cutting videos according to timecodes)'),
|
||||
text: i18n.t('Instead of video apparently starting at 0, you can offset by a specified value. This only applies to the preview inside LosslessCut and does not modify the file in any way. (Useful for viewing/cutting videos according to timecodes)'),
|
||||
input: 'text',
|
||||
inputValue: inputValue || '',
|
||||
showCancelButton: true,
|
||||
@ -247,16 +248,16 @@ export async function createFixedDurationSegments(fileDuration) {
|
||||
export async function showCutFailedDialog({ detectedFileFormat }) {
|
||||
const html = (
|
||||
<div style={{ textAlign: 'left' }}>
|
||||
Try one of the following before exporting again:
|
||||
<Trans>Try one of the following before exporting again:</Trans>
|
||||
<ol>
|
||||
{detectedFileFormat === 'mp4' && <li>Change output <b>Format</b> from <b>MP4</b> to <b>MOV</b></li>}
|
||||
<li>Select a different output <b>Format</b> (<b>matroska</b> and <b>mp4</b> support most codecs)</li>
|
||||
<li>Disable unnecessary <b>Tracks</b></li>
|
||||
<li>Try both <b>Normal cut</b> and <b>Keyframe cut</b></li>
|
||||
<li>Set a different <b>Working directory</b></li>
|
||||
<li>Try with a <b>Different file</b></li>
|
||||
<li>See <b>Help</b></li>
|
||||
<li>If nothing helps, you can send an <b>Error report</b></li>
|
||||
{detectedFileFormat === 'mp4' && <li><Trans>Change output <b>Format</b> from <b>MP4</b> to <b>MOV</b></Trans></li>}
|
||||
<li><Trans>Select a different output <b>Format</b> (<b>matroska</b> and <b>mp4</b> support most codecs)</Trans></li>
|
||||
<li><Trans>Disable unnecessary <b>Tracks</b></Trans></li>
|
||||
<li><Trans>Try both <b>Normal cut</b> and <b>Keyframe cut</b></Trans></li>
|
||||
<li><Trans>Set a different <b>Working directory</b></Trans></li>
|
||||
<li><Trans>Try with a <b>Different file</b></Trans></li>
|
||||
<li><Trans>See <b>Help</b></Trans></li>
|
||||
<li><Trans>If nothing helps, you can send an <b>Error report</b></Trans></li>
|
||||
</ol>
|
||||
</div>
|
||||
);
|
||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||
import Swal from 'sweetalert2';
|
||||
import withReactContent from 'sweetalert2-react-content';
|
||||
import i18n from 'i18next';
|
||||
import { Trans } from 'react-i18next';
|
||||
|
||||
import CopyClipboardButton from './components/CopyClipboardButton';
|
||||
import { isStoreBuild, isMasBuild, isWindowsStoreBuild } from './util';
|
||||
@ -15,8 +16,8 @@ const ReactSwal = withReactContent(Swal);
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function openSendReportDialog(err, state) {
|
||||
const reportInstructions = isStoreBuild
|
||||
? <p>Please send an email to <span style={{ fontWeight: 'bold' }} role="button" onClick={() => electron.shell.openExternal('mailto:losslesscut@yankee.no')}>losslesscut@yankee.no</span> where you describe what you were doing.</p>
|
||||
: <p>Please create an issue at <span style={{ fontWeight: 'bold' }} role="button" onClick={() => electron.shell.openExternal('https://github.com/mifi/lossless-cut/issues')}>https://github.com/mifi/lossless-cut/issues</span> where you describe what you were doing.</p>;
|
||||
? <p><Trans>Please send an email to <span style={{ fontWeight: 'bold' }} role="button" onClick={() => electron.shell.openExternal('mailto:losslesscut@yankee.no')}>losslesscut@yankee.no</span> where you describe what you were doing.</Trans></p>
|
||||
: <p><Trans>Please create an issue at <span style={{ fontWeight: 'bold' }} role="button" onClick={() => electron.shell.openExternal('https://github.com/mifi/lossless-cut/issues')}>https://github.com/mifi/lossless-cut/issues</span> where you describe what you were doing.</Trans></p>;
|
||||
|
||||
const platform = os.platform();
|
||||
const version = electron.remote.app.getVersion();
|
||||
@ -48,7 +49,7 @@ export function openSendReportDialog(err, state) {
|
||||
<div style={{ textAlign: 'left', overflow: 'auto', maxHeight: 300, overflowY: 'auto' }}>
|
||||
{reportInstructions}
|
||||
|
||||
<p>Include the following text: <CopyClipboardButton text={text} /></p>
|
||||
<p><Trans>Include the following text:</Trans> <CopyClipboardButton text={text} /></p>
|
||||
|
||||
<div style={{ fontWeight: 600, fontSize: 12, whiteSpace: 'pre-wrap' }} contentEditable suppressContentEditableWarning>
|
||||
{text}
|
||||
|
Loading…
Reference in New Issue
Block a user