allow translation of Content and ToolTips

pull/687/head
gabrielburnworth 2018-02-28 12:12:11 -08:00
parent 3d3e16d61c
commit f2a3f826c0
13 changed files with 315 additions and 305 deletions

View File

@ -1,170 +1,175 @@
var HelperNamespace = (function () {
/**
* @desc Build a list of all the files that are children of the root isDirectory
* @param {string} dir The rot isDirectory
* @param {list} filelist The list of the directories/files already detected
* @param {string} ext The extension to filter for the files
*/
function walkSync(dir, filelist, ext) {
var path = path || require('path');
var fs = fs || require('fs'),
files = fs.readdirSync(dir);
filelist = filelist || [];
files.forEach(function (file) {
if (fs.statSync(path.join(dir, file)).isDirectory()) {
filelist = walkSync(path.join(dir, file), filelist, ext);
}
else {
if (file.indexOf(ext) > 0)
filelist.push(path.join(dir, file));
}
});
return filelist;
};
/**
* @desc Build a list of all the files that are children of the root isDirectory
* @param {string} dir The rot isDirectory
* @param {list} filelist The list of the directories/files already detected
* @param {string} ext The extension to filter for the files
*/
function walkSync(dir, filelist, ext) {
var path = path || require('path');
var fs = fs || require('fs'),
files = fs.readdirSync(dir);
filelist = filelist || [];
files.forEach(function (file) {
if (fs.statSync(path.join(dir, file)).isDirectory()) {
filelist = walkSync(path.join(dir, file), filelist, ext);
}
else {
if (file.indexOf(ext) > 0)
filelist.push(path.join(dir, file));
}
});
return filelist;
};
/**
* @desc search in the file in parameter to detect the tags
*/
function searchInFile(path) {
/* some tags could be missed in this regex
We detect all the tags in the code
regex is matching:
'.t("")' or '{t("")' or ' t("")' or '(t("")' or
'.t(``)' or '{t(``)' or ' t(``)' or '(t(``)'*/
var REGEX = /[.{(\s]t\(["`]([\w\s{}().,:'\-=\\?!]*)["`].*\)/g;
/**
* @desc search in the file in parameter to detect the tags
*/
function searchInFile(path, regex) {
var fs = fs || require('fs')
// load the file
var fileContent = fs.readFileSync(path, 'utf8');
var strArray = [];
// match all the groups
var match = regex.exec(fileContent);
while (match != null) {
strArray.push(match[1].replace(/\s+/g, " "))
match = regex.exec(fileContent);
}
return strArray;
}
// '.t("")' or '{t("")' or ' t("")' or '(t("")' or
// '.t(``)' or '{t(``)' or ' t(``)' or '(t(``)'
var T_REGEX = /[.{(\s]t\(["`]([\w\s{}().,:'\-=\\?!]*)["`].*\)/g;
// '``'
var C_REGEX = /[`]([\w\s{}().,:'\-=\\?!]*)[`].*/g;
/**
* Get all the tags in the files with extension .ts of the current project
*/
function getAllTags() {
const srcPath = __dirname + '/../../../';
var listFilteredFiles = walkSync(srcPath, [], '.ts');
var allTags = listFilteredFiles.map(function (x) {
return searchInFile(x, T_REGEX)
});
var constantsTags = searchInFile(srcPath + 'webpack/constants.ts', C_REGEX);
//flatten list of list in a simple list
var flatAllTags = [].concat.apply([], allTags);
var flatConstantsTags = [].concat.apply([], constantsTags);
var flattenedTags = [].concat.apply([], [flatAllTags, flatConstantsTags]);
//distinct
var uniq = Array.from(new Set(flattenedTags));
var sorted = uniq.sort(function (a, b) { return a.localeCompare(b); });
return sorted;
}
/**
* For debugging
*/
function logAllTags() {
console.dir(getAllTags());
}
/**
* Create the translation file or update it with new tags
* The tags are in the following order:
* 1. New tags in English that need to be translated (ASC)
* 2. Tags already translated, and kept because it match an existing tag in src (ASC)
* 3. Tags already in the file before but not found at the moment in the src (ASC)
* @param {string} lang The short name of the language. for the language in parameter
*/
function createOrUpdateTranslationFile(lang) {
lang = lang || 'en';
//check current file entry
const langFilePath = __dirname + '/' + lang + '.js';
var fs = fs || require('fs')
try {
var columnsResult = HelperNamespace.getAllTags();
var jsonCurrentTagData = {};
columnsResult.forEach(function (column) {
jsonCurrentTagData[column] = column;
});
var ordered = {};
var fileContent;
try {
//check the file can be opened
var stats = fs.statSync(langFilePath);
var fs = fs || require('fs')
// load the file
var fileContent = fs.readFileSync(path, 'utf8');
var strArray = [];
//match all the groups
var match = REGEX.exec(fileContent);
while (match != null) {
strArray.push(match[1].replace(/\s+/g, " "))
match = REGEX.exec(fileContent);
var fileContent = fs.readFileSync(langFilePath, 'utf8');
console.log("Current file content: ");
console.log(fileContent);
}
catch (e) { // do this
console.log("we will create the file: " + langFilePath);
//If there is no current file, we will create it
};
try {
if (fileContent != undefined) {
var jsonContent = fileContent
.replace("module.exports = ", "")
//regex to delete all comments // and :* in the JSON file
.replace(/(\/\*(\n|\r|.)*\*\/)|(\/\/.*(\n|\r))/g, "");
var jsonParsed = JSON.parse(jsonContent);
Object.keys(jsonParsed).sort().forEach(function (key) {
ordered[key] = jsonParsed[key];
});
}
return strArray;
}
} catch (e) {
console.log("file: " + langFilePath + " contains an error: " + e);
//If there is an error with the current file content, abort
return;
}
/**
* Get all the tags in the files with extension .ts of the current project
*/
function getAllTags() {
const srcPath = __dirname + '/../../../';
var listFilteredFiles = walkSync(srcPath, [], '.ts');
var allTags = listFilteredFiles.map(function(x) {return searchInFile(x)} );
//flatten list of list in a simple list
var flattenedTags = [].concat.apply([], allTags);
//distinct
var uniq = Array.from(new Set(flattenedTags));
var sorted = uniq.sort(function (a, b) { return a.localeCompare(b); });
return sorted;
}
/**
* For debugging
*/
function logAllTags() {
console.dir(getAllTags());
}
/**
* Create the translation file or update it with new tags
* The tags are in the following order:
* 1. New tags in English that need to be translated (ASC)
* 2. Tags already translated, and kept because it match an existing tag in src (ASC)
* 3. Tags already in the file before but not found at the moment in the src (ASC)
* @param {string} lang The short name of the language. for the language in parameter
*/
function createOrUpdateTranslationFile(lang) {
lang = lang || 'en';
//check current file entry
const langFilePath = __dirname + '/' + lang + '.js';
var fs = fs || require('fs')
try {
var columnsResult = HelperNamespace.getAllTags();
var jsonCurrentTagData = {};
columnsResult.forEach(function (column) {
jsonCurrentTagData[column] = column;
});
var ordered = {};
var fileContent;
try {
//check the file can be opened
var stats = fs.statSync(langFilePath);
// load the file
var fileContent = fs.readFileSync(langFilePath, 'utf8');
console.log("Current file content: ");
console.log(fileContent);
}
catch (e) { // do this
console.log("we will create the file: " + langFilePath);
//If there is no current file, we will create it
};
try {
if (fileContent != undefined) {
var jsonContent = fileContent
.replace("module.exports = ", "")
//regex to delete all comments // and :* in the JSON file
.replace(/(\/\*(\n|\r|.)*\*\/)|(\/\/.*(\n|\r))/g, "");
var jsonParsed = JSON.parse(jsonContent);
Object.keys(jsonParsed).sort().forEach(function (key) {
ordered[key] = jsonParsed[key];
});
}
} catch (e) {
console.log("file: " + langFilePath + " contains an error: " + e);
//If there is an error with the current file content, abort
return;
}
// merge new tags with existing translation
var result = {};
var unexistingTag = {};
// all current tags in English
for (var key in jsonCurrentTagData) result[key] = jsonCurrentTagData[key];
for (var key in ordered) {
// replace current tag with an existing translation
if (result.hasOwnProperty(key)) {
delete result[key];
result[key] = ordered[key];
}
// if the tag doesn't exist but a translation exists,
// put the key/value at the end of the json
else {
unexistingTag[key] = ordered[key];
}
}
for (var key in unexistingTag) result[key] = unexistingTag[key];
var stringJson = JSON.stringify(result, null, " ");
var newFileContent = "module.exports = " + stringJson;
fs.writeFileSync(langFilePath, newFileContent);
} catch (e) {
console.log("file: " + langFilePath + ". error append: " + e);
// merge new tags with existing translation
var result = {};
var unexistingTag = {};
// all current tags in English
for (var key in jsonCurrentTagData) result[key] = jsonCurrentTagData[key];
for (var key in ordered) {
// replace current tag with an existing translation
if (result.hasOwnProperty(key)) {
delete result[key];
result[key] = ordered[key];
}
}
// if the tag doesn't exist but a translation exists,
// put the key/value at the end of the json
else {
unexistingTag[key] = ordered[key];
}
}
for (var key in unexistingTag) result[key] = unexistingTag[key];
//public functions
return {
logAllTags: logAllTags,
getAllTags: getAllTags,
createOrUpdateTranslationFile: createOrUpdateTranslationFile
};
var stringJson = JSON.stringify(result, null, " ");
var newFileContent = "module.exports = " + stringJson;
fs.writeFileSync(langFilePath, newFileContent);
} catch (e) {
console.log("file: " + langFilePath + ". error append: " + e);
}
}
//public functions
return {
logAllTags: logAllTags,
getAllTags: getAllTags,
createOrUpdateTranslationFile: createOrUpdateTranslationFile
};
})();
// Need to run this cmd in this folder: node _helper.js

View File

@ -11,7 +11,7 @@ export class LabsFeatures extends React.Component<{}, {}> {
render() {
return <Widget className="peripherals-widget">
<WidgetHeader title={t("App Settings")}
helpText={t(ToolTips.LABS)}>
helpText={ToolTips.LABS}>
</WidgetHeader>
<WidgetBody>
<LabsFeaturesList onToggle={(x) => {

View File

@ -4,171 +4,171 @@ export namespace ToolTips {
// Controls
export const MOVE =
`Use these manual control buttons to move FarmBot in realtime. Press the
trim(`Use these manual control buttons to move FarmBot in realtime. Press the
arrows for relative movements or type in new coordinates and press GO for an
absolute movement. Tip: Press the Home button when you are done so FarmBot
is ready to get back to work.`;
is ready to get back to work.`);
export const WEBCAM =
`If you have a webcam, you can view the video stream in this widget.
Press the edit button to update and save your webcam URL.`;
trim(`If you have a webcam, you can view the video stream in this widget.
Press the edit button to update and save your webcam URL.`);
export const PERIPHERALS =
`Use these toggle switches to control FarmBot's peripherals in realtime. To
edit and create new peripherals, press the EDIT button. Make sure to turn
things off when you're done!`;
trim(`Use these toggle switches to control FarmBot's peripherals in realtime.
To edit and create new peripherals, press the EDIT button. Make sure to turn
things off when you're done!`);
// Device
export const OS_SETTINGS =
`View and change device settings.`;
trim(`View and change device settings.`);
export const HW_SETTINGS =
`Change settings of your FarmBot hardware with the fields below. Caution:
trim(`Change settings of your FarmBot hardware with the fields below. Caution:
Changing these settings to extreme values can cause hardware malfunction.
Make sure to test any new settings before letting your FarmBot use them
unsupervised. Tip: Recalibrate FarmBot after changing settings and test a
few sequences to verify that everything works as expected.`;
few sequences to verify that everything works as expected.`);
export const PIN_BINDINGS =
`Assign a sequence to execute when a Raspberry Pi GPIO pin is activated.`;
trim(`Assign a sequence to execute when a Raspberry Pi GPIO pin is activated.`);
// Connectivity
export const CONNECTIVITY =
`Diagnose connectivity issues with FarmBot and the browser.`;
trim(`Diagnose connectivity issues with FarmBot and the browser.`);
// Hardware Settings: Homing and Calibration
export const HOMING =
`(Alpha) If encoders or end-stops are enabled, home axis (find zero).`;
trim(`(Alpha) If encoders or end-stops are enabled, home axis (find zero).`);
export const CALIBRATION =
`(Alpha) If encoders or end-stops are enabled, home axis and determine
maximum.`;
trim(`(Alpha) If encoders or end-stops are enabled, home axis and determine
maximum.`);
export const SET_ZERO_POSITION =
`Set the current location as zero.`;
trim(`Set the current location as zero.`);
export const FIND_HOME_ON_BOOT =
`If encoders or end-stops are enabled, find the home position when the
trim(`If encoders or end-stops are enabled, find the home position when the
device powers on. Warning! This will perform homing on all axes when the
device powers on. Encoders or endstops must be enabled. It is recommended
to make sure homing works properly before enabling this feature.`;
to make sure homing works properly before enabling this feature.`);
export const STOP_AT_HOME =
`Stop at the home location of the axis.`;
trim(`Stop at the home location of the axis.`);
export const STOP_AT_MAX =
`Don't allow movement past the maximum value provided in AXIS LENGTH.`;
trim(`Don't allow movement past the maximum value provided in AXIS LENGTH.`);
export const NEGATIVE_COORDINATES_ONLY =
`Restrict travel to negative coordinate locations. Overridden by disabling
STOP AT HOME.`;
trim(`Restrict travel to negative coordinate locations. Overridden by
disabling STOP AT HOME.`);
export const LENGTH =
`Set the length of each axis to provide software limits. Used only if
STOP AT MAX is enabled.`;
trim(`Set the length of each axis to provide software limits. Used only if
STOP AT MAX is enabled.`);
export const TIMEOUT_AFTER =
`Amount of time to wait for a command to execute before stopping.`;
trim(`Amount of time to wait for a command to execute before stopping.`);
// Hardware Settings: Motors
export const MAX_MOVEMENT_RETRIES =
`Number of times to retry a movement before stopping.`;
trim(`Number of times to retry a movement before stopping.`);
export const E_STOP_ON_MOV_ERR =
`Emergency stop if movement is not complete after the maximum number of
retries.`;
trim(`Emergency stop if movement is not complete after the maximum number of
retries.`);
export const MAX_SPEED =
`Maximum travel speed after acceleration in motor steps per second.`;
trim(`Maximum travel speed after acceleration in motor steps per second.`);
export const HOME_SPEED =
`Home position adjustment travel speed (homing and calibration)
in motor steps per second.`;
trim(`Home position adjustment travel speed (homing and calibration)
in motor steps per second.`);
export const MIN_SPEED =
`Minimum movement speed in motor steps per second. Also used for homing
and calibration.`;
trim(`Minimum movement speed in motor steps per second. Also used for homing
and calibration.`);
export const ACCELERATE_FOR =
`Number of steps used for acceleration and deceleration.`;
trim(`Number of steps used for acceleration and deceleration.`);
export const STEPS_PER_MM =
`The number of motor steps required to move the axis one millimeter.`;
trim(`The number of motor steps required to move the axis one millimeter.`);
export const ALWAYS_POWER_MOTORS =
`Keep power applied to motors. Prevents slipping from gravity in certain
situations.`;
trim(`Keep power applied to motors. Prevents slipping from gravity in certain
situations.`);
export const INVERT_MOTORS =
`Invert direction of motor during calibration.`;
trim(`Invert direction of motor during calibration.`);
export const ENABLE_X2_MOTOR =
`Enable use of a second x-axis motor. Connects to E0 on RAMPS.`;
trim(`Enable use of a second x-axis motor. Connects to E0 on RAMPS.`);
// Hardware Settings: Encoders and Endstops
export const ENABLE_ENCODERS =
`(Alpha) Enable use of rotary encoders during calibration and homing.`;
trim(`(Alpha) Enable use of rotary encoders during calibration and homing.`);
export const ENCODER_POSITIONING =
`[EXPERIMENTAL] Use encoders for positioning.`;
trim(`[EXPERIMENTAL] Use encoders for positioning.`);
export const INVERT_ENCODERS =
`(Alpha) Reverse the direction of encoder position reading.`;
trim(`(Alpha) Reverse the direction of encoder position reading.`);
export const MAX_MISSED_STEPS =
`(Alpha) Number of steps missed (determined by encoder) before motor is
considered to have stalled.`;
trim(`(Alpha) Number of steps missed (determined by encoder) before motor is
considered to have stalled.`);
export const ENCODER_MISSED_STEP_DECAY =
`(Alpha) Reduction to missed step total for every good step.`;
trim(`(Alpha) Reduction to missed step total for every good step.`);
export const ENCODER_SCALING =
`(Alpha) encoder scaling factor = 100 * (motor resolution * microsteps) /
(encoder resolution).`;
trim(`(Alpha) encoder scaling factor = 100 * (motor resolution * microsteps)
/ (encoder resolution).`);
export const ENABLE_ENDSTOPS =
`Enable use of electronic end-stops during calibration and homing.`;
trim(`Enable use of electronic end-stops during calibration and homing.`);
export const INVERT_ENDPOINTS =
`Swap axis end-stops during calibration.`;
trim(`Swap axis end-stops during calibration.`);
// Hardware Settings: Pin Guard
export const PIN_GUARD_PIN_NUMBER =
`The number of the pin to guard. This pin will be set to the specified
state after the duration specified by TIMEOUT.`;
trim(`The number of the pin to guard. This pin will be set to the specified
state after the duration specified by TIMEOUT.`);
// Farmware
export const FARMWARE =
`Manage Farmware (plugins).`;
trim(`Manage Farmware (plugins).`);
export const PHOTOS =
`Take and view photos with your FarmBot's camera.`;
trim(`Take and view photos with your FarmBot's camera.`);
export const WEED_DETECTOR =
`Detect weeds using FarmBot's camera and display them on the Farm Designer
map.`;
trim(`Detect weeds using FarmBot's camera and display them on the
Farm Designer map.`);
export const CAMERA_CALIBRATION =
`Calibrate FarmBot's camera for use in the weed detection software.`;
trim(`Calibrate FarmBot's camera for use in the weed detection software.`);
// Sequences
export const SEQUENCE_COMMANDS =
`These are the most basic commands FarmBot can execute. Drag and drop them
to create sequences for watering, planting seeds, measuring soil properties,
and more.`;
trim(`These are the most basic commands FarmBot can execute. Drag and drop
them to create sequences for watering, planting seeds, measuring soil
properties, and more.`);
export const SEQUENCE_EDITOR =
`Drag and drop commands here to create sequences for watering, planting
trim(`Drag and drop commands here to create sequences for watering, planting
seeds, measuring soil properties, and more. Press the Test button to
immediately try your sequence with FarmBot. You can also edit, copy, and
delete existing sequences; assign a color; and give your commands custom
names.`;
names.`);
export const SEQUENCE_LIST =
`Here is the list of all of your sequences. Click one to edit.`;
trim(`Here is the list of all of your sequences. Click one to edit.`);
export const MOVE_ABSOLUTE =
`The Move Absolute step instructs FarmBot to move to the specified
trim(`The Move Absolute step instructs FarmBot to move to the specified
coordinate regardless of the current position. For example, if FarmBot is
currently at X=1000, Y=1000 and it receives a Move Absolute where X=0 and
Y=3000, then FarmBot will move to X=0, Y=3000. If FarmBot must move in
@ -177,110 +177,114 @@ export namespace ToolTips {
Offsets allow you to more easily instruct FarmBot to move to a location,
but offset from it by the specified amount. For example moving to just
above where a peripheral is located. Using offsets lets FarmBot do the
math for you.`;
math for you.`);
export const MOVE_RELATIVE =
`The Move Relative step instructs FarmBot to move the specified distance
trim(`The Move Relative step instructs FarmBot to move the specified distance
from its current location. For example, if FarmBot is currently at X=1000,
Y=1000 and it receives a Move Relative where X=0 and Y=3000, then FarmBot
will move to X=1000, Y=4000. If FarmBot must move in multiple directions,
it will move diagonally. If you require straight movements along one axis
at a time, use multiple Move Relative steps. Move Relative steps should be
preceded by a Move Absolute step to ensure you are starting from a known
location.`;
location.`);
export const WRITE_PIN =
`The Write Pin step instructs FarmBot to set the specified pin on the
trim(`The Write Pin step instructs FarmBot to set the specified pin on the
Arduino to the specified mode and value. Use the digital pin mode for
on (1) and off (0) control, and analog pin mode for PWM (pulse width
modulation) (0-255).`;
modulation) (0-255).`);
export const READ_PIN =
`The Read Pin step instructs FarmBot to read the current value of the
trim(`The Read Pin step instructs FarmBot to read the current value of the
specified pin. Pin Mode: Use digital for a 0 (LOW) or 1 (HIGH) response,
and analog for a voltage reading (0-1023 for 0-5V).`;
and analog for a voltage reading (0-1023 for 0-5V).`);
export const WAIT =
`The Wait step instructs FarmBot to wait for the specified amount of time.
Use it in combination with the Pin Write step to water for a length of
time.`;
trim(`The Wait step instructs FarmBot to wait for the specified amount
of time. Use it in combination with the Pin Write step to water for a
length of time.`);
export const SEND_MESSAGE =
`The Send Message step instructs FarmBot to send a custom message to the
logs (and toast message and/or email, if selected). This can help you with
debugging your sequences.`;
trim(`The Send Message step instructs FarmBot to send a custom message
to the logs (and toast message and/or email, if selected). This can
help you with debugging your sequences.`);
export const FIND_HOME =
`The Find Home step instructs the device to perform a homing command to
find and set zero for the chosen axis or axes.`;
trim(`The Find Home step instructs the device to perform a homing
command to find and set zero for the chosen axis or axes.`);
export const IF =
`Execute a sequence if a condition is satisfied. If the condition is not
satisfied, chose to do nothing or execute a different sequence.`;
trim(`Execute a sequence if a condition is satisfied. If the condition
is not satisfied, chose to do nothing or execute a different sequence.`);
export const EXECUTE_SEQUENCE =
`Executes another sequence.`;
trim(`Executes another sequence.`);
export const EXECUTE_SCRIPT = `The Run Farmware step runs a Farmware package.
Visit the Farmware page to install and manage Farmware.`;
export const EXECUTE_SCRIPT =
trim(`The Run Farmware step runs a Farmware package.
Visit the Farmware page to install and manage Farmware.`);
export const TAKE_PHOTO =
`Snaps a photo using the device camera. Select the camera type on the
Device page.`;
trim(`Snaps a photo using the device camera. Select the camera type on the
Device page.`);
// Regimens
export const BULK_SCHEDULER =
`Add sequences to your regimen by selecting a sequence from the drop down,
specifying a time, choosing which days it should run on, and then clicking
the + button. For example: a Seeding sequence might be scheduled for Day 1,
while a Watering sequence would be scheduled to run every other day.`;
trim(`Add sequences to your regimen by selecting a sequence from the
drop down, specifying a time, choosing which days it should run on,
and then clicking the + button. For example: a Seeding sequence might
be scheduled for Day 1, while a Watering sequence would be scheduled
to run every other day.`);
export const REGIMEN_EDITOR =
`Regimens allow FarmBot to take care of a plant throughout its entire life.
A regimen consists of many sequences that are scheduled to run based on the
age of the plant. Regimens are applied to plants from the farm designer
(coming soon) and can be re-used on many plants growing at the same or
different times. Multiple regimens can be applied to any one plant.`;
trim(`Regimens allow FarmBot to take care of a plant throughout its
entire life. A regimen consists of many sequences that are scheduled
to run based on the age of the plant. Regimens are applied to plants
from the farm designer (coming soon) and can be re-used on many plants
growing at the same or different times. Multiple regimens can be
applied to any one plant.`);
export const REGIMEN_LIST =
`This is a list of all of your regimens. Click one to begin editing it.`;
trim(`This is a list of all of your regimens. Click one to begin
editing it.`);
// Tools
export const TOOL_LIST =
`This is a list of all your FarmBot Tools. Click the Edit button to add,
edit, or delete tools.`;
trim(`This is a list of all your FarmBot Tools. Click the Edit button
to add, edit, or delete tools.`);
export const TOOLBAY_LIST =
`Toolbays are where you store your FarmBot Tools. Each Toolbay has Slots
that you can put your Tools in, which should be reflective of your real
FarmBot hardware configuration.`;
trim(`Toolbays are where you store your FarmBot Tools. Each Toolbay
has Slots that you can put your Tools in, which should be reflective
of your real FarmBot hardware configuration.`);
// Logs
export const LOGS =
`View and filter log messages.`;
trim(`View and filter log messages.`);
export const SEQUENCE_LOG_BEGIN =
`Send a log message upon the start of sequence execution.`;
trim(`Send a log message upon the start of sequence execution.`);
export const SEQUENCE_LOG_STEP =
`Send a log message for each sequence step.`;
trim(`Send a log message for each sequence step.`);
export const SEQUENCE_LOG_END =
`Send a log message upon the end of sequence execution.`;
trim(`Send a log message upon the end of sequence execution.`);
export const FIRMWARE_LOG_SENT =
`Log all commands sent to firmware (clears after refresh).`;
trim(`Log all commands sent to firmware (clears after refresh).`);
export const FIRMWARE_LOG_RECEIVED =
`Log all responses received from firmware (clears after refresh).
Warning: extremely verbose.`;
trim(`Log all responses received from firmware (clears after refresh).
Warning: extremely verbose.`);
export const FIRMWARE_DEBUG_MESSAGES =
`Log all debug received from firmware (clears after refresh).`;
trim(`Log all debug received from firmware (clears after refresh).`);
// App
export const LABS =
`Customize your web app experience.`;
trim(`Customize your web app experience.`);
}
export namespace Content {
@ -426,8 +430,8 @@ export namespace Content {
export const FARM_EVENT_TZ_WARNING =
trim(`Note: Times displayed according to FarmBot's local time, which
is currently different from your browser's time. Timezone data is configurable
on the Device page).`);
is currently different from your browser's time. Timezone data is
configurable on the Device page).`);
export const FIRST_PARTY_WARNING =
trim(`Are you sure you want to delete this first party farmware?

View File

@ -28,7 +28,7 @@ export function EncodersAndEndStops(props: EncodersProps) {
<Collapse isOpen={!!encoders_and_endstops}>
<BooleanMCUInputGroup
name={t("Enable Encoders")}
tooltip={t(ToolTips.ENABLE_ENCODERS)}
tooltip={ToolTips.ENABLE_ENCODERS}
x={"encoder_enabled_x"}
y={"encoder_enabled_y"}
z={"encoder_enabled_z"}
@ -36,7 +36,7 @@ export function EncodersAndEndStops(props: EncodersProps) {
bot={bot} />
<BooleanMCUInputGroup
name={t("Use Encoders for Positioning")}
tooltip={t(ToolTips.ENCODER_POSITIONING)}
tooltip={ToolTips.ENCODER_POSITIONING}
x={"encoder_use_for_pos_x"}
y={"encoder_use_for_pos_y"}
z={"encoder_use_for_pos_z"}
@ -45,7 +45,7 @@ export function EncodersAndEndStops(props: EncodersProps) {
bot={bot} />
<BooleanMCUInputGroup
name={t("Invert Encoders")}
tooltip={t(ToolTips.INVERT_ENCODERS)}
tooltip={ToolTips.INVERT_ENCODERS}
x={"encoder_invert_x"}
y={"encoder_invert_y"}
z={"encoder_invert_z"}
@ -54,7 +54,7 @@ export function EncodersAndEndStops(props: EncodersProps) {
bot={bot} />
<NumericMCUInputGroup
name={t("Max Missed Steps")}
tooltip={t(ToolTips.MAX_MISSED_STEPS)}
tooltip={ToolTips.MAX_MISSED_STEPS}
x={"encoder_missed_steps_max_x"}
y={"encoder_missed_steps_max_y"}
z={"encoder_missed_steps_max_z"}
@ -63,7 +63,7 @@ export function EncodersAndEndStops(props: EncodersProps) {
dispatch={dispatch} />
<NumericMCUInputGroup
name={t("Encoder Missed Step Decay")}
tooltip={t(ToolTips.ENCODER_MISSED_STEP_DECAY)}
tooltip={ToolTips.ENCODER_MISSED_STEP_DECAY}
x={"encoder_missed_steps_decay_x"}
y={"encoder_missed_steps_decay_y"}
z={"encoder_missed_steps_decay_z"}
@ -72,7 +72,7 @@ export function EncodersAndEndStops(props: EncodersProps) {
dispatch={dispatch} />
<NumericMCUInputGroup
name={t("Encoder Scaling")}
tooltip={t(ToolTips.ENCODER_SCALING)}
tooltip={ToolTips.ENCODER_SCALING}
x={"encoder_scaling_x"}
y={"encoder_scaling_y"}
z={"encoder_scaling_z"}
@ -81,7 +81,7 @@ export function EncodersAndEndStops(props: EncodersProps) {
dispatch={dispatch} />
<BooleanMCUInputGroup
name={t("Enable Endstops")}
tooltip={t(ToolTips.ENABLE_ENDSTOPS)}
tooltip={ToolTips.ENABLE_ENDSTOPS}
x={"movement_enable_endpoints_x"}
y={"movement_enable_endpoints_y"}
z={"movement_enable_endpoints_z"}
@ -89,7 +89,7 @@ export function EncodersAndEndStops(props: EncodersProps) {
bot={bot} />
<BooleanMCUInputGroup
name={t("Invert Endstops")}
tooltip={t(ToolTips.INVERT_ENDPOINTS)}
tooltip={ToolTips.INVERT_ENDPOINTS}
x={"movement_invert_endpoints_x"}
y={"movement_invert_endpoints_y"}
z={"movement_invert_endpoints_z"}

View File

@ -42,7 +42,7 @@ export function HomingAndCalibration(props: HomingAndCalibrationProps) {
<ZeroRow />
<BooleanMCUInputGroup
name={t("Find Home on Boot")}
tooltip={t(ToolTips.FIND_HOME_ON_BOOT)}
tooltip={ToolTips.FIND_HOME_ON_BOOT}
disable={disabled}
x={"movement_home_at_boot_x"}
y={"movement_home_at_boot_y"}
@ -52,7 +52,7 @@ export function HomingAndCalibration(props: HomingAndCalibrationProps) {
caution={true} />
<BooleanMCUInputGroup
name={t("Stop at Home")}
tooltip={t(ToolTips.STOP_AT_HOME)}
tooltip={ToolTips.STOP_AT_HOME}
x={"movement_stop_at_home_x"}
y={"movement_stop_at_home_y"}
z={"movement_stop_at_home_z"}
@ -60,7 +60,7 @@ export function HomingAndCalibration(props: HomingAndCalibrationProps) {
bot={bot} />
<BooleanMCUInputGroup
name={t("Stop at Max")}
tooltip={t(ToolTips.STOP_AT_MAX)}
tooltip={ToolTips.STOP_AT_MAX}
x={"movement_stop_at_max_x"}
y={"movement_stop_at_max_y"}
z={"movement_stop_at_max_z"}
@ -68,7 +68,7 @@ export function HomingAndCalibration(props: HomingAndCalibrationProps) {
bot={bot} />
<BooleanMCUInputGroup
name={t("Negative Coordinates Only")}
tooltip={t(ToolTips.NEGATIVE_COORDINATES_ONLY)}
tooltip={ToolTips.NEGATIVE_COORDINATES_ONLY}
x={"movement_home_up_x"}
y={"movement_home_up_y"}
z={"movement_home_up_z"}
@ -76,7 +76,7 @@ export function HomingAndCalibration(props: HomingAndCalibrationProps) {
bot={bot} />
<NumericMCUInputGroup
name={t("Axis Length (steps)")}
tooltip={t(ToolTips.LENGTH)}
tooltip={ToolTips.LENGTH}
x={"movement_axis_nr_steps_x"}
y={"movement_axis_nr_steps_y"}
z={"movement_axis_nr_steps_z"}
@ -90,7 +90,7 @@ export function HomingAndCalibration(props: HomingAndCalibrationProps) {
intSize={axisLengthIntSize} />
<NumericMCUInputGroup
name={t("Timeout after (seconds)")}
tooltip={t(ToolTips.TIMEOUT_AFTER)}
tooltip={ToolTips.TIMEOUT_AFTER}
x={"movement_timeout_x"}
y={"movement_timeout_y"}
z={"movement_timeout_z"}

View File

@ -21,7 +21,7 @@ export function HomingRow(props: HomingRowProps) {
<label>
{t("HOMING")}
</label>
<SpacePanelToolTip tooltip={t(ToolTips.HOMING)} />
<SpacePanelToolTip tooltip={ToolTips.HOMING} />
</Col>
{axisTrackingStatus(hardware)
.map((row) => {

View File

@ -20,7 +20,7 @@ export function StepsPerMmSettings(props: MotorsProps) {
if (minFwVersionCheck(firmware_version, "5.0.5")) {
return <NumericMCUInputGroup
name={t("Steps per MM")}
tooltip={t(ToolTips.STEPS_PER_MM)}
tooltip={ToolTips.STEPS_PER_MM}
x={"movement_step_per_mm_x"}
y={"movement_step_per_mm_y"}
z={"movement_step_per_mm_z"}
@ -32,7 +32,7 @@ export function StepsPerMmSettings(props: MotorsProps) {
<label>
{t("Steps per MM")}
</label>
<SpacePanelToolTip tooltip={t(ToolTips.STEPS_PER_MM)} />
<SpacePanelToolTip tooltip={ToolTips.STEPS_PER_MM} />
</Col>
<Col xs={2}>
<BotConfigInputBox
@ -74,7 +74,7 @@ export function Motors(props: MotorsProps) {
<label>
{t("Max Retries")}
</label>
<SpacePanelToolTip tooltip={t(ToolTips.MAX_MOVEMENT_RETRIES)} />
<SpacePanelToolTip tooltip={ToolTips.MAX_MOVEMENT_RETRIES} />
</Col>
<Col xs={6}>
<McuInputBox
@ -88,7 +88,7 @@ export function Motors(props: MotorsProps) {
<label>
{t("E-Stop on Movement Error")}
</label>
<SpacePanelToolTip tooltip={t(ToolTips.E_STOP_ON_MOV_ERR)} />
<SpacePanelToolTip tooltip={ToolTips.E_STOP_ON_MOV_ERR} />
</Col>
<Col xs={2} className={"centered-button-div"}>
<ToggleButton
@ -99,7 +99,7 @@ export function Motors(props: MotorsProps) {
</Row>
<NumericMCUInputGroup
name={t("Max Speed (steps/s)")}
tooltip={t(ToolTips.MAX_SPEED)}
tooltip={ToolTips.MAX_SPEED}
x={"movement_max_spd_x"}
y={"movement_max_spd_y"}
z={"movement_max_spd_z"}
@ -108,7 +108,7 @@ export function Motors(props: MotorsProps) {
{minFwVersionCheck(firmware_version, "5.0.5") &&
<NumericMCUInputGroup
name={t("Homing Speed (steps/s)")}
tooltip={t(ToolTips.HOME_SPEED)}
tooltip={ToolTips.HOME_SPEED}
x={"movement_home_spd_x"}
y={"movement_home_spd_y"}
z={"movement_home_spd_z"}
@ -116,7 +116,7 @@ export function Motors(props: MotorsProps) {
dispatch={dispatch} />}
<NumericMCUInputGroup
name={t("Minimum Speed (steps/s)")}
tooltip={t(ToolTips.MIN_SPEED)}
tooltip={ToolTips.MIN_SPEED}
x={"movement_min_spd_x"}
y={"movement_min_spd_y"}
z={"movement_min_spd_z"}
@ -124,7 +124,7 @@ export function Motors(props: MotorsProps) {
dispatch={dispatch} />
<NumericMCUInputGroup
name={t("Accelerate for (steps)")}
tooltip={t(ToolTips.ACCELERATE_FOR)}
tooltip={ToolTips.ACCELERATE_FOR}
x={"movement_steps_acc_dec_x"}
y={"movement_steps_acc_dec_y"}
z={"movement_steps_acc_dec_z"}
@ -136,7 +136,7 @@ export function Motors(props: MotorsProps) {
sourceFbosConfig={sourceFbosConfig} />
<BooleanMCUInputGroup
name={t("Always Power Motors")}
tooltip={t(ToolTips.ALWAYS_POWER_MOTORS)}
tooltip={ToolTips.ALWAYS_POWER_MOTORS}
x={"movement_keep_active_x"}
y={"movement_keep_active_y"}
z={"movement_keep_active_z"}
@ -144,7 +144,7 @@ export function Motors(props: MotorsProps) {
bot={bot} />
<BooleanMCUInputGroup
name={t("Invert Motors")}
tooltip={t(ToolTips.INVERT_MOTORS)}
tooltip={ToolTips.INVERT_MOTORS}
x={"movement_invert_motor_x"}
y={"movement_invert_motor_y"}
z={"movement_invert_motor_z"}
@ -155,7 +155,7 @@ export function Motors(props: MotorsProps) {
<label>
{t("Enable 2nd X Motor")}
</label>
<SpacePanelToolTip tooltip={t(ToolTips.ENABLE_X2_MOTOR)} />
<SpacePanelToolTip tooltip={ToolTips.ENABLE_X2_MOTOR} />
</Col>
<Col xs={2} className={"centered-button-div"}>
<ToggleButton
@ -169,7 +169,7 @@ export function Motors(props: MotorsProps) {
<label>
{t("Invert 2nd X Motor")}
</label>
<SpacePanelToolTip tooltip={t(ToolTips.INVERT_MOTORS)} />
<SpacePanelToolTip tooltip={ToolTips.INVERT_MOTORS} />
</Col>
<Col xs={2} className={"centered-button-div"}>
<ToggleButton

View File

@ -25,7 +25,7 @@ export function PinGuard(props: PinGuardProps) {
<label>
{t("Pin Number")}
</label>
<SpacePanelToolTip tooltip={t(ToolTips.PIN_GUARD_PIN_NUMBER)} />
<SpacePanelToolTip tooltip={ToolTips.PIN_GUARD_PIN_NUMBER} />
</Col>
<Col xs={4}>
<label>

View File

@ -1,4 +1,5 @@
import * as React from "react";
import { t } from "i18next";
interface SPTTProps {
tooltip?: string | undefined;
@ -8,7 +9,7 @@ export function SpacePanelToolTip({ tooltip }: SPTTProps) {
return (tooltip && <div className="help">
<i className="fa fa-question-circle help-icon" />
<div className="help-text">
{tooltip}
{t(tooltip)}
</div>
</div>) || <span />;
}

View File

@ -29,7 +29,7 @@ export class ConnectivityPanel extends React.Component<Props, ConnectivityState>
return <Widget className="connectivity-widget">
<WidgetHeader
title={t("Connectivity")}
helpText={t(ToolTips.CONNECTIVITY)}>
helpText={ToolTips.CONNECTIVITY}>
<RetryBtn
status={this.props.status}
onClick={this.props.onRefresh}

View File

@ -19,7 +19,7 @@ export class CameraCalibration extends
return <Widget className={classname}>
<TitleBar
title={t("Camera Calibration")}
help={t(ToolTips.CAMERA_CALIBRATION)}
help={ToolTips.CAMERA_CALIBRATION}
docs={"farmware#section-weed-detector"}
onCalibrate={this.props.dispatch(calibrate)}
env={this.props.env} />

View File

@ -62,8 +62,8 @@ export class WeedDetector
onDeletionClick={this.clearWeeds}
deletionProgress={this.state.deletionProgress}
onTest={this.props.dispatch(test)}
title={"Weed Detector"}
help={t(ToolTips.WEED_DETECTOR)}
title={t("Weed Detector")}
help={ToolTips.WEED_DETECTOR}
docs={"farmware#section-camera-calibration"} />
<WidgetBody>
<Row>

View File

@ -17,7 +17,7 @@ export function WidgetHeader(props: WidgetHeaderProps) {
{props.helpText &&
<i className="fa fa-question-circle help-icon">
<div className="help-text">
{props.helpText}
{t(props.helpText)}
{props.docPage &&
<a
href={docLink(props.docPage)}