kopia lustrzana https://github.com/OpenDroneMap/WebODM
More translation strings
rodzic
ba3fd861b8
commit
28f35de733
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import '../css/AssetDownloadButtons.scss';
|
||||
import AssetDownloads from '../classes/AssetDownloads';
|
||||
import PropTypes from 'prop-types';
|
||||
import { _ } from '../classes/gettext';
|
||||
|
||||
class AssetDownloadButtons extends React.Component {
|
||||
static defaultProps = {
|
||||
|
@ -29,7 +30,7 @@ class AssetDownloadButtons extends React.Component {
|
|||
|
||||
return (<div className={"asset-download-buttons " + (this.props.showLabel ? "btn-group" : "") + " " + (this.props.direction === "up" ? "dropup" : "")}>
|
||||
<button type="button" className={"btn btn-sm " + this.props.buttonClass} disabled={this.props.disabled} data-toggle="dropdown">
|
||||
<i className="glyphicon glyphicon-download"></i>{this.props.showLabel ? " Download Assets" : ""}
|
||||
<i className="glyphicon glyphicon-download"></i>{this.props.showLabel ? " " + _("Download Assets") : ""}
|
||||
</button>
|
||||
{this.props.showLabel ?
|
||||
<button type="button" className={"btn btn-sm dropdown-toggle " + this.props.buttonClass} data-toggle="dropdown" disabled={this.props.disabled}>
|
||||
|
|
|
@ -4,8 +4,8 @@ import FormDialog from './FormDialog';
|
|||
import ProcessingNodeOption from './ProcessingNodeOption';
|
||||
import PresetUtils from '../classes/PresetUtils';
|
||||
import PropTypes from 'prop-types';
|
||||
import $ from 'jquery';
|
||||
import values from 'object.values';
|
||||
import { _ } from '../classes/gettext';
|
||||
|
||||
if (!Object.values) {
|
||||
values.shim();
|
||||
|
@ -92,13 +92,13 @@ class EditPresetDialog extends React.Component {
|
|||
show={true}
|
||||
onShow={this.onShow}
|
||||
saveIcon="far fa-edit"
|
||||
title="Edit Task Options"
|
||||
title={_("Edit Task Options")}
|
||||
saveAction={this.props.saveAction}
|
||||
deleteWarning={false}
|
||||
deleteAction={(this.props.preset.id !== -1 && !this.props.preset.system) ? this.props.deleteAction : undefined}>
|
||||
{!this.isCustomPreset() ?
|
||||
<div className="row preset-name">
|
||||
<label className="col-sm-2 control-label">Name</label>
|
||||
<label className="col-sm-2 control-label">{_("Name")}</label>
|
||||
<div className="col-sm-10">
|
||||
<input type="text" className="form-control" ref={(domNode) => { this.nameInput = domNode; }} value={this.state.name} onChange={this.handleChange('name')} />
|
||||
</div>
|
||||
|
|
|
@ -6,6 +6,7 @@ import ErrorMessage from './ErrorMessage';
|
|||
import PropTypes from 'prop-types';
|
||||
import Storage from '../classes/Storage';
|
||||
import $ from 'jquery';
|
||||
import { _, interpolate } from '../classes/gettext';
|
||||
|
||||
|
||||
class EditTaskForm extends React.Component {
|
||||
|
@ -85,7 +86,7 @@ class EditTaskForm extends React.Component {
|
|||
|
||||
loadProcessingNodes(){
|
||||
const failed = () => {
|
||||
this.setState({error: "Could not load list of processing nodes. Are you connected to the internet?"});
|
||||
this.setState({error: _("Could not load list of processing nodes. Are you connected to the internet?")});
|
||||
}
|
||||
|
||||
this.nodesRequest =
|
||||
|
@ -93,11 +94,8 @@ class EditTaskForm extends React.Component {
|
|||
if (Array.isArray(json)){
|
||||
// No nodes with options?
|
||||
const noProcessingNodesError = (nodes) => {
|
||||
var extra = nodes ? "We tried to reach:<ul>" + nodes.map(n => Utils.html`<li><a href="${n.url}">${n.label}</a></li>`).join("") + "</ul>" : "";
|
||||
this.setState({error: `There are no usable processing nodes. ${extra}Make sure that at least one processing node is reachable and
|
||||
that you have granted the current user sufficient permissions to view
|
||||
the processing node (by going to Administration -- Processing Nodes -- Select Node -- Object Permissions -- Add User/Group and check CAN VIEW PROCESSING NODE).
|
||||
If you are bringing a node back online, it will take about 30 seconds for WebODM to recognize it.`});
|
||||
var extra = nodes ? _("We tried to reach:") + "<ul>" + nodes.map(n => Utils.html`<li><a href="${n.url}">${n.label}</a></li>`).join("") + "</ul>" : "";
|
||||
this.setState({error: _("There are no usable processing nodes.") + extra + _("Make sure that at least one processing node is reachable and that you have granted the current user sufficient permissions to view the processing node (by going to Administration -- Processing Nodes -- Select Node -- Object Permissions -- Add User/Group and check CAN VIEW PROCESSING NODE). If you are bringing a node back online, it will take about 30 seconds for WebODM to recognize it.")});
|
||||
};
|
||||
|
||||
if (json.length === 0){
|
||||
|
@ -215,7 +213,7 @@ class EditTaskForm extends React.Component {
|
|||
|
||||
loadPresets(){
|
||||
const failed = () => {
|
||||
this.setState({error: "Could not load list of presets. Are you connected to the internet?"});
|
||||
this.setState({error: _("Could not load list of presets. Are you connected to the internet?")});
|
||||
}
|
||||
|
||||
this.presetsRequest =
|
||||
|
@ -224,13 +222,14 @@ class EditTaskForm extends React.Component {
|
|||
// Add custom preset
|
||||
const customPreset = {
|
||||
id: -1,
|
||||
name: "(Custom)",
|
||||
name: "(" + _("Custom") + ")",
|
||||
options: [],
|
||||
system: true
|
||||
};
|
||||
presets.unshift(customPreset);
|
||||
|
||||
// Choose preset
|
||||
_("Default"); // Add translation
|
||||
let selectedPreset = presets[0],
|
||||
defaultPreset = presets.find(p => p.name === "Default"); // Do not translate Default
|
||||
if (defaultPreset) selectedPreset = defaultPreset;
|
||||
|
@ -351,7 +350,7 @@ class EditTaskForm extends React.Component {
|
|||
getAvailableOptionsOnlyText(options, availableOptions){
|
||||
const opts = this.getAvailableOptionsOnly(options, availableOptions);
|
||||
let res = opts.map(opt => `${opt.name}:${opt.value}`).join(", ");
|
||||
if (!res) res = "Default";
|
||||
if (!res) res = _("Default");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -382,7 +381,7 @@ class EditTaskForm extends React.Component {
|
|||
if (!customPreset){
|
||||
customPreset = {
|
||||
id: -1,
|
||||
name: "(Custom)",
|
||||
name: "(" + _("Custom") + ")",
|
||||
options: [],
|
||||
system: true
|
||||
};
|
||||
|
@ -435,7 +434,7 @@ class EditTaskForm extends React.Component {
|
|||
this.setState({presetActionPerforming: true});
|
||||
|
||||
const isCustom = selectedPreset.id === -1,
|
||||
name = isCustom ? "My Preset" : "Copy of " + selectedPreset.name;
|
||||
name = isCustom ? _("My Preset") : interpolate(_("Copy of %(preset)s"), {preset: selectedPreset.name});
|
||||
|
||||
$.ajax({
|
||||
url: `/api/presets/`,
|
||||
|
@ -458,7 +457,7 @@ class EditTaskForm extends React.Component {
|
|||
this.setState({presets, selectedPreset: preset});
|
||||
this.handleEditPreset();
|
||||
}).fail(() => {
|
||||
this.setState({presetError: "Could not duplicate the preset. Please try to refresh the page."});
|
||||
this.setState({presetError: _("Could not duplicate the preset. Please try to refresh the page.")});
|
||||
}).always(() => {
|
||||
this.setState({presetActionPerforming: false});
|
||||
});
|
||||
|
@ -467,11 +466,11 @@ class EditTaskForm extends React.Component {
|
|||
handleDeletePreset(){
|
||||
const { selectedPreset, presets } = this.state;
|
||||
if (selectedPreset.system){
|
||||
this.setState({presetError: "System presets can only be removed by a staff member from the Administration panel."});
|
||||
this.setState({presetError: _("System presets can only be removed by a staff member from the Administration panel.")});
|
||||
return;
|
||||
}
|
||||
|
||||
if (window.confirm(`Are you sure you want to delete "${selectedPreset.name}"?`)){
|
||||
if (window.confirm(interpolate(_('Are you sure you want to delete "%(preset)s"?'), { preset: selectedPreset.name}))){
|
||||
this.setState({presetActionPerforming: true});
|
||||
|
||||
return $.ajax({
|
||||
|
@ -484,7 +483,7 @@ class EditTaskForm extends React.Component {
|
|||
// Select first by default
|
||||
this.setState({presets, selectedPreset: presets[0], editingPreset: false});
|
||||
}).fail(() => {
|
||||
this.setState({presetError: "Could not delete the preset. Please try to refresh the page."});
|
||||
this.setState({presetError: _("Could not delete the preset. Please try to refresh the page.")});
|
||||
}).always(() => {
|
||||
this.setState({presetActionPerforming: false});
|
||||
});
|
||||
|
@ -499,7 +498,7 @@ class EditTaskForm extends React.Component {
|
|||
<div className="alert alert-warning">
|
||||
<div dangerouslySetInnerHTML={{__html:this.state.error}}></div>
|
||||
<button className="btn btn-sm btn-primary" onClick={this.retryLoad}>
|
||||
<i className="fa fa-rotate-left"></i> Retry
|
||||
<i className="fa fa-rotate-left"></i> {_("Retry")}
|
||||
</button>
|
||||
</div>
|
||||
</div>);
|
||||
|
@ -515,35 +514,35 @@ class EditTaskForm extends React.Component {
|
|||
value={this.state.selectedPreset.id}
|
||||
onChange={this.handleSelectPreset}>
|
||||
{this.state.presets.map(preset =>
|
||||
<option value={preset.id} key={preset.id} className={preset.system ? "system-preset" : ""}>{preset.name}</option>
|
||||
<option value={preset.id} key={preset.id} className={preset.system ? "system-preset" : ""}>{preset.name === "Default" ? _(preset.name) : preset.name}</option>
|
||||
)}
|
||||
</select>
|
||||
|
||||
{!this.state.presetActionPerforming ?
|
||||
<div className="btn-group presets-dropdown">
|
||||
<button type="button" className="btn btn-default" title="Edit Task Options" onClick={this.handleEditPreset}>
|
||||
<i className="fa fa-sliders-h"></i> Edit
|
||||
<button type="button" className="btn btn-default" title={_("Edit Task Options")} onClick={this.handleEditPreset}>
|
||||
<i className="fa fa-sliders-h"></i> {_("Edit")}
|
||||
</button>
|
||||
<button type="button" className="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span className="caret"></span>
|
||||
</button>
|
||||
<ul className="dropdown-menu">
|
||||
<li>
|
||||
<a href="javascript:void(0);" onClick={this.handleEditPreset}><i className="fa fa-sliders-h"></i> Edit</a>
|
||||
<a href="javascript:void(0);" onClick={this.handleEditPreset}><i className="fa fa-sliders-h"></i> {_("Edit")}</a>
|
||||
</li>
|
||||
<li className="divider"></li>
|
||||
|
||||
{this.state.selectedPreset.id !== -1 ?
|
||||
<li>
|
||||
<a href="javascript:void(0);" onClick={this.handleDuplicateSavePreset}><i className="fa fa-copy"></i> Duplicate</a>
|
||||
<a href="javascript:void(0);" onClick={this.handleDuplicateSavePreset}><i className="fa fa-copy"></i> {_("Duplicate")}</a>
|
||||
</li>
|
||||
:
|
||||
<li>
|
||||
<a href="javascript:void(0);" onClick={this.handleDuplicateSavePreset}><i className="fa fa-save"></i> Save</a>
|
||||
<a href="javascript:void(0);" onClick={this.handleDuplicateSavePreset}><i className="fa fa-save"></i> {_("Save")}</a>
|
||||
</li>
|
||||
}
|
||||
<li className={this.state.selectedPreset.system ? "disabled" : ""}>
|
||||
<a href="javascript:void(0);" onClick={this.handleDeletePreset}><i className="fa fa-trash"></i> Delete</a>
|
||||
<a href="javascript:void(0);" onClick={this.handleDeletePreset}><i className="fa fa-trash"></i> {_("Delete")}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -554,7 +553,7 @@ class EditTaskForm extends React.Component {
|
|||
taskOptions = (
|
||||
<div>
|
||||
<div className="form-group">
|
||||
<label className="col-sm-2 control-label">Processing Node</label>
|
||||
<label className="col-sm-2 control-label">{_("Processing Node")}</label>
|
||||
<div className="col-sm-10">
|
||||
<select className="form-control" value={this.state.selectedNode.key} onChange={this.handleSelectNode}>
|
||||
{this.state.processingNodes.map(node =>
|
||||
|
@ -564,7 +563,7 @@ class EditTaskForm extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
<div className="form-group form-inline">
|
||||
<label className="col-sm-2 control-label">Options</label>
|
||||
<label className="col-sm-2 control-label">{_("Options")}</label>
|
||||
<div className="col-sm-10">
|
||||
{!this.props.inReview ? optionsSelector :
|
||||
<div className="review-options">
|
||||
|
@ -588,14 +587,14 @@ class EditTaskForm extends React.Component {
|
|||
);
|
||||
}else{
|
||||
taskOptions = (<div className="form-group">
|
||||
<div className="col-sm-offset-2 col-sm-10">Loading processing nodes and presets... <i className="fa fa-sync fa-spin fa-fw"></i></div>
|
||||
<div className="col-sm-offset-2 col-sm-10">{_("Loading processing nodes and presets...")} <i className="fa fa-sync fa-spin fa-fw"></i></div>
|
||||
</div>);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="edit-task-form">
|
||||
<div className="form-group">
|
||||
<label className="col-sm-2 control-label">Name</label>
|
||||
<label className="col-sm-2 control-label">{_("Name")}</label>
|
||||
<div className="col-sm-10">
|
||||
{this.state.loadingTaskName ?
|
||||
<i className="fa fa-circle-notch fa-spin fa-fw name-loading"></i>
|
||||
|
|
|
@ -25,7 +25,7 @@ class ErrorMessage extends React.Component {
|
|||
if (parent.state[prop]){
|
||||
return (
|
||||
<div className={"alert alert-warning alert-dismissible " + (this.props.className ? this.props.className : "")}>
|
||||
<button type="button" className="close" aria-label="Close" onClick={this.close}><span aria-hidden="true">×</span></button>
|
||||
<button type="button" className="close" title={_("Close")} onClick={this.close}><span aria-hidden="true">×</span></button>
|
||||
{parent.state[prop]}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import '../css/Histogram.scss';
|
||||
import d3 from 'd3';
|
||||
import { _ } from '../classes/gettext';
|
||||
|
||||
export default class Histogram extends React.Component {
|
||||
static defaultProps = {
|
||||
|
@ -289,8 +290,8 @@ export default class Histogram extends React.Component {
|
|||
return (<div className={"histogram " + (this.props.loading ? "disabled" : "")}>
|
||||
<div ref={(domNode) => { this.hgContainer = domNode; }}>
|
||||
</div>
|
||||
<label>Min:</label> <input onChange={this.handleChangeMin} type="number" className="form-control min-max" size={5} value={this.state.min} />
|
||||
<label>Max:</label> <input onChange={this.handleChangeMax} type="number" className="form-control min-max" size={5} value={this.state.max} />
|
||||
<label>{_("Min:")}</label> <input onChange={this.handleChangeMin} type="number" className="form-control min-max" size={5} value={this.state.min} />
|
||||
<label>{_("Max:")}</label> <input onChange={this.handleChangeMax} type="number" className="form-control min-max" size={5} value={this.state.max} />
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import AssetDownloads from '../classes/AssetDownloads';
|
||||
import '../css/ImagePopup.scss';
|
||||
import { _ } from '../classes/gettext';
|
||||
|
||||
class ImagePopup extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -43,7 +44,7 @@ class ImagePopup extends React.Component {
|
|||
}
|
||||
|
||||
imageOnError = () => {
|
||||
this.setState({error: "Image is missing", loading: false});
|
||||
this.setState({error: _("Image is missing"), loading: false});
|
||||
}
|
||||
|
||||
imageOnLoad = () => {
|
||||
|
@ -82,7 +83,7 @@ class ImagePopup extends React.Component {
|
|||
<a onClick={this.onImgClick} href="javascript:void(0);" title={feature.properties.filename}><img style={{borderRadius: "4px"}} src={imageUrl} onLoad={this.imageOnLoad} onError={this.imageOnError} /></a>
|
||||
</div>,
|
||||
<div key="download-image">
|
||||
<a href={downloadImageLink}><i className="fa fa-image"></i> Download Image</a>
|
||||
<a href={downloadImageLink}><i className="fa fa-image"></i> {_("Download Image")}</a>
|
||||
</div>
|
||||
]}
|
||||
<div>
|
||||
|
|
|
@ -5,6 +5,8 @@ import Dropzone from '../vendor/dropzone';
|
|||
import csrf from '../django/csrf';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import UploadProgressBar from './UploadProgressBar';
|
||||
import { _, interpolate } from '../classes/gettext';
|
||||
import Trans from './Trans';
|
||||
|
||||
class ImportTaskPanel extends React.Component {
|
||||
static defaultProps = {
|
||||
|
@ -58,7 +60,7 @@ class ImportTaskPanel extends React.Component {
|
|||
});
|
||||
|
||||
this.dz.on("error", (file) => {
|
||||
if (this.state.uploading) this.setState({error: "Cannot upload file. Check your internet connection and try again."});
|
||||
if (this.state.uploading) this.setState({error: _("Cannot upload file. Check your internet connection and try again.")});
|
||||
})
|
||||
.on("sending", () => {
|
||||
this.setState({typeUrl: false, uploading: true, totalCount: 1});
|
||||
|
@ -86,10 +88,10 @@ class ImportTaskPanel extends React.Component {
|
|||
if (!response.id) throw new Error(`Expected id field, but none given (${response})`);
|
||||
this.props.onImported();
|
||||
}catch(e){
|
||||
this.setState({error: `Invalid response from server: ${e.message}`});
|
||||
this.setState({error: interpolate(_('Invalid response from server: %(error)s'), { error: e.message})});
|
||||
}
|
||||
}else if (this.state.uploading){
|
||||
this.setState({uploading: false, error: "An error occured while uploading the file. Please try again."});
|
||||
this.setState({uploading: false, error: _("An error occured while uploading the file. Please try again.")});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -133,11 +135,11 @@ class ImportTaskPanel extends React.Component {
|
|||
if (json.id){
|
||||
this.props.onImported();
|
||||
}else{
|
||||
this.setState({error: json.error || `Cannot import from URL, server responded: ${JSON.stringify(json)}`});
|
||||
this.setState({error: json.error || interpolate(_("Invalid JSON response: %(error)s"), {error: JSON.stringify(json)})});
|
||||
}
|
||||
})
|
||||
.fail(() => {
|
||||
this.setState({importingFromUrl: false, error: "Cannot import from URL. Check your internet connection."});
|
||||
this.setState({importingFromUrl: false, error: _("Cannot import from URL. Check your internet connection.")});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -153,16 +155,16 @@ class ImportTaskPanel extends React.Component {
|
|||
<div className="form-horizontal">
|
||||
<ErrorMessage bind={[this, 'error']} />
|
||||
|
||||
<button type="button" className="close theme-color-primary" aria-label="Close" onClick={this.cancel}><span aria-hidden="true">×</span></button>
|
||||
<h4>Import Existing Assets</h4>
|
||||
<p>You can import .zip files that have been exported from existing tasks via Download Assets <i className="glyphicon glyphicon-arrow-right"></i> All Assets.</p>
|
||||
<button type="button" className="close theme-color-primary" title="Close" onClick={this.cancel}><span aria-hidden="true">×</span></button>
|
||||
<h4>{_("Import Existing Assets")}</h4>
|
||||
<p><Trans params={{arrow: '<i class="glyphicon glyphicon-arrow-right"></i>'}}>{_("You can import .zip files that have been exported from existing tasks via Download Assets %(arrow)s All Assets.")}</Trans></p>
|
||||
|
||||
<button disabled={this.state.uploading}
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
ref={this.setRef("uploadButton")}>
|
||||
<i className="glyphicon glyphicon-upload"></i>
|
||||
Upload a File
|
||||
{_("Upload a File")}
|
||||
</button>
|
||||
<button disabled={this.state.uploading}
|
||||
type="button"
|
||||
|
@ -170,7 +172,7 @@ class ImportTaskPanel extends React.Component {
|
|||
onClick={this.handleImportFromUrl}
|
||||
ref={this.setRef("importFromUrlButton")}>
|
||||
<i className="glyphicon glyphicon-cloud-download"></i>
|
||||
Import From URL
|
||||
{_("Import From URL")}
|
||||
</button>
|
||||
|
||||
{this.state.typeUrl ?
|
||||
|
@ -179,7 +181,7 @@ class ImportTaskPanel extends React.Component {
|
|||
<input disabled={this.state.importingFromUrl} onChange={this.handleChangeImportUrl} size="45" type="text" className="form-control" placeholder="http://" value={this.state.importUrl} />
|
||||
<button onClick={this.handleConfirmImportUrl}
|
||||
disabled={this.state.importUrl.length < 4 || this.state.importingFromUrl}
|
||||
className="btn-import btn btn-primary"><i className="glyphicon glyphicon-cloud-download"></i> Import</button>
|
||||
className="btn-import btn btn-primary"><i className="glyphicon glyphicon-cloud-download"></i> {_("Import")}</button>
|
||||
</div>
|
||||
</div> : ""}
|
||||
|
||||
|
@ -189,7 +191,7 @@ class ImportTaskPanel extends React.Component {
|
|||
className="btn btn-danger btn-sm"
|
||||
onClick={this.cancelUpload}>
|
||||
<i className="glyphicon glyphicon-remove-circle"></i>
|
||||
Cancel Upload
|
||||
{_("Cancel Upload")}
|
||||
</button>
|
||||
</div> : ""}
|
||||
</div>
|
||||
|
|
|
@ -7,6 +7,7 @@ import Utils from '../classes/Utils';
|
|||
import Workers from '../classes/Workers';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import $ from 'jquery';
|
||||
import { _, interpolate } from '../classes/gettext';
|
||||
|
||||
export default class LayersControlLayer extends React.Component {
|
||||
static defaultProps = {
|
||||
|
@ -245,7 +246,7 @@ export default class LayersControlLayer extends React.Component {
|
|||
}else if (result.error){
|
||||
this.setState({exportLoading: false, error: result.error});
|
||||
}else{
|
||||
this.setState({exportLoading: false, error: "Invalid response: " + result});
|
||||
this.setState({exportLoading: false, error: interpolate(_("Invalid JSON response: %(error)s"), {error: JSON.stringify(result)})});
|
||||
}
|
||||
}).fail(error => {
|
||||
this.setState({exportLoading: false, error: JSON.stringify(error)});
|
||||
|
@ -283,7 +284,7 @@ export default class LayersControlLayer extends React.Component {
|
|||
|
||||
{formula !== "" && algorithms ?
|
||||
<div className="row form-group form-inline">
|
||||
<label className="col-sm-3 control-label">Algorithm:</label>
|
||||
<label className="col-sm-3 control-label">{_("Algorithm:")}</label>
|
||||
<div className="col-sm-9 ">
|
||||
{histogramLoading ?
|
||||
<i className="fa fa-circle-notch fa-spin fa-fw" /> :
|
||||
|
@ -295,7 +296,7 @@ export default class LayersControlLayer extends React.Component {
|
|||
|
||||
{bands !== "" && algo ?
|
||||
<div className="row form-group form-inline">
|
||||
<label className="col-sm-3 control-label">Filter:</label>
|
||||
<label className="col-sm-3 control-label">{_("Filter:")}</label>
|
||||
<div className="col-sm-9 ">
|
||||
{histogramLoading ?
|
||||
<i className="fa fa-circle-notch fa-spin fa-fw" /> :
|
||||
|
@ -307,7 +308,7 @@ export default class LayersControlLayer extends React.Component {
|
|||
|
||||
{colorMap && color_maps.length ?
|
||||
<div className="row form-group form-inline">
|
||||
<label className="col-sm-3 control-label">Color:</label>
|
||||
<label className="col-sm-3 control-label">{_("Color:")}</label>
|
||||
<div className="col-sm-9 ">
|
||||
{histogramLoading ?
|
||||
<i className="fa fa-circle-notch fa-spin fa-fw" /> :
|
||||
|
@ -319,18 +320,18 @@ export default class LayersControlLayer extends React.Component {
|
|||
|
||||
{hillshade !== "" ?
|
||||
<div className="row form-group form-inline">
|
||||
<label className="col-sm-3 control-label">Shading:</label>
|
||||
<label className="col-sm-3 control-label">{_("Shading:")}</label>
|
||||
<div className="col-sm-9 ">
|
||||
<select className="form-control" value={hillshade} onChange={this.handleSelectHillshade}>
|
||||
<option value="0">None</option>
|
||||
<option value="6">Normal</option>
|
||||
<option value="18">Extruded</option>
|
||||
<option value="0">{_("None")}</option>
|
||||
<option value="6">{_("Normal")}</option>
|
||||
<option value="18">{_("Extruded")}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div> : ""}
|
||||
|
||||
<div className="row form-group form-inline">
|
||||
<label className="col-sm-3 control-label">Export: </label>
|
||||
<label className="col-sm-3 control-label">{_("Export:")} </label>
|
||||
<div className="col-sm-9">
|
||||
<button onClick={this.handleExport} disabled={exportLoading} type="button" className="btn btn-sm btn-default">
|
||||
{exportLoading ? <i className="fa fa-spin fa-circle-notch"/> : <i className="far fa-image fa-fw" />} GeoTIFF
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import '../css/LayersControlPanel.scss';
|
||||
import LayersControlLayer from './LayersControlLayer';
|
||||
import { _ } from '../classes/gettext';
|
||||
|
||||
export default class LayersControlPanel extends React.Component {
|
||||
static defaultProps = {
|
||||
|
@ -22,7 +23,7 @@ export default class LayersControlPanel extends React.Component {
|
|||
render(){
|
||||
let content = "";
|
||||
|
||||
if (!this.props.layers.length) content = (<span><i className="loading fa fa-circle-notch fa-spin"></i> Loading...</span>);
|
||||
if (!this.props.layers.length) content = (<span><i className="loading fa fa-circle-notch fa-spin"></i> {_("Loading...")}</span>);
|
||||
else{
|
||||
content = (<div>
|
||||
{this.props.overlays.length ?
|
||||
|
@ -40,7 +41,7 @@ export default class LayersControlPanel extends React.Component {
|
|||
|
||||
return (<div className="layers-control-panel">
|
||||
<span className="close-button" onClick={this.props.onClose}/>
|
||||
<div className="title">Layers</div>
|
||||
<div className="title">{_("Layers")}</div>
|
||||
<hr/>
|
||||
{content}
|
||||
</div>);
|
||||
|
|
|
@ -26,6 +26,7 @@ import update from 'immutability-helper';
|
|||
import Utils from '../classes/Utils';
|
||||
import '../vendor/leaflet/Leaflet.Ajax';
|
||||
import '../vendor/leaflet/Leaflet.Awesome-markers';
|
||||
import { _ } from '../classes/gettext';
|
||||
|
||||
class Map extends React.Component {
|
||||
static defaultProps = {
|
||||
|
@ -78,13 +79,13 @@ class Map extends React.Component {
|
|||
typeToHuman = (type) => {
|
||||
switch(type){
|
||||
case "orthophoto":
|
||||
return "Orthophoto";
|
||||
return _("Orthophoto");
|
||||
case "plant":
|
||||
return "Plant Health";
|
||||
return _("Plant Health");
|
||||
case "dsm":
|
||||
return "DSM";
|
||||
return _("DSM");
|
||||
case "dtm":
|
||||
return "DTM";
|
||||
return _("DTM");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@ -255,7 +256,7 @@ class Map extends React.Component {
|
|||
}
|
||||
}
|
||||
});
|
||||
shotsLayer[Symbol.for("meta")] = {name: name + " (Cameras)", icon: "fa fa-camera fa-fw"};
|
||||
shotsLayer[Symbol.for("meta")] = {name: name + " " + _("(Cameras)"), icon: "fa fa-camera fa-fw"};
|
||||
|
||||
this.setState(update(this.state, {
|
||||
overlays: {$push: [shotsLayer]}
|
||||
|
@ -327,13 +328,12 @@ class Map extends React.Component {
|
|||
|
||||
const customLayer = L.layerGroup();
|
||||
customLayer.on("add", a => {
|
||||
let url = window.prompt(`Enter a tile URL template. Valid tokens are:
|
||||
{z}, {x}, {y} for Z/X/Y tile scheme
|
||||
{-y} for flipped TMS-style Y coordinates
|
||||
|
||||
Example:
|
||||
https://a.tile.openstreetmap.org/{z}/{x}/{y}.png
|
||||
`, 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png');
|
||||
let url = window.prompt([_('Enter a tile URL template. Valid coordinates are:'),
|
||||
_('{z}, {x}, {y} for Z/X/Y tile scheme'),
|
||||
_('{-y} for flipped TMS-style Y coordinates'),
|
||||
'',
|
||||
_('Example:'),
|
||||
'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'].join("\n"), 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png');
|
||||
|
||||
if (url){
|
||||
customLayer.clearLayers();
|
||||
|
@ -346,8 +346,8 @@ https://a.tile.openstreetmap.org/{z}/{x}/{y}.png
|
|||
l.bringToBack();
|
||||
}
|
||||
});
|
||||
this.basemaps["Custom"] = customLayer;
|
||||
this.basemaps["None"] = L.layerGroup();
|
||||
this.basemaps[_("Custom")] = customLayer;
|
||||
this.basemaps[_("None")] = L.layerGroup();
|
||||
}
|
||||
|
||||
this.layersControl = new LayersControl({
|
||||
|
@ -398,7 +398,7 @@ https://a.tile.openstreetmap.org/{z}/{x}/{y}.png
|
|||
this.container = Leaflet.DomUtil.create('div', 'leaflet-control-add-overlay leaflet-bar leaflet-control');
|
||||
Leaflet.DomEvent.disableClickPropagation(this.container);
|
||||
const btn = Leaflet.DomUtil.create('a', 'leaflet-control-add-overlay-button');
|
||||
btn.setAttribute("title", "Add a temporary GeoJSON (.json) or ShapeFile (.zip) overlay");
|
||||
btn.setAttribute("title", _("Add a temporary GeoJSON (.json) or ShapeFile (.zip) overlay"));
|
||||
|
||||
this.container.append(btn);
|
||||
addDnDZone(btn, {url: "/", clickable: true});
|
||||
|
@ -447,7 +447,7 @@ https://a.tile.openstreetmap.org/{z}/{x}/{y}.png
|
|||
$assetLinks.append($(linksHtml));
|
||||
})
|
||||
.fail(() => {
|
||||
$assetLinks.append($("<li>Error: cannot load assets list. </li>"));
|
||||
$assetLinks.append($("<li>" + _("Error: cannot load assets list.") + "</li>"));
|
||||
})
|
||||
.always(() => {
|
||||
$assetLinks.removeClass('loading');
|
||||
|
|
|
@ -540,7 +540,7 @@ class ProjectListItem extends React.Component {
|
|||
|
||||
{this.state.upload.error !== "" ?
|
||||
<div className="alert alert-warning alert-dismissible">
|
||||
<button type="button" className="close" aria-label={_("Close")} onClick={this.closeUploadError}><span aria-hidden="true">×</span></button>
|
||||
<button type="button" className="close" title={_("Close")} onClick={this.closeUploadError}><span aria-hidden="true">×</span></button>
|
||||
{this.state.upload.error}
|
||||
</div>
|
||||
: ""}
|
||||
|
|
|
@ -222,7 +222,7 @@ class TaskListItem extends React.Component {
|
|||
|
||||
optionsToList(options){
|
||||
if (!Array.isArray(options)) return "";
|
||||
else if (options.length === 0) return _("Default");
|
||||
else if (options.length === 0) return "Default";
|
||||
else {
|
||||
return options.map(opt => `${opt.name}: ${opt.value}`).join(", ");
|
||||
}
|
||||
|
@ -531,9 +531,7 @@ class TaskListItem extends React.Component {
|
|||
|
||||
{showExitedWithCodeOneHints ?
|
||||
<div className="task-warning"><i className="fa fa-info-circle"></i> <div className="inline">
|
||||
"Process exited with code 1" means that part of the processing failed. Sometimes it's a problem with the dataset, sometimes it can be solved by tweaking the Task Options and sometimes it might be a bug!
|
||||
If you need help, upload your images somewhere like <a href="https://www.dronedb.app/" target="_blank">DroneDB</a> or <a href="https://drive.google.com/drive/u/0/" target="_blank">Google Drive</a> and <a href="http://community.opendronemap.org/c/webodm" target="_blank">open a topic</a> on our community forum, making
|
||||
sure to include a <a href="javascript:void(0);" onClick={this.setView("console")}>copy of your task's output</a>. Our awesome contributors will try to help you! <i className="far fa-smile"></i>
|
||||
<Trans params={{link1: `<a href="https://www.dronedb.app/" target="_blank">DroneDB</a>`, link2: `<a href="https://drive.google.com/drive/u/0/" target="_blank">Google Drive</a>`, open_a_topic: `<a href="http://community.opendronemap.org/c/webodm" target="_blank">${_("open a topic")}</a>`, }}>{_("\"Process exited with code 1\" means that part of the processing failed. Sometimes it's a problem with the dataset, sometimes it can be solved by tweaking the Task Options and sometimes it might be a bug! If you need help, upload your images somewhere like %(link1)s or %(link2)s and %(open_a_topic)s on our community forum, making sure to include a copy of your task's output. Our awesome contributors will try to help you!")}</Trans> <i className="far fa-smile"></i>
|
||||
</div>
|
||||
</div>
|
||||
: ""}
|
||||
|
@ -579,12 +577,12 @@ class TaskListItem extends React.Component {
|
|||
if (task.last_error){
|
||||
statusLabel = getStatusLabel(task.last_error, 'error');
|
||||
}else if (!task.processing_node && !imported){
|
||||
statusLabel = getStatusLabel("Set a processing node");
|
||||
statusLabel = getStatusLabel(_("Set a processing node"));
|
||||
statusIcon = "fa fa-hourglass-3";
|
||||
showEditLink = true;
|
||||
}else if (task.partial && !task.pending_action){
|
||||
statusIcon = "fa fa-hourglass-3";
|
||||
statusLabel = getStatusLabel("Waiting for image upload...");
|
||||
statusLabel = getStatusLabel(_("Waiting for image upload..."));
|
||||
}else{
|
||||
let progress = 100;
|
||||
let type = 'done';
|
||||
|
|
|
@ -15,7 +15,8 @@ class Trans extends React.Component {
|
|||
if (!this.props.children) return (<span/>);
|
||||
|
||||
let content = "";
|
||||
|
||||
console.log(this.props.children);
|
||||
console.log(interpolate(this.props.children, this.props.params));
|
||||
if (typeof this.props.children === "string"){
|
||||
content = (<span dangerouslySetInnerHTML={{__html: interpolate(this.props.children, this.props.params)}}></span>);
|
||||
}else{
|
||||
|
@ -31,7 +32,7 @@ class Trans extends React.Component {
|
|||
i++;
|
||||
});
|
||||
}
|
||||
|
||||
console.log(content);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
<ul>
|
||||
<li>{% trans 'You need at least 5 images' %}</li>
|
||||
<li>{% trans 'Images must overlap by 65% or more' %}</li>
|
||||
<li>{% trans 'For great 3D, images must overlap by 83%' %}</li>
|
||||
<li>{% trans 'A <a href="https://github.com/OpenDroneMap/OpenDroneMap/wiki/Running-OpenDroneMap#running-odm-with-ground-control" target="_blank">GCP file</a> is optional, but can increase georeferencing accuracy' %}</li>
|
||||
<li>{% trans 'For great 3D, images must overlap by 83%' %}</li>
|
||||
<li>{% blocktrans with link_start='<a href="https://github.com/OpenDroneMap/OpenDroneMap/wiki/Running-OpenDroneMap#running-odm-with-ground-control" target="_blank">' link_end='</a>' %}A {{link_start}}GCP File{{link_end}} is optional, but can increase georeferencing accuracy{% endblocktrans %}</li>
|
||||
</ul>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
|
Ładowanie…
Reference in New Issue