Internationalize all messages without substitutions.

pull/106/head
whitequark 2017-01-07 06:41:13 +00:00
parent 4fda1e4361
commit 984f74d271
21 changed files with 3316 additions and 806 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -212,21 +212,20 @@ if(HAVE_GETTEXT)
set(output_pot ${CMAKE_CURRENT_SOURCE_DIR}/../res/messages.pot) set(output_pot ${CMAKE_CURRENT_SOURCE_DIR}/../res/messages.pot)
set(templ_po ${CMAKE_CURRENT_BINARY_DIR}/messages.po) set(templ_po ${CMAKE_CURRENT_BINARY_DIR}/messages.po)
set(output_po ${CMAKE_CURRENT_SOURCE_DIR}/../res/locales/en_US.po) set(output_po ${CMAKE_CURRENT_SOURCE_DIR}/../res/locales/en_US.po)
set(inputs) set(inputs ${solvespace_core_SOURCES})
foreach(input ${solvespace_core_SOURCES})
list(APPEND inputs ${CMAKE_CURRENT_SOURCE_DIR}/${input})
endforeach()
add_custom_command( add_custom_command(
OUTPUT ${output_pot} OUTPUT ${output_pot}
COMMAND ${XGETTEXT} COMMAND ${XGETTEXT}
--keyword --keyword=_ --keyword=N_ --keyword --keyword=_ --keyword=N_ --keyword=C_:2,1c --keyword=CN_:2,1c
--force-po --width=100 --sort-by-file --force-po --width=100 --sort-by-file
--package-name=SolveSpace --package-version=3.0 --package-name=SolveSpace
--package-version=${solvespace_VERSION_MAJOR}.${solvespace_VERSION_MINOR}
"--copyright-holder=the PACKAGE authors" "--copyright-holder=the PACKAGE authors"
--msgid-bugs-address=whitequark@whitequark.org --msgid-bugs-address=whitequark@whitequark.org
--from-code=utf-8 --output=${output_pot} ${inputs} --from-code=utf-8 --output=${output_pot} ${inputs}
DEPENDS ${inputs} DEPENDS ${inputs}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Extracting translations" COMMENT "Extracting translations"
VERBATIM) VERBATIM)
add_custom_command( add_custom_command(
@ -240,7 +239,7 @@ if(HAVE_GETTEXT)
DEPENDS ${output_pot} DEPENDS ${output_pot}
COMMENT "Updating English translations" COMMENT "Updating English translations"
VERBATIM) VERBATIM)
add_custom_target(solvespace-translations ALL add_custom_target(solvespace-translations
DEPENDS ${output_pot} ${output_po}) DEPENDS ${output_pot} ${output_po})
endif() endif()

View File

@ -239,8 +239,8 @@ void GraphicsWindow::PasteClipboard(Vector trans, double theta, double scale) {
void GraphicsWindow::MenuClipboard(Command id) { void GraphicsWindow::MenuClipboard(Command id) {
if(id != Command::DELETE && !SS.GW.LockedInWorkplane()) { if(id != Command::DELETE && !SS.GW.LockedInWorkplane()) {
Error("Cut, paste, and copy work only in a workplane.\n\n" Error(_("Cut, paste, and copy work only in a workplane.\n\n"
"Activate one with Sketch -> In Workplane."); "Activate one with Sketch -> In Workplane."));
return; return;
} }
@ -256,7 +256,7 @@ void GraphicsWindow::MenuClipboard(Command id) {
case Command::PASTE_TRANSFORM: { case Command::PASTE_TRANSFORM: {
if(SS.clipboard.r.n == 0) { if(SS.clipboard.r.n == 0) {
Error("Clipboard is empty; nothing to paste."); Error(_("Clipboard is empty; nothing to paste."));
break; break;
} }
@ -303,7 +303,7 @@ bool TextWindow::EditControlDoneForPaste(const char *s) {
if(v > 0) { if(v > 0) {
shown.paste.times = v; shown.paste.times = v;
} else { } else {
Error("Number of copies to paste must be at least one."); Error(_("Number of copies to paste must be at least one."));
} }
break; break;
} }
@ -319,7 +319,7 @@ bool TextWindow::EditControlDoneForPaste(const char *s) {
if(fabs(v) > 1e-6) { if(fabs(v) > 1e-6) {
shown.paste.scale = v; shown.paste.scale = v;
} else { } else {
Error("Scale cannot be zero."); Error(_("Scale cannot be zero."));
} }
break; break;
} }
@ -357,7 +357,7 @@ void TextWindow::ScreenPasteTransformed(int link, uint32_t v) {
Entity *e = SK.GetEntity(SS.GW.gs.point[0]); Entity *e = SK.GetEntity(SS.GW.gs.point[0]);
SS.TW.shown.paste.origin = e->PointGetNum(); SS.TW.shown.paste.origin = e->PointGetNum();
} else { } else {
Error("Select one point to define origin of rotation."); Error(_("Select one point to define origin of rotation."));
} }
SS.GW.ClearSelection(); SS.GW.ClearSelection();
break; break;
@ -369,7 +369,7 @@ void TextWindow::ScreenPasteTransformed(int link, uint32_t v) {
SS.TW.shown.paste.trans = SS.TW.shown.paste.trans =
(pb->PointGetNum()).Minus(pa->PointGetNum()); (pb->PointGetNum()).Minus(pa->PointGetNum());
} else { } else {
Error("Select two points to define translation vector."); Error(_("Select two points to define translation vector."));
} }
SS.GW.ClearSelection(); SS.GW.ClearSelection();
break; break;
@ -379,16 +379,16 @@ void TextWindow::ScreenPasteTransformed(int link, uint32_t v) {
SS.TW.shown.paste.trans.Magnitude() < LENGTH_EPS && SS.TW.shown.paste.trans.Magnitude() < LENGTH_EPS &&
SS.TW.shown.paste.times != 1) SS.TW.shown.paste.times != 1)
{ {
Message("Transformation is identity. So all copies will be " Message(_("Transformation is identity. So all copies will be "
"exactly on top of each other."); "exactly on top of each other."));
} }
if(SS.TW.shown.paste.times*SS.clipboard.r.n > 100) { if(SS.TW.shown.paste.times*SS.clipboard.r.n > 100) {
Error("Too many items to paste; split this into smaller " Error(_("Too many items to paste; split this into smaller "
"pastes."); "pastes."));
break; break;
} }
if(!SS.GW.LockedInWorkplane()) { if(!SS.GW.LockedInWorkplane()) {
Error("No workplane active."); Error(_("No workplane active."));
break; break;
} }
Entity *wrkpl = SK.GetEntity(SS.GW.ActiveWorkplane()); Entity *wrkpl = SK.GetEntity(SS.GW.ActiveWorkplane());

View File

@ -325,7 +325,7 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
if(sscanf(s, "%lf, %lf, %lf", &x, &y, &z)==3) { if(sscanf(s, "%lf, %lf, %lf", &x, &y, &z)==3) {
SS.lightDir[edit.i] = Vector::From(x, y, z); SS.lightDir[edit.i] = Vector::From(x, y, z);
} else { } else {
Error("Bad format: specify coordinates as x, y, z"); Error(_("Bad format: specify coordinates as x, y, z"));
} }
InvalidateGraphics(); InvalidateGraphics();
break; break;
@ -336,7 +336,7 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
rgb = rgb.ClampWithin(0, 1); rgb = rgb.ClampWithin(0, 1);
SS.modelColor[edit.i] = RGBf(rgb.x, rgb.y, rgb.z); SS.modelColor[edit.i] = RGBf(rgb.x, rgb.y, rgb.z);
} else { } else {
Error("Bad format: specify color as r, g, b"); Error(_("Bad format: specify color as r, g, b"));
} }
break; break;
} }
@ -361,8 +361,8 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
case Edit::CAMERA_TANGENT: { case Edit::CAMERA_TANGENT: {
SS.cameraTangent = (min(2.0, max(0.0, atof(s))))/1000.0; SS.cameraTangent = (min(2.0, max(0.0, atof(s))))/1000.0;
if(!SS.usePerspectiveProj) { if(!SS.usePerspectiveProj) {
Message("The perspective factor will have no effect until you " Message(_("The perspective factor will have no effect until you "
"enable View -> Use Perspective Projection."); "enable View -> Use Perspective Projection."));
} }
InvalidateGraphics(); InvalidateGraphics();
break; break;
@ -375,7 +375,7 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
case Edit::DIGITS_AFTER_DECIMAL: { case Edit::DIGITS_AFTER_DECIMAL: {
int v = atoi(s); int v = atoi(s);
if(v < 0 || v > 8) { if(v < 0 || v > 8) {
Error("Specify between 0 and 8 digits after the decimal."); Error(_("Specify between 0 and 8 digits after the decimal."));
} else { } else {
SS.SetUnitDigitsAfterDecimal(v); SS.SetUnitDigitsAfterDecimal(v);
} }
@ -387,7 +387,7 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
if(e) { if(e) {
double ev = e->Eval(); double ev = e->Eval();
if(fabs(ev) < 0.001 || isnan(ev)) { if(fabs(ev) < 0.001 || isnan(ev)) {
Error("Export scale must not be zero!"); Error(_("Export scale must not be zero!"));
} else { } else {
SS.exportScale = (float)ev; SS.exportScale = (float)ev;
} }
@ -399,7 +399,7 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
if(e) { if(e) {
double ev = SS.ExprToMm(e); double ev = SS.ExprToMm(e);
if(isnan(ev) || ev < 0) { if(isnan(ev) || ev < 0) {
Error("Cutter radius offset must not be negative!"); Error(_("Cutter radius offset must not be negative!"));
} else { } else {
SS.exportOffset = (float)ev; SS.exportOffset = (float)ev;
} }
@ -453,10 +453,10 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
SS.autosaveInterval = interval; SS.autosaveInterval = interval;
SetAutosaveTimerFor(interval); SetAutosaveTimerFor(interval);
} else { } else {
Error("Bad value: autosave interval should be positive"); Error(_("Bad value: autosave interval should be positive"));
} }
} else { } else {
Error("Bad format: specify interval in integral minutes"); Error(_("Bad format: specify interval in integral minutes"));
} }
break; break;
} }

View File

@ -7,47 +7,47 @@
#include "solvespace.h" #include "solvespace.h"
std::string Constraint::DescriptionString() const { std::string Constraint::DescriptionString() const {
const char *s; std::string s;
switch(type) { switch(type) {
case Type::POINTS_COINCIDENT: s = "pts-coincident"; break; case Type::POINTS_COINCIDENT: s = C_("constr-name", "pts-coincident"); break;
case Type::PT_PT_DISTANCE: s = "pt-pt-distance"; break; case Type::PT_PT_DISTANCE: s = C_("constr-name", "pt-pt-distance"); break;
case Type::PT_LINE_DISTANCE: s = "pt-line-distance"; break; case Type::PT_LINE_DISTANCE: s = C_("constr-name", "pt-line-distance"); break;
case Type::PT_PLANE_DISTANCE: s = "pt-plane-distance"; break; case Type::PT_PLANE_DISTANCE: s = C_("constr-name", "pt-plane-distance"); break;
case Type::PT_FACE_DISTANCE: s = "pt-face-distance"; break; case Type::PT_FACE_DISTANCE: s = C_("constr-name", "pt-face-distance"); break;
case Type::PROJ_PT_DISTANCE: s = "proj-pt-pt-distance"; break; case Type::PROJ_PT_DISTANCE: s = C_("constr-name", "proj-pt-pt-distance"); break;
case Type::PT_IN_PLANE: s = "pt-in-plane"; break; case Type::PT_IN_PLANE: s = C_("constr-name", "pt-in-plane"); break;
case Type::PT_ON_LINE: s = "pt-on-line"; break; case Type::PT_ON_LINE: s = C_("constr-name", "pt-on-line"); break;
case Type::PT_ON_FACE: s = "pt-on-face"; break; case Type::PT_ON_FACE: s = C_("constr-name", "pt-on-face"); break;
case Type::EQUAL_LENGTH_LINES: s = "eq-length"; break; case Type::EQUAL_LENGTH_LINES: s = C_("constr-name", "eq-length"); break;
case Type::EQ_LEN_PT_LINE_D: s = "eq-length-and-pt-ln-dist"; break; case Type::EQ_LEN_PT_LINE_D: s = C_("constr-name", "eq-length-and-pt-ln-dist"); break;
case Type::EQ_PT_LN_DISTANCES: s = "eq-pt-line-distances"; break; case Type::EQ_PT_LN_DISTANCES: s = C_("constr-name", "eq-pt-line-distances"); break;
case Type::LENGTH_RATIO: s = "length-ratio"; break; case Type::LENGTH_RATIO: s = C_("constr-name", "length-ratio"); break;
case Type::LENGTH_DIFFERENCE: s = "length-difference"; break; case Type::LENGTH_DIFFERENCE: s = C_("constr-name", "length-difference"); break;
case Type::SYMMETRIC: s = "symmetric"; break; case Type::SYMMETRIC: s = C_("constr-name", "symmetric"); break;
case Type::SYMMETRIC_HORIZ: s = "symmetric-h"; break; case Type::SYMMETRIC_HORIZ: s = C_("constr-name", "symmetric-h"); break;
case Type::SYMMETRIC_VERT: s = "symmetric-v"; break; case Type::SYMMETRIC_VERT: s = C_("constr-name", "symmetric-v"); break;
case Type::SYMMETRIC_LINE: s = "symmetric-line"; break; case Type::SYMMETRIC_LINE: s = C_("constr-name", "symmetric-line"); break;
case Type::AT_MIDPOINT: s = "at-midpoint"; break; case Type::AT_MIDPOINT: s = C_("constr-name", "at-midpoint"); break;
case Type::HORIZONTAL: s = "horizontal"; break; case Type::HORIZONTAL: s = C_("constr-name", "horizontal"); break;
case Type::VERTICAL: s = "vertical"; break; case Type::VERTICAL: s = C_("constr-name", "vertical"); break;
case Type::DIAMETER: s = "diameter"; break; case Type::DIAMETER: s = C_("constr-name", "diameter"); break;
case Type::PT_ON_CIRCLE: s = "pt-on-circle"; break; case Type::PT_ON_CIRCLE: s = C_("constr-name", "pt-on-circle"); break;
case Type::SAME_ORIENTATION: s = "same-orientation"; break; case Type::SAME_ORIENTATION: s = C_("constr-name", "same-orientation"); break;
case Type::ANGLE: s = "angle"; break; case Type::ANGLE: s = C_("constr-name", "angle"); break;
case Type::PARALLEL: s = "parallel"; break; case Type::PARALLEL: s = C_("constr-name", "parallel"); break;
case Type::ARC_LINE_TANGENT: s = "arc-line-tangent"; break; case Type::ARC_LINE_TANGENT: s = C_("constr-name", "arc-line-tangent"); break;
case Type::CUBIC_LINE_TANGENT: s = "cubic-line-tangent"; break; case Type::CUBIC_LINE_TANGENT: s = C_("constr-name", "cubic-line-tangent"); break;
case Type::CURVE_CURVE_TANGENT: s = "curve-curve-tangent"; break; case Type::CURVE_CURVE_TANGENT: s = C_("constr-name", "curve-curve-tangent"); break;
case Type::PERPENDICULAR: s = "perpendicular"; break; case Type::PERPENDICULAR: s = C_("constr-name", "perpendicular"); break;
case Type::EQUAL_RADIUS: s = "eq-radius"; break; case Type::EQUAL_RADIUS: s = C_("constr-name", "eq-radius"); break;
case Type::EQUAL_ANGLE: s = "eq-angle"; break; case Type::EQUAL_ANGLE: s = C_("constr-name", "eq-angle"); break;
case Type::EQUAL_LINE_ARC_LEN: s = "eq-line-len-arc-len"; break; case Type::EQUAL_LINE_ARC_LEN: s = C_("constr-name", "eq-line-len-arc-len"); break;
case Type::WHERE_DRAGGED: s = "lock-where-dragged"; break; case Type::WHERE_DRAGGED: s = C_("constr-name", "lock-where-dragged"); break;
case Type::COMMENT: s = "comment"; break; case Type::COMMENT: s = C_("constr-name", "comment"); break;
default: s = "???"; break; default: s = "???"; break;
} }
return ssprintf("c%03x-%s", h.v, s); return ssprintf("c%03x-%s", h.v, s.c_str());
} }
#ifndef LIBRARY #ifndef LIBRARY
@ -156,16 +156,15 @@ void Constraint::MenuConstrain(Command id) {
c.type = Type::DIAMETER; c.type = Type::DIAMETER;
c.entityA = gs.entity[0]; c.entityA = gs.entity[0];
} else { } else {
Error( Error(_("Bad selection for distance / diameter constraint. This "
"Bad selection for distance / diameter constraint. This " "constraint can apply to:\n\n"
"constraint can apply to:\n\n" " * two points (distance between points)\n"
" * two points (distance between points)\n" " * a line segment (length)\n"
" * a line segment (length)\n" " * two points and a line segment or normal (projected distance)\n"
" * two points and a line segment or normal (projected distance)\n" " * a workplane and a point (minimum distance)\n"
" * a workplane and a point (minimum distance)\n" " * a line segment and a point (minimum distance)\n"
" * a line segment and a point (minimum distance)\n" " * a plane face and a point (minimum distance)\n"
" * a plane face and a point (minimum distance)\n" " * a circle or an arc (diameter)\n"));
" * a circle or an arc (diameter)\n");
return; return;
} }
if(c.type == Type::PT_PT_DISTANCE || c.type == Type::PROJ_PT_DISTANCE) { if(c.type == Type::PT_PT_DISTANCE || c.type == Type::PROJ_PT_DISTANCE) {
@ -210,13 +209,13 @@ void Constraint::MenuConstrain(Command id) {
c.ptA = gs.point[0]; c.ptA = gs.point[0];
c.entityA = gs.face[0]; c.entityA = gs.face[0];
} else { } else {
Error("Bad selection for on point / curve / plane constraint. " Error(_("Bad selection for on point / curve / plane constraint. "
"This constraint can apply to:\n\n" "This constraint can apply to:\n\n"
" * two points (points coincident)\n" " * two points (points coincident)\n"
" * a point and a workplane (point in plane)\n" " * a point and a workplane (point in plane)\n"
" * a point and a line segment (point on line)\n" " * a point and a line segment (point on line)\n"
" * a point and a circle or arc (point on curve)\n" " * a point and a circle or arc (point on curve)\n"
" * a point and a plane face (point on face)\n"); " * a point and a plane face (point on face)\n"));
return; return;
} }
AddConstraint(&c); AddConstraint(&c);
@ -272,22 +271,22 @@ void Constraint::MenuConstrain(Command id) {
c.entityB = gs.entity[1]; c.entityB = gs.entity[1];
} }
} else { } else {
Error("Bad selection for equal length / radius constraint. " Error(_("Bad selection for equal length / radius constraint. "
"This constraint can apply to:\n\n" "This constraint can apply to:\n\n"
" * two line segments (equal length)\n" " * two line segments (equal length)\n"
" * two line segments and two points " " * two line segments and two points "
"(equal point-line distances)\n" "(equal point-line distances)\n"
" * a line segment and two points " " * a line segment and two points "
"(equal point-line distances)\n" "(equal point-line distances)\n"
" * a line segment, and a point and line segment " " * a line segment, and a point and line segment "
"(point-line distance equals length)\n" "(point-line distance equals length)\n"
" * four line segments or normals " " * four line segments or normals "
"(equal angle between A,B and C,D)\n" "(equal angle between A,B and C,D)\n"
" * three line segments or normals " " * three line segments or normals "
"(equal angle between A,B and B,C)\n" "(equal angle between A,B and B,C)\n"
" * two circles or arcs (equal radius)\n" " * two circles or arcs (equal radius)\n"
" * a line segment and an arc " " * a line segment and an arc "
"(line segment length equals arc length)\n"); "(line segment length equals arc length)\n"));
return; return;
} }
if(c.type == Type::EQUAL_ANGLE) { if(c.type == Type::EQUAL_ANGLE) {
@ -311,9 +310,9 @@ void Constraint::MenuConstrain(Command id) {
c.entityA = gs.entity[0]; c.entityA = gs.entity[0];
c.entityB = gs.entity[1]; c.entityB = gs.entity[1];
} else { } else {
Error("Bad selection for length ratio constraint. This " Error(_("Bad selection for length ratio constraint. This "
"constraint can apply to:\n\n" "constraint can apply to:\n\n"
" * two line segments\n"); " * two line segments\n"));
return; return;
} }
@ -328,9 +327,9 @@ void Constraint::MenuConstrain(Command id) {
c.entityA = gs.entity[0]; c.entityA = gs.entity[0];
c.entityB = gs.entity[1]; c.entityB = gs.entity[1];
} else { } else {
Error("Bad selection for length difference constraint. This " Error(_("Bad selection for length difference constraint. This "
"constraint can apply to:\n\n" "constraint can apply to:\n\n"
" * two line segments\n"); " * two line segments\n"));
return; return;
} }
@ -354,12 +353,12 @@ void Constraint::MenuConstrain(Command id) {
c.entityA = gs.entity[i]; c.entityA = gs.entity[i];
c.entityB = gs.entity[1-i]; c.entityB = gs.entity[1-i];
} else { } else {
Error("Bad selection for at midpoint constraint. This " Error(_("Bad selection for at midpoint constraint. This "
"constraint can apply to:\n\n" "constraint can apply to:\n\n"
" * a line segment and a point " " * a line segment and a point "
"(point at midpoint)\n" "(point at midpoint)\n"
" * a line segment and a workplane " " * a line segment and a workplane "
"(line's midpoint on plane)\n"); "(line's midpoint on plane)\n"));
return; return;
} }
AddConstraint(&c); AddConstraint(&c);
@ -412,22 +411,22 @@ void Constraint::MenuConstrain(Command id) {
c.entityA = gs.entity[0]; c.entityA = gs.entity[0];
c.type = Type::SYMMETRIC_LINE; c.type = Type::SYMMETRIC_LINE;
} else { } else {
Error("Bad selection for symmetric constraint. This constraint " Error(_("Bad selection for symmetric constraint. This constraint "
"can apply to:\n\n" "can apply to:\n\n"
" * two points or a line segment " " * two points or a line segment "
"(symmetric about workplane's coordinate axis)\n" "(symmetric about workplane's coordinate axis)\n"
" * line segment, and two points or a line segment " " * line segment, and two points or a line segment "
"(symmetric about line segment)\n" "(symmetric about line segment)\n"
" * workplane, and two points or a line segment " " * workplane, and two points or a line segment "
"(symmetric about workplane)\n"); "(symmetric about workplane)\n"));
return; return;
} }
if(c.entityA.v == Entity::NO_ENTITY.v) { if(c.entityA.v == Entity::NO_ENTITY.v) {
// Horizontal / vertical symmetry, implicit symmetry plane // Horizontal / vertical symmetry, implicit symmetry plane
// normal to the workplane // normal to the workplane
if(c.workplane.v == Entity::FREE_IN_3D.v) { if(c.workplane.v == Entity::FREE_IN_3D.v) {
Error("A workplane must be active when constraining " Error(_("A workplane must be active when constraining "
"symmetric without an explicit symmetry plane."); "symmetric without an explicit symmetry plane."));
return; return;
} }
Vector pa = SK.GetEntity(c.ptA)->PointGetNum(); Vector pa = SK.GetEntity(c.ptA)->PointGetNum();
@ -456,8 +455,8 @@ void Constraint::MenuConstrain(Command id) {
case Command::HORIZONTAL: { case Command::HORIZONTAL: {
hEntity ha, hb; hEntity ha, hb;
if(c.workplane.v == Entity::FREE_IN_3D.v) { if(c.workplane.v == Entity::FREE_IN_3D.v) {
Error("Activate a workplane (with Sketch -> In Workplane) before " Error(_("Activate a workplane (with Sketch -> In Workplane) before "
"applying a horizontal or vertical constraint."); "applying a horizontal or vertical constraint."));
return; return;
} }
if(gs.lineSegments == 1 && gs.n == 1) { if(gs.lineSegments == 1 && gs.n == 1) {
@ -469,10 +468,10 @@ void Constraint::MenuConstrain(Command id) {
ha = c.ptA = gs.point[0]; ha = c.ptA = gs.point[0];
hb = c.ptB = gs.point[1]; hb = c.ptB = gs.point[1];
} else { } else {
Error("Bad selection for horizontal / vertical constraint. " Error(_("Bad selection for horizontal / vertical constraint. "
"This constraint can apply to:\n\n" "This constraint can apply to:\n\n"
" * two points\n" " * two points\n"
" * a line segment\n"); " * a line segment\n"));
return; return;
} }
if(id == Command::HORIZONTAL) { if(id == Command::HORIZONTAL) {
@ -490,9 +489,9 @@ void Constraint::MenuConstrain(Command id) {
c.entityA = gs.anyNormal[0]; c.entityA = gs.anyNormal[0];
c.entityB = gs.anyNormal[1]; c.entityB = gs.anyNormal[1];
} else { } else {
Error("Bad selection for same orientation constraint. This " Error(_("Bad selection for same orientation constraint. This "
"constraint can apply to:\n\n" "constraint can apply to:\n\n"
" * two normals\n"); " * two normals\n"));
return; return;
} }
SS.UndoRemember(); SS.UndoRemember();
@ -542,7 +541,7 @@ void Constraint::MenuConstrain(Command id) {
break; break;
} }
} }
Error("Must select an angle constraint."); Error(_("Must select an angle constraint."));
return; return;
case Command::REFERENCE: case Command::REFERENCE:
@ -554,7 +553,7 @@ void Constraint::MenuConstrain(Command id) {
break; break;
} }
} }
Error("Must select a constraint with associated label."); Error(_("Must select a constraint with associated label."));
return; return;
case Command::ANGLE: case Command::ANGLE:
@ -565,11 +564,11 @@ void Constraint::MenuConstrain(Command id) {
c.entityB = gs.vector[1]; c.entityB = gs.vector[1];
c.valA = 0; c.valA = 0;
} else { } else {
Error("Bad selection for angle constraint. This constraint " Error(_("Bad selection for angle constraint. This constraint "
"can apply to:\n\n" "can apply to:\n\n"
" * two line segments\n" " * two line segments\n"
" * a line segment and a normal\n" " * a line segment and a normal\n"
" * two normals\n"); " * two normals\n"));
return; return;
} }
@ -622,9 +621,9 @@ void Constraint::MenuConstrain(Command id) {
} else if(l0.Equals(a2) || l1.Equals(a2)) { } else if(l0.Equals(a2) || l1.Equals(a2)) {
c.other = true; c.other = true;
} else { } else {
Error("The tangent arc and line segment must share an " Error(_("The tangent arc and line segment must share an "
"endpoint. Constrain them with Constrain -> " "endpoint. Constrain them with Constrain -> "
"On Point before constraining tangent."); "On Point before constraining tangent."));
return; return;
} }
c.type = Type::ARC_LINE_TANGENT; c.type = Type::ARC_LINE_TANGENT;
@ -646,9 +645,9 @@ void Constraint::MenuConstrain(Command id) {
} else if(l0.Equals(af) || l1.Equals(af)) { } else if(l0.Equals(af) || l1.Equals(af)) {
c.other = true; c.other = true;
} else { } else {
Error("The tangent cubic and line segment must share an " Error(_("The tangent cubic and line segment must share an "
"endpoint. Constrain them with Constrain -> " "endpoint. Constrain them with Constrain -> "
"On Point before constraining tangent."); "On Point before constraining tangent."));
return; return;
} }
c.type = Type::CUBIC_LINE_TANGENT; c.type = Type::CUBIC_LINE_TANGENT;
@ -656,7 +655,7 @@ void Constraint::MenuConstrain(Command id) {
c.entityB = line->h; c.entityB = line->h;
} else if(gs.cubics + gs.arcs == 2 && gs.n == 2) { } else if(gs.cubics + gs.arcs == 2 && gs.n == 2) {
if(!SS.GW.LockedInWorkplane()) { if(!SS.GW.LockedInWorkplane()) {
Error("Curve-curve tangency must apply in workplane."); Error(_("Curve-curve tangency must apply in workplane."));
return; return;
} }
Entity *eA = SK.GetEntity(gs.entity[0]), Entity *eA = SK.GetEntity(gs.entity[0]),
@ -674,22 +673,22 @@ void Constraint::MenuConstrain(Command id) {
} else if(af.Equals(bf)) { } else if(af.Equals(bf)) {
c.other = true; c.other2 = true; c.other = true; c.other2 = true;
} else { } else {
Error("The curves must share an endpoint. Constrain them " Error(_("The curves must share an endpoint. Constrain them "
"with Constrain -> On Point before constraining " "with Constrain -> On Point before constraining "
"tangent."); "tangent."));
return; return;
} }
c.type = Type::CURVE_CURVE_TANGENT; c.type = Type::CURVE_CURVE_TANGENT;
c.entityA = eA->h; c.entityA = eA->h;
c.entityB = eB->h; c.entityB = eB->h;
} else { } else {
Error("Bad selection for parallel / tangent constraint. This " Error(_("Bad selection for parallel / tangent constraint. This "
"constraint can apply to:\n\n" "constraint can apply to:\n\n"
" * two line segments (parallel)\n" " * two line segments (parallel)\n"
" * a line segment and a normal (parallel)\n" " * a line segment and a normal (parallel)\n"
" * two normals (parallel)\n" " * two normals (parallel)\n"
" * two line segments, arcs, or beziers, that share " " * two line segments, arcs, or beziers, that share "
"an endpoint (tangent)\n"); "an endpoint (tangent)\n"));
return; return;
} }
AddConstraint(&c); AddConstraint(&c);
@ -701,11 +700,11 @@ void Constraint::MenuConstrain(Command id) {
c.entityA = gs.vector[0]; c.entityA = gs.vector[0];
c.entityB = gs.vector[1]; c.entityB = gs.vector[1];
} else { } else {
Error("Bad selection for perpendicular constraint. This " Error(_("Bad selection for perpendicular constraint. This "
"constraint can apply to:\n\n" "constraint can apply to:\n\n"
" * two line segments\n" " * two line segments\n"
" * a line segment and a normal\n" " * a line segment and a normal\n"
" * two normals\n"); " * two normals\n"));
return; return;
} }
AddConstraint(&c); AddConstraint(&c);
@ -716,9 +715,9 @@ void Constraint::MenuConstrain(Command id) {
c.type = Type::WHERE_DRAGGED; c.type = Type::WHERE_DRAGGED;
c.ptA = gs.point[0]; c.ptA = gs.point[0];
} else { } else {
Error("Bad selection for lock point where dragged constraint. " Error(_("Bad selection for lock point where dragged constraint. "
"This constraint can apply to:\n\n" "This constraint can apply to:\n\n"
" * a point\n"); " * a point\n"));
return; return;
} }
AddConstraint(&c); AddConstraint(&c);
@ -727,7 +726,7 @@ void Constraint::MenuConstrain(Command id) {
case Command::COMMENT: case Command::COMMENT:
SS.GW.pending.operation = GraphicsWindow::Pending::COMMAND; SS.GW.pending.operation = GraphicsWindow::Pending::COMMAND;
SS.GW.pending.command = Command::COMMENT; SS.GW.pending.command = Command::COMMENT;
SS.GW.pending.description = "click center of comment text"; SS.GW.pending.description = _("click center of comment text");
SS.ScheduleShowTW(); SS.ScheduleShowTW();
break; break;

View File

@ -15,8 +15,8 @@ void SolveSpaceUI::ExportSectionTo(const std::string &filename) {
Group *g = SK.GetGroup(SS.GW.activeGroup); Group *g = SK.GetGroup(SS.GW.activeGroup);
g->GenerateDisplayItems(); g->GenerateDisplayItems();
if(g->displayMesh.IsEmpty()) { if(g->displayMesh.IsEmpty()) {
Error("No solid model present; draw one with extrudes and revolves, " Error(_("No solid model present; draw one with extrudes and revolves, "
"or use Export 2d View to export bare lines and curves."); "or use Export 2d View to export bare lines and curves."));
return; return;
} }
@ -57,12 +57,12 @@ void SolveSpaceUI::ExportSectionTo(const std::string &filename) {
u = ut.WithMagnitude(1); u = ut.WithMagnitude(1);
v = (n.Cross(u)).WithMagnitude(1); v = (n.Cross(u)).WithMagnitude(1);
} else { } else {
Error("Bad selection for export section. Please select:\n\n" Error(_("Bad selection for export section. Please select:\n\n"
" * nothing, with an active workplane " " * nothing, with an active workplane "
"(workplane is section plane)\n" "(workplane is section plane)\n"
" * a face (section plane through face)\n" " * a face (section plane through face)\n"
" * a point and two line segments " " * a point and two line segments "
"(plane through point and parallel to lines)\n"); "(plane through point and parallel to lines)\n"));
return; return;
} }
SS.GW.ClearSelection(); SS.GW.ClearSelection();
@ -802,7 +802,7 @@ void SolveSpaceUI::ExportMeshTo(const std::string &filename) {
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh); SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
if(m->IsEmpty()) { if(m->IsEmpty()) {
Error("Active group mesh is empty; nothing to export."); Error(_("Active group mesh is empty; nothing to export."));
return; return;
} }

View File

@ -327,9 +327,9 @@ public:
entity->setWidthMm(Style::WidthMm(hs.v)); entity->setWidthMm(Style::WidthMm(hs.v));
if(s->stippleType == StipplePattern::FREEHAND) { if(s->stippleType == StipplePattern::FREEHAND) {
messages.insert("freehand lines were replaced with continuous lines"); messages.insert(_("freehand lines were replaced with continuous lines"));
} else if(s->stippleType == StipplePattern::ZIGZAG) { } else if(s->stippleType == StipplePattern::ZIGZAG) {
messages.insert("zigzag lines were replaced with continuous lines"); messages.insert(_("zigzag lines were replaced with continuous lines"));
} }
} }
@ -580,8 +580,8 @@ void DxfFileWriter::FinishAndCloseFile() {
} }
if(!interface.messages.empty()) { if(!interface.messages.empty()) {
std::string text = "Some aspects of the drawing have no DXF equivalent and " std::string text = _("Some aspects of the drawing have no DXF equivalent and "
"were not exported:\n"; "were not exported:\n");
for(const std::string &message : interface.messages) { for(const std::string &message : interface.messages) {
text += " * " + message + "\n"; text += " * " + message + "\n";
} }
@ -797,8 +797,8 @@ void PdfFileWriter::StartFile() {
if((ptMax.x - ptMin.x) > 200*25.4 || if((ptMax.x - ptMin.x) > 200*25.4 ||
(ptMax.y - ptMin.y) > 200*25.4) (ptMax.y - ptMin.y) > 200*25.4)
{ {
Message("PDF page size exceeds 200 by 200 inches; many viewers may " Message(_("PDF page size exceeds 200 by 200 inches; many viewers may "
"reject this file."); "reject this file."));
} }
fprintf(f, fprintf(f,

View File

@ -40,7 +40,7 @@ hGroup SolveSpaceUI::CreateDefaultDrawingGroup() {
// And an empty group, for the first stuff the user draws. // And an empty group, for the first stuff the user draws.
g.visible = true; g.visible = true;
g.name = "sketch-in-plane"; g.name = C_("group-name", "sketch-in-plane");
g.type = Group::Type::DRAWING_WORKPLANE; g.type = Group::Type::DRAWING_WORKPLANE;
g.subtype = Group::Subtype::WORKPLANE_BY_POINT_ORTHO; g.subtype = Group::Subtype::WORKPLANE_BY_POINT_ORTHO;
g.order = 1; g.order = 1;
@ -58,7 +58,7 @@ void SolveSpaceUI::NewFile() {
// Our initial group, that contains the references. // Our initial group, that contains the references.
Group g = {}; Group g = {};
g.visible = true; g.visible = true;
g.name = "#references"; g.name = C_("group-name", "#references");
g.type = Group::Type::DRAWING_3D; g.type = Group::Type::DRAWING_3D;
g.order = 0; g.order = 0;
g.h = Group::HGROUP_REFERENCES; g.h = Group::HGROUP_REFERENCES;
@ -505,8 +505,8 @@ bool SolveSpaceUI::LoadFromFile(const std::string &filename, bool canCancel) {
fclose(fh); fclose(fh);
if(fileLoadError) { if(fileLoadError) {
Error("Unrecognized data in file. This file may be corrupt, or " Error(_("Unrecognized data in file. This file may be corrupt, or "
"from a new version of the program."); "from a newer version of the program."));
// At least leave the program in a non-crashing state. // At least leave the program in a non-crashing state.
if(SK.group.n == 0) { if(SK.group.n == 0) {
NewFile(); NewFile();

View File

@ -489,8 +489,7 @@ void GraphicsWindow::MenuView(Command id) {
case Command::SHOW_GRID: case Command::SHOW_GRID:
SS.GW.showSnapGrid = !SS.GW.showSnapGrid; SS.GW.showSnapGrid = !SS.GW.showSnapGrid;
if(SS.GW.showSnapGrid && !SS.GW.LockedInWorkplane()) { if(SS.GW.showSnapGrid && !SS.GW.LockedInWorkplane()) {
Message("No workplane is active, so the grid will not " Message(_("No workplane is active, so the grid will not appear."));
"appear.");
} }
SS.GW.EnsureValidActives(); SS.GW.EnsureValidActives();
InvalidateGraphics(); InvalidateGraphics();
@ -499,11 +498,11 @@ void GraphicsWindow::MenuView(Command id) {
case Command::PERSPECTIVE_PROJ: case Command::PERSPECTIVE_PROJ:
SS.usePerspectiveProj = !SS.usePerspectiveProj; SS.usePerspectiveProj = !SS.usePerspectiveProj;
if(SS.cameraTangent < 1e-6) { if(SS.cameraTangent < 1e-6) {
Error("The perspective factor is set to zero, so the view will " Error(_("The perspective factor is set to zero, so the view will "
"always be a parallel projection.\n\n" "always be a parallel projection.\n\n"
"For a perspective projection, modify the perspective " "For a perspective projection, modify the perspective "
"factor in the configuration screen. A value around 0.3 " "factor in the configuration screen. A value around 0.3 "
"is typical."); "is typical."));
} }
SS.GW.EnsureValidActives(); SS.GW.EnsureValidActives();
InvalidateGraphics(); InvalidateGraphics();
@ -580,8 +579,8 @@ void GraphicsWindow::MenuView(Command id) {
SS.GW.AnimateOnto(quat0, pt.ScaledBy(-1)); SS.GW.AnimateOnto(quat0, pt.ScaledBy(-1));
SS.GW.ClearSelection(); SS.GW.ClearSelection();
} else { } else {
Error("Select a point; this point will become the center " Error(_("Select a point; this point will become the center "
"of the view on screen."); "of the view on screen."));
} }
break; break;
@ -862,8 +861,7 @@ void GraphicsWindow::MenuEdit(Command id) {
} }
} while(didSomething); } while(didSomething);
if(newlySelected == 0) { if(newlySelected == 0) {
Error("No additional entities share endpoints with the " Error(_("No additional entities share endpoints with the selected entities."));
"selected entities.");
} }
InvalidateGraphics(); InvalidateGraphics();
SS.ScheduleShowTW(); SS.ScheduleShowTW();
@ -883,9 +881,9 @@ void GraphicsWindow::MenuEdit(Command id) {
hGroup hg = e ? e->group : SS.GW.activeGroup; hGroup hg = e ? e->group : SS.GW.activeGroup;
Group *g = SK.GetGroup(hg); Group *g = SK.GetGroup(hg);
if(g->type != Group::Type::LINKED) { if(g->type != Group::Type::LINKED) {
Error("To use this command, select a point or other " Error(_("To use this command, select a point or other "
"entity from an linked part, or make a link " "entity from an linked part, or make a link "
"group the active group."); "group the active group."));
break; break;
} }
@ -907,16 +905,16 @@ void GraphicsWindow::MenuEdit(Command id) {
case Command::SNAP_TO_GRID: { case Command::SNAP_TO_GRID: {
if(!SS.GW.LockedInWorkplane()) { if(!SS.GW.LockedInWorkplane()) {
Error("No workplane is active. Activate a workplane " Error(_("No workplane is active. Activate a workplane "
"(with Sketch -> In Workplane) to define the plane " "(with Sketch -> In Workplane) to define the plane "
"for the snap grid."); "for the snap grid."));
break; break;
} }
SS.GW.GroupSelection(); SS.GW.GroupSelection();
if(SS.GW.gs.points == 0 && SS.GW.gs.constraintLabels == 0) { if(SS.GW.gs.points == 0 && SS.GW.gs.constraintLabels == 0) {
Error("Can't snap these items to grid; select points, " Error(_("Can't snap these items to grid; select points, "
"text comments, or constraints with a label. " "text comments, or constraints with a label. "
"To snap a line, select its endpoints."); "To snap a line, select its endpoints."));
break; break;
} }
SS.UndoRemember(); SS.UndoRemember();
@ -979,15 +977,15 @@ void GraphicsWindow::MenuRequest(Command id) {
} else if(g->type == Group::Type::DRAWING_WORKPLANE) { } else if(g->type == Group::Type::DRAWING_WORKPLANE) {
// The group's default workplane // The group's default workplane
g->activeWorkplane = g->h.entity(0); g->activeWorkplane = g->h.entity(0);
Message("No workplane selected. Activating default workplane " Message(_("No workplane selected. Activating default workplane "
"for this group."); "for this group."));
} }
if(!SS.GW.LockedInWorkplane()) { if(!SS.GW.LockedInWorkplane()) {
Error("No workplane is selected, and the active group does " Error(_("No workplane is selected, and the active group does "
"not have a default workplane. Try selecting a " "not have a default workplane. Try selecting a "
"workplane, or activating a sketch-in-new-workplane " "workplane, or activating a sketch-in-new-workplane "
"group."); "group."));
break; break;
} }
// Align the view with the selected workplane // Align the view with the selected workplane
@ -1008,9 +1006,9 @@ void GraphicsWindow::MenuRequest(Command id) {
if(SS.GW.gs.n == 1 && SS.GW.gs.points == 1) { if(SS.GW.gs.n == 1 && SS.GW.gs.points == 1) {
SS.GW.MakeTangentArc(); SS.GW.MakeTangentArc();
} else if(SS.GW.gs.n != 0) { } else if(SS.GW.gs.n != 0) {
Error("Bad selection for tangent arc at point. Select a " Error(_("Bad selection for tangent arc at point. Select a "
"single point, or select nothing to set up arc " "single point, or select nothing to set up arc "
"parameters."); "parameters."));
} else { } else {
SS.TW.GoToScreen(TextWindow::Screen::TANGENT_ARC); SS.TW.GoToScreen(TextWindow::Screen::TANGENT_ARC);
SS.GW.ForceTextWindowShown(); SS.GW.ForceTextWindowShown();
@ -1019,15 +1017,16 @@ void GraphicsWindow::MenuRequest(Command id) {
} }
break; break;
case Command::ARC: s = "click point on arc (draws anti-clockwise)"; goto c; case Command::ARC: s = _("click point on arc (draws anti-clockwise)"); goto c;
case Command::DATUM_POINT: s = "click to place datum point"; goto c; case Command::DATUM_POINT: s = _("click to place datum point"); goto c;
case Command::LINE_SEGMENT: s = "click first point of line segment"; goto c; case Command::LINE_SEGMENT: s = _("click first point of line segment"); goto c;
case Command::CONSTR_SEGMENT: s = "click first point of construction line segment"; goto c; case Command::CONSTR_SEGMENT:
case Command::CUBIC: s = "click first point of cubic segment"; goto c; s = _("click first point of construction line segment"); goto c;
case Command::CIRCLE: s = "click center of circle"; goto c; case Command::CUBIC: s = _("click first point of cubic segment"); goto c;
case Command::WORKPLANE: s = "click origin of workplane"; goto c; case Command::CIRCLE: s = _("click center of circle"); goto c;
case Command::RECTANGLE: s = "click one corner of rectangle"; goto c; case Command::WORKPLANE: s = _("click origin of workplane"); goto c;
case Command::TTF_TEXT: s = "click top left of text"; goto c; case Command::RECTANGLE: s = _("click one corner of rectangle"); goto c;
case Command::TTF_TEXT: s = _("click top left of text"); goto c;
c: c:
SS.GW.pending.operation = GraphicsWindow::Pending::COMMAND; SS.GW.pending.operation = GraphicsWindow::Pending::COMMAND;
SS.GW.pending.command = id; SS.GW.pending.command = id;
@ -1040,8 +1039,8 @@ c:
SS.UndoRemember(); SS.UndoRemember();
SS.GW.GroupSelection(); SS.GW.GroupSelection();
if(SS.GW.gs.entities == 0) { if(SS.GW.gs.entities == 0) {
Error("No entities are selected. Select entities before " Error(_("No entities are selected. Select entities before "
"trying to toggle their construction state."); "trying to toggle their construction state."));
} }
int i; int i;
for(i = 0; i < SS.GW.gs.entities; i++) { for(i = 0; i < SS.GW.gs.entities; i++) {

View File

@ -86,12 +86,12 @@ void Group::MenuGroup(Command id) {
switch(id) { switch(id) {
case Command::GROUP_3D: case Command::GROUP_3D:
g.type = Type::DRAWING_3D; g.type = Type::DRAWING_3D;
g.name = "sketch-in-3d"; g.name = C_("group-name", "sketch-in-3d");
break; break;
case Command::GROUP_WRKPL: case Command::GROUP_WRKPL:
g.type = Type::DRAWING_WORKPLANE; g.type = Type::DRAWING_WORKPLANE;
g.name = "sketch-in-plane"; g.name = C_("group-name", "sketch-in-plane");
if(gs.points == 1 && gs.n == 1) { if(gs.points == 1 && gs.n == 1) {
g.subtype = Subtype::WORKPLANE_BY_POINT_ORTHO; g.subtype = Subtype::WORKPLANE_BY_POINT_ORTHO;
@ -142,28 +142,28 @@ void Group::MenuGroup(Command id) {
} else ssassert(false, "Unexpected workplane subtype"); } else ssassert(false, "Unexpected workplane subtype");
} }
} else { } else {
Error("Bad selection for new sketch in workplane. This " Error(_("Bad selection for new sketch in workplane. This "
"group can be created with:\n\n" "group can be created with:\n\n"
" * a point (through the point, orthogonal to coordinate axes)\n" " * a point (through the point, orthogonal to coordinate axes)\n"
" * a point and two line segments (through the point, " " * a point and two line segments (through the point, "
"parallel to the lines)\n" "parallel to the lines)\n"
" * a workplane (copy of the workplane)\n"); " * a workplane (copy of the workplane)\n"));
return; return;
} }
break; break;
case Command::GROUP_EXTRUDE: case Command::GROUP_EXTRUDE:
if(!SS.GW.LockedInWorkplane()) { if(!SS.GW.LockedInWorkplane()) {
Error("Activate a workplane (Sketch -> In Workplane) before " Error(_("Activate a workplane (Sketch -> In Workplane) before "
"extruding. The sketch will be extruded normal to the " "extruding. The sketch will be extruded normal to the "
"workplane."); "workplane."));
return; return;
} }
g.type = Type::EXTRUDE; g.type = Type::EXTRUDE;
g.opA = SS.GW.activeGroup; g.opA = SS.GW.activeGroup;
g.predef.entityB = SS.GW.ActiveWorkplane(); g.predef.entityB = SS.GW.ActiveWorkplane();
g.subtype = Subtype::ONE_SIDED; g.subtype = Subtype::ONE_SIDED;
g.name = "extrude"; g.name = C_("group-name", "extrude");
break; break;
case Command::GROUP_LATHE: case Command::GROUP_LATHE:
@ -175,17 +175,17 @@ void Group::MenuGroup(Command id) {
g.predef.entityB = gs.entity[0]; g.predef.entityB = gs.entity[0];
// since a line segment is a vector // since a line segment is a vector
} else { } else {
Error("Bad selection for new lathe group. This group can " Error(_("Bad selection for new lathe group. This group can "
"be created with:\n\n" "be created with:\n\n"
" * a point and a line segment or normal " " * a point and a line segment or normal "
"(revolved about an axis parallel to line / " "(revolved about an axis parallel to line / "
"normal, through point)\n" "normal, through point)\n"
" * a line segment (revolved about line segment)\n"); " * a line segment (revolved about line segment)\n"));
return; return;
} }
g.type = Type::LATHE; g.type = Type::LATHE;
g.opA = SS.GW.activeGroup; g.opA = SS.GW.activeGroup;
g.name = "lathe"; g.name = C_("group-name", "lathe");
break; break;
case Command::GROUP_ROT: { case Command::GROUP_ROT: {
@ -198,20 +198,20 @@ void Group::MenuGroup(Command id) {
g.predef.origin = gs.point[0]; g.predef.origin = gs.point[0];
g.predef.entityB = gs.vector[0]; g.predef.entityB = gs.vector[0];
} else { } else {
Error("Bad selection for new rotation. This group can " Error(_("Bad selection for new rotation. This group can "
"be created with:\n\n" "be created with:\n\n"
" * a point, while locked in workplane (rotate " " * a point, while locked in workplane (rotate "
"in plane, about that point)\n" "in plane, about that point)\n"
" * a point and a line or a normal (rotate about " " * a point and a line or a normal (rotate about "
"an axis through the point, and parallel to " "an axis through the point, and parallel to "
"line / normal)\n"); "line / normal)\n"));
return; return;
} }
g.type = Type::ROTATE; g.type = Type::ROTATE;
g.opA = SS.GW.activeGroup; g.opA = SS.GW.activeGroup;
g.valA = 3; g.valA = 3;
g.subtype = Subtype::ONE_SIDED; g.subtype = Subtype::ONE_SIDED;
g.name = "rotate"; g.name = C_("group-name", "rotate");
break; break;
} }
@ -222,7 +222,7 @@ void Group::MenuGroup(Command id) {
g.subtype = Subtype::ONE_SIDED; g.subtype = Subtype::ONE_SIDED;
g.predef.entityB = SS.GW.ActiveWorkplane(); g.predef.entityB = SS.GW.ActiveWorkplane();
g.activeWorkplane = SS.GW.ActiveWorkplane(); g.activeWorkplane = SS.GW.ActiveWorkplane();
g.name = "translate"; g.name = C_("group-name", "translate");
break; break;
case Command::GROUP_LINK: { case Command::GROUP_LINK: {
@ -254,7 +254,7 @@ void Group::MenuGroup(Command id) {
if(groupName.length() > 0) { if(groupName.length() > 0) {
g.name = groupName; g.name = groupName;
} else { } else {
g.name = "link"; g.name = C_("group-name", "link");
} }
g.meshCombine = CombineAs::ASSEMBLE; g.meshCombine = CombineAs::ASSEMBLE;
@ -336,7 +336,7 @@ void Group::TransformImportedBy(Vector t, Quaternion q) {
std::string Group::DescriptionString() { std::string Group::DescriptionString() {
if(name.empty()) { if(name.empty()) {
return ssprintf("g%03x-(unnamed)", h.v); return ssprintf("g%03x-%s", h.v, _("(unnamed)"));
} else { } else {
return ssprintf("g%03x-%s", h.v, name.c_str()); return ssprintf("g%03x-%s", h.v, name.c_str());
} }

View File

@ -604,7 +604,8 @@ void Group::DrawPolyError(Canvas *canvas) {
// Report this error only in sketch-in-workplane groups; otherwise // Report this error only in sketch-in-workplane groups; otherwise
// it's just a nuisance. // it's just a nuisance.
if(type == Type::DRAWING_WORKPLANE) { if(type == Type::DRAWING_WORKPLANE) {
canvas->DrawVectorText("not closed contour, or not all same style!", textHeight, canvas->DrawVectorText(_("not closed contour, or not all same style!"),
textHeight,
polyError.notClosedAt.b, camera.projRight, camera.projUp, polyError.notClosedAt.b, camera.projRight, camera.projUp,
hcsError); hcsError);
canvas->DrawLine(polyError.notClosedAt.a, polyError.notClosedAt.b, hcsUnclosed); canvas->DrawLine(polyError.notClosedAt.a, polyError.notClosedAt.b, hcsUnclosed);
@ -616,11 +617,11 @@ void Group::DrawPolyError(Canvas *canvas) {
if(type == Type::DRAWING_WORKPLANE) { if(type == Type::DRAWING_WORKPLANE) {
const char *msg; const char *msg;
if(polyError.how == PolyError::NOT_COPLANAR) { if(polyError.how == PolyError::NOT_COPLANAR) {
msg = "points not all coplanar!"; msg = _("points not all coplanar!");
} else if(polyError.how == PolyError::SELF_INTERSECTING) { } else if(polyError.how == PolyError::SELF_INTERSECTING) {
msg = "contour is self-intersecting!"; msg = _("contour is self-intersecting!");
} else { } else {
msg = "zero-length edge!"; msg = _("zero-length edge!");
} }
canvas->DrawVectorText(msg, textHeight, canvas->DrawVectorText(msg, textHeight,
polyError.errorPointAt, camera.projRight, camera.projUp, polyError.errorPointAt, camera.projRight, camera.projUp,

View File

@ -234,8 +234,7 @@ void GraphicsWindow::ParametricCurve::ConstrainPointIfCoincident(hEntity hpt) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void GraphicsWindow::MakeTangentArc() { void GraphicsWindow::MakeTangentArc() {
if(!LockedInWorkplane()) { if(!LockedInWorkplane()) {
Error("Must be sketching in workplane to create tangent " Error(_("Must be sketching in workplane to create tangent arc."));
"arc.");
return; return;
} }
@ -282,9 +281,9 @@ void GraphicsWindow::MakeTangentArc() {
} }
} }
if(c != 2) { if(c != 2) {
Error("To create a tangent arc, select a point where two " Error(_("To create a tangent arc, select a point where two "
"non-construction lines or circles in this group and " "non-construction lines or circles in this group and "
"workplane join."); "workplane join."));
return; return;
} }
@ -369,9 +368,9 @@ void GraphicsWindow::MakeTangentArc() {
t[0] > 0.99 || t[1] > 0.99 || t[0] > 0.99 || t[1] > 0.99 ||
isnan(t[0]) || isnan(t[1])) isnan(t[0]) || isnan(t[1]))
{ {
Error("Couldn't round this corner. Try a smaller radius, or try " Error(_("Couldn't round this corner. Try a smaller radius, or try "
"creating the desired geometry by hand with tangency " "creating the desired geometry by hand with tangency "
"constraints."); "constraints."));
return; return;
} }
@ -573,7 +572,7 @@ hEntity GraphicsWindow::SplitEntity(hEntity he, Vector pinter) {
} else if(e->type == Entity::Type::CUBIC || e->type == Entity::Type::CUBIC_PERIODIC) { } else if(e->type == Entity::Type::CUBIC || e->type == Entity::Type::CUBIC_PERIODIC) {
ret = SplitCubic(he, pinter); ret = SplitCubic(he, pinter);
} else { } else {
Error("Couldn't split this entity; lines, circles, or cubics only."); Error(_("Couldn't split this entity; lines, circles, or cubics only."));
return Entity::NO_ENTITY; return Entity::NO_ENTITY;
} }
@ -599,7 +598,7 @@ hEntity GraphicsWindow::SplitEntity(hEntity he, Vector pinter) {
void GraphicsWindow::SplitLinesOrCurves() { void GraphicsWindow::SplitLinesOrCurves() {
if(!LockedInWorkplane()) { if(!LockedInWorkplane()) {
Error("Must be sketching in workplane to split."); Error(_("Must be sketching in workplane to split."));
return; return;
} }
@ -609,8 +608,8 @@ void GraphicsWindow::SplitLinesOrCurves() {
gs.cubics + gs.cubics +
gs.periodicCubics) == 2)) gs.periodicCubics) == 2))
{ {
Error("Select two entities that intersect each other (e.g. two lines " Error(_("Select two entities that intersect each other (e.g. two lines "
"or two circles or a circle and a line)."); "or two circles or a circle and a line)."));
return; return;
} }
@ -653,7 +652,7 @@ void GraphicsWindow::SplitLinesOrCurves() {
Constraint::ConstrainCoincident(hia, hib); Constraint::ConstrainCoincident(hia, hib);
} }
} else { } else {
Error("Can't split; no intersection found."); Error(_("Can't split; no intersection found."));
} }
// All done, clean up and regenerate. // All done, clean up and regenerate.

View File

@ -775,7 +775,7 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
SS.MarkGroupDirtyByEntity(gs.entity[0]); SS.MarkGroupDirtyByEntity(gs.entity[0]);
ClearSelection(); ClearSelection();
} else { } else {
Error("Cannot add spline point: maximum number of points reached."); Error(_("Cannot add spline point: maximum number of points reached."));
} }
break; break;
} }
@ -945,14 +945,14 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
pending.operation = Pending::DRAGGING_NEW_LINE_POINT; pending.operation = Pending::DRAGGING_NEW_LINE_POINT;
pending.request = hr; pending.request = hr;
pending.point = hr.entity(2); pending.point = hr.entity(2);
pending.description = "click next point of line, or press Esc"; pending.description = _("click next point of line, or press Esc");
SK.GetEntity(pending.point)->PointForceTo(v); SK.GetEntity(pending.point)->PointForceTo(v);
break; break;
case Command::RECTANGLE: { case Command::RECTANGLE: {
if(!SS.GW.LockedInWorkplane()) { if(!SS.GW.LockedInWorkplane()) {
Error("Can't draw rectangle in 3d; first, activate a workplane " Error(_("Can't draw rectangle in 3d; first, activate a workplane "
"with Sketch -> In Workplane."); "with Sketch -> In Workplane."));
ClearSuper(); ClearSuper();
break; break;
} }
@ -978,7 +978,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
pending.operation = Pending::DRAGGING_NEW_POINT; pending.operation = Pending::DRAGGING_NEW_POINT;
pending.point = lns[1].entity(2); pending.point = lns[1].entity(2);
pending.description = "click to place other corner of rectangle"; pending.description = _("click to place other corner of rectangle");
hr = lns[0]; hr = lns[0];
break; break;
} }
@ -998,13 +998,13 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
pending.operation = Pending::DRAGGING_NEW_RADIUS; pending.operation = Pending::DRAGGING_NEW_RADIUS;
pending.circle = hr.entity(0); pending.circle = hr.entity(0);
pending.description = "click to set radius"; pending.description = _("click to set radius");
break; break;
case Command::ARC: { case Command::ARC: {
if(!SS.GW.LockedInWorkplane()) { if(!SS.GW.LockedInWorkplane()) {
Error("Can't draw arc in 3d; first, activate a workplane " Error(_("Can't draw arc in 3d; first, activate a workplane "
"with Sketch -> In Workplane."); "with Sketch -> In Workplane."));
ClearPending(); ClearPending();
break; break;
} }
@ -1021,7 +1021,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
pending.operation = Pending::DRAGGING_NEW_ARC_POINT; pending.operation = Pending::DRAGGING_NEW_ARC_POINT;
pending.point = hr.entity(3); pending.point = hr.entity(3);
pending.description = "click to place point"; pending.description = _("click to place point");
break; break;
} }
case Command::CUBIC: case Command::CUBIC:
@ -1036,13 +1036,13 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
pending.operation = Pending::DRAGGING_NEW_CUBIC_POINT; pending.operation = Pending::DRAGGING_NEW_CUBIC_POINT;
pending.point = hr.entity(4); pending.point = hr.entity(4);
pending.description = "click next point of cubic, or press Esc"; pending.description = _("click next point of cubic, or press Esc");
break; break;
case Command::WORKPLANE: case Command::WORKPLANE:
if(LockedInWorkplane()) { if(LockedInWorkplane()) {
Error("Sketching in a workplane already; sketch in 3d before " Error(_("Sketching in a workplane already; sketch in 3d before "
"creating new workplane."); "creating new workplane."));
ClearSuper(); ClearSuper();
break; break;
} }
@ -1057,8 +1057,8 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
case Command::TTF_TEXT: { case Command::TTF_TEXT: {
if(!SS.GW.LockedInWorkplane()) { if(!SS.GW.LockedInWorkplane()) {
Error("Can't draw text in 3d; first, activate a workplane " Error(_("Can't draw text in 3d; first, activate a workplane "
"with Sketch -> In Workplane."); "with Sketch -> In Workplane."));
ClearSuper(); ClearSuper();
break; break;
} }
@ -1072,7 +1072,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
pending.operation = Pending::DRAGGING_NEW_POINT; pending.operation = Pending::DRAGGING_NEW_POINT;
pending.point = hr.entity(2); pending.point = hr.entity(2);
pending.description = "click to place bottom left of text"; pending.description = _("click to place bottom left of text");
break; break;
} }
@ -1083,7 +1083,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
c.workplane = SS.GW.ActiveWorkplane(); c.workplane = SS.GW.ActiveWorkplane();
c.type = Constraint::Type::COMMENT; c.type = Constraint::Type::COMMENT;
c.disp.offset = v; c.disp.offset = v;
c.comment = "NEW COMMENT -- DOUBLE-CLICK TO EDIT"; c.comment = _("NEW COMMENT -- DOUBLE-CLICK TO EDIT");
hc = Constraint::AddConstraint(&c); hc = Constraint::AddConstraint(&c);
break; break;
} }
@ -1196,7 +1196,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
pending.operation = Pending::DRAGGING_NEW_LINE_POINT; pending.operation = Pending::DRAGGING_NEW_LINE_POINT;
pending.request = hr; pending.request = hr;
pending.point = hr.entity(2); pending.point = hr.entity(2);
pending.description = "click next point of line, or press Esc"; pending.description = _("click next point of line, or press Esc");
break; break;
} }

View File

@ -1254,6 +1254,25 @@ unsigned PluralExpr::Eval(const std::string &s, unsigned n) {
return t.value; return t.value;
} }
//-----------------------------------------------------------------------------
// Gettext message keys
//-----------------------------------------------------------------------------
class TranslationKey {
public:
bool hasContext;
std::string context;
std::string ident;
};
struct TranslationKeyLess {
bool operator()(const TranslationKey &a, const TranslationKey &b) const {
return a.hasContext < b.hasContext ||
(a.hasContext == b.hasContext && a.context < b.context) ||
(a.hasContext == b.hasContext && a.context == b.context && a.ident < b.ident);
}
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Gettext .po file parsing // Gettext .po file parsing
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1265,7 +1284,7 @@ public:
unsigned pluralCount; unsigned pluralCount;
std::string pluralExpr; std::string pluralExpr;
std::map<std::string, std::vector<std::string>> messages; std::map<TranslationKey, std::vector<std::string>, TranslationKeyLess> messages;
void SkipSpace(); void SkipSpace();
std::string ReadString(); std::string ReadString();
@ -1342,11 +1361,18 @@ void GettextParser::Parse() {
SkipSpace(); SkipSpace();
while(!reader.AtEnd()) { while(!reader.AtEnd()) {
TranslationKey key = {};
if(reader.TryString("msgctxt")) {
key.hasContext = true;
key.context = ReadString();
}
reader.ExpectString("msgid"); reader.ExpectString("msgid");
std::string msgid = ReadString(); key.ident = ReadString();
if(reader.TryString("msgid_plural")) { if(reader.TryString("msgid_plural")) {
std::string _msgid_plural = ReadString(); ReadString(); // we don't need it
// We don't need it.
} }
std::vector<std::string> msgstrs; std::vector<std::string> msgstrs;
@ -1364,7 +1390,7 @@ void GettextParser::Parse() {
} }
} }
if(msgid == "") { if(key.ident == "") {
ssassert(msgstrs.size() == 1, ssassert(msgstrs.size() == 1,
"Expected exactly one header msgstr"); "Expected exactly one header msgstr");
ParseHeader(msgstrs[0]); ParseHeader(msgstrs[0]);
@ -1372,7 +1398,7 @@ void GettextParser::Parse() {
ssassert(msgstrs.size() == 1 || ssassert(msgstrs.size() == 1 ||
msgstrs.size() == pluralCount, msgstrs.size() == pluralCount,
"Expected msgstr count to match plural form count"); "Expected msgstr count to match plural form count");
messages.emplace(msgid, msgstrs); messages.emplace(key, msgstrs);
} }
} }
} }
@ -1386,12 +1412,12 @@ public:
unsigned pluralCount; unsigned pluralCount;
std::string pluralExpr; std::string pluralExpr;
std::map<std::string, std::vector<std::string>> messages; std::map<TranslationKey, std::vector<std::string>, TranslationKeyLess> messages;
static Translation From(const std::string &poData); static Translation From(const std::string &poData);
const std::string &Translate(const char *msgid); const std::string &Translate(const TranslationKey &key);
const std::string &TranslatePlural(const char *msgid, unsigned n); const std::string &TranslatePlural(const TranslationKey &key, unsigned n);
}; };
Translation Translation::From(const std::string &poData) { Translation Translation::From(const std::string &poData) {
@ -1406,28 +1432,28 @@ Translation Translation::From(const std::string &poData) {
return trans; return trans;
} }
const std::string &Translation::Translate(const char *msgid) { const std::string &Translation::Translate(const TranslationKey &key) {
auto it = messages.find(msgid); auto it = messages.find(key);
if(it == messages.end()) { if(it == messages.end()) {
dbp("Missing translation for '%s'", msgid); dbp("Missing translation for %s'%s'", key.context.c_str(), key.ident.c_str());
messages[msgid].emplace_back(msgid); messages[key].emplace_back(key.ident);
it = messages.find(msgid); it = messages.find(key);
} }
if(it->second.size() != 1) { if(it->second.size() != 1) {
dbp("Incorrect use of translated message '%s'", msgid); dbp("Incorrect use of translated message %s'%s'", key.context.c_str(), key.ident.c_str());
ssassert(false, "Using a message with a plural form without a number"); ssassert(false, "Using a message with a plural form without a number");
} }
return it->second[0]; return it->second[0];
} }
const std::string &Translation::TranslatePlural(const char *msgid, unsigned n) { const std::string &Translation::TranslatePlural(const TranslationKey &key, unsigned n) {
auto it = messages.find(msgid); auto it = messages.find(key);
if(it == messages.end()) { if(it == messages.end()) {
dbp("Missing translation for '%s'", msgid); dbp("Missing translation for %s'%s'", key.context.c_str(), key.ident.c_str());
for(unsigned i = 0; i < pluralCount; i++) { for(unsigned i = 0; i < pluralCount; i++) {
messages[msgid].emplace_back(msgid); messages[key].emplace_back(key.ident);
} }
it = messages.find(msgid); it = messages.find(key);
} }
unsigned pluralForm = PluralExpr::Eval(pluralExpr, n); unsigned pluralForm = PluralExpr::Eval(pluralExpr, n);
return it->second[pluralForm]; return it->second[pluralForm];
@ -1501,11 +1527,31 @@ bool SetLocale(uint16_t lcid) {
} }
const std::string &Translate(const char *msgid) { const std::string &Translate(const char *msgid) {
return currentTranslation->Translate(msgid); TranslationKey key = {};
key.ident = msgid;
return currentTranslation->Translate(key);
}
const std::string &Translate(const char *msgctxt, const char *msgid) {
TranslationKey key = {};
key.hasContext = true;
key.context = msgctxt;
key.ident = msgid;
return currentTranslation->Translate(key);
} }
const std::string &TranslatePlural(const char *msgid, unsigned n) { const std::string &TranslatePlural(const char *msgid, unsigned n) {
return currentTranslation->TranslatePlural(msgid, n); TranslationKey key = {};
key.ident = msgid;
return currentTranslation->TranslatePlural(key, n);
}
const std::string &TranslatePlural(const char *msgctxt, const char *msgid, unsigned n) {
TranslationKey key = {};
key.hasContext = true;
key.context = msgctxt;
key.ident = msgid;
return currentTranslation->TranslatePlural(key, n);
} }
} }

View File

@ -476,10 +476,10 @@ void SolveSpaceUI::MenuFile(Command id) {
(FilenameHasExtension(exportFile, ".txt") || (FilenameHasExtension(exportFile, ".txt") ||
fabs(SS.exportOffset) > LENGTH_EPS)) fabs(SS.exportOffset) > LENGTH_EPS))
{ {
Message("Constraints are currently shown, and will be exported " Message(_("Constraints are currently shown, and will be exported "
"in the toolpath. This is probably not what you want; " "in the toolpath. This is probably not what you want; "
"hide them by clicking the link at the top of the " "hide them by clicking the link at the top of the "
"text window."); "text window."));
} }
SS.ExportViewOrWireframeTo(exportFile, /*exportWireframe*/false); SS.ExportViewOrWireframeTo(exportFile, /*exportWireframe*/false);
@ -583,11 +583,11 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
SS.ScheduleShowTW(); SS.ScheduleShowTW();
SS.GW.ClearSelection(); SS.GW.ClearSelection();
} else { } else {
Error("Constraint must have a label, and must not be " Error(_("Constraint must have a label, and must not be "
"a reference dimension."); "a reference dimension."));
} }
} else { } else {
Error("Bad selection for step dimension; select a constraint."); Error(_("Bad selection for step dimension; select a constraint."));
} }
break; break;
@ -611,7 +611,7 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
Error("%d edges interfere with other triangles, bad.", Error("%d edges interfere with other triangles, bad.",
SS.nakedEdges.l.n); SS.nakedEdges.l.n);
} else { } else {
Message("The assembly does not interfere, good."); Message(_("The assembly does not interfere, good."));
} }
break; break;
} }
@ -688,9 +688,9 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
case Command::AREA: { case Command::AREA: {
Group *g = SK.GetGroup(SS.GW.activeGroup); Group *g = SK.GetGroup(SS.GW.activeGroup);
if(g->polyError.how != PolyError::GOOD) { if(g->polyError.how != PolyError::GOOD) {
Error("This group does not contain a correctly-formed " Error(_("This group does not contain a correctly-formed "
"2d closed area. It is open, not coplanar, or self-" "2d closed area. It is open, not coplanar, or self-"
"intersecting."); "intersecting."));
break; break;
} }
SEdgeList sel = {}; SEdgeList sel = {};
@ -731,7 +731,7 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
perimeter / scale, perimeter / scale,
SS.UnitName()); SS.UnitName());
} else { } else {
Error("Bad selection for perimeter; select line segments, arcs, and curves."); Error(_("Bad selection for perimeter; select line segments, arcs, and curves."));
} }
break; break;
} }
@ -747,7 +747,7 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
SS.traced.point = gs.point[0]; SS.traced.point = gs.point[0];
SS.GW.ClearSelection(); SS.GW.ClearSelection();
} else { } else {
Error("Bad selection for trace; select a single point."); Error(_("Bad selection for trace; select a single point."));
} }
break; break;

View File

@ -158,8 +158,8 @@ void Style::AssignSelectionToStyle(uint32_t v) {
} }
if(showError) { if(showError) {
Error("Can't assign style to an entity that's derived from another " Error(_("Can't assign style to an entity that's derived from another "
"entity; try assigning a style to this entity's parent."); "entity; try assigning a style to this entity's parent."));
} }
SS.GW.ClearSelection(); SS.GW.ClearSelection();
@ -695,13 +695,13 @@ bool TextWindow::EditControlDoneForStyles(const char *str) {
SS.backgroundColor = RGBf(rgb.x, rgb.y, rgb.z); SS.backgroundColor = RGBf(rgb.x, rgb.y, rgb.z);
} }
} else { } else {
Error("Bad format: specify color as r, g, b"); Error(_("Bad format: specify color as r, g, b"));
} }
break; break;
} }
case Edit::STYLE_NAME: case Edit::STYLE_NAME:
if(!*str) { if(!*str) {
Error("Style name cannot be empty"); Error(_("Style name cannot be empty"));
} else { } else {
SS.UndoRemember(); SS.UndoRemember();
s = Style::Get(edit.style); s = Style::Get(edit.style);
@ -714,7 +714,7 @@ bool TextWindow::EditControlDoneForStyles(const char *str) {
if(e) { if(e) {
double ev = e->Eval(); double ev = e->Eval();
if(ev < 0.001 || isnan(ev)) { if(ev < 0.001 || isnan(ev)) {
Error("Scale must not be zero or negative!"); Error(_("Scale must not be zero or negative!"));
} else { } else {
SS.bgImage.scale = ev / SS.MmPerUnit(); SS.bgImage.scale = ev / SS.MmPerUnit();
} }

View File

@ -654,11 +654,11 @@ void TextWindow::EditControlDone(const char *s) {
double ev = e->Eval(); double ev = e->Eval();
if((int)ev < 1) { if((int)ev < 1) {
Error("Can't repeat fewer than 1 time."); Error(_("Can't repeat fewer than 1 time."));
break; break;
} }
if((int)ev > 999) { if((int)ev > 999) {
Error("Can't repeat more than 999 times."); Error(_("Can't repeat more than 999 times."));
break; break;
} }
@ -687,7 +687,7 @@ void TextWindow::EditControlDone(const char *s) {
} }
case Edit::GROUP_NAME: { case Edit::GROUP_NAME: {
if(!*s) { if(!*s) {
Error("Group name cannot be empty"); Error(_("Group name cannot be empty"));
} else { } else {
SS.UndoRemember(); SS.UndoRemember();
@ -701,7 +701,7 @@ void TextWindow::EditControlDone(const char *s) {
if(e) { if(e) {
double ev = e->Eval(); double ev = e->Eval();
if(fabs(ev) < 1e-6) { if(fabs(ev) < 1e-6) {
Error("Scale cannot be zero."); Error(_("Scale cannot be zero."));
} else { } else {
Group *g = SK.GetGroup(edit.group); Group *g = SK.GetGroup(edit.group);
g->scale = ev; g->scale = ev;
@ -722,7 +722,7 @@ void TextWindow::EditControlDone(const char *s) {
SS.MarkGroupDirty(g->h); SS.MarkGroupDirty(g->h);
SS.GW.ClearSuper(); SS.GW.ClearSuper();
} else { } else {
Error("Bad format: specify color as r, g, b"); Error(_("Bad format: specify color as r, g, b"));
} }
break; break;
} }
@ -731,7 +731,7 @@ void TextWindow::EditControlDone(const char *s) {
if(e) { if(e) {
double alpha = e->Eval(); double alpha = e->Eval();
if(alpha < 0 || alpha > 1) { if(alpha < 0 || alpha > 1) {
Error("Opacity must be between zero and one."); Error(_("Opacity must be between zero and one."));
} else { } else {
Group *g = SK.GetGroup(edit.group); Group *g = SK.GetGroup(edit.group);
g->color.alpha = (int)(255.1f * alpha); g->color.alpha = (int)(255.1f * alpha);
@ -770,7 +770,7 @@ void TextWindow::EditControlDone(const char *s) {
Expr *e = Expr::From(s, /*popUpError=*/true); Expr *e = Expr::From(s, /*popUpError=*/true);
if(!e) break; if(!e) break;
if(e->Eval() < LENGTH_EPS) { if(e->Eval() < LENGTH_EPS) {
Error("Radius cannot be zero or negative."); Error(_("Radius cannot be zero or negative."));
break; break;
} }
SS.tangentArcRadius = SS.ExprToMm(e); SS.tangentArcRadius = SS.ExprToMm(e);

View File

@ -32,10 +32,31 @@ bool SetLocale(const std::string &name);
bool SetLocale(uint16_t lcid); bool SetLocale(uint16_t lcid);
const std::string &Translate(const char *msgid); const std::string &Translate(const char *msgid);
const std::string &Translate(const char *msgctxt, const char *msgid);
const std::string &TranslatePlural(const char *msgid, unsigned n); const std::string &TranslatePlural(const char *msgid, unsigned n);
const std::string &TranslatePlural(const char *msgctxt, const char *msgid, unsigned n);
inline const char *N_(const char *msgid) { return msgid; } inline const char *N_(const char *msgid) {
inline const char *_(const char *msgid) { return Translate(msgid).c_str(); } return msgid;
}
inline const char *CN_(const char *msgctxt, const char *msgid) {
return msgid;
}
#if defined(LIBRARY)
inline const char *_(const char *msgid) {
return msgid;
}
inline const char *C_(const char *msgctxt, const char *msgid) {
return msgid;
}
#else
inline const char *_(const char *msgid) {
return Translate(msgid).c_str();
}
inline const char *C_(const char *msgctxt, const char *msgid) {
return Translate(msgctxt, msgid).c_str();
}
#endif
// This table describes the top-level menus in the graphics winodw. // This table describes the top-level menus in the graphics winodw.
enum class Command : uint32_t { enum class Command : uint32_t {

View File

@ -75,7 +75,7 @@ bool TextWindow::EditControlDoneForView(const char *s) {
if(v > LENGTH_EPS) { if(v > LENGTH_EPS) {
SS.GW.scale = v; SS.GW.scale = v;
} else { } else {
Error("Scale cannot be zero or negative."); Error(_("Scale cannot be zero or negative."));
} }
} }
break; break;
@ -87,7 +87,7 @@ bool TextWindow::EditControlDoneForView(const char *s) {
pt = pt.ScaledBy(SS.MmPerUnit()); pt = pt.ScaledBy(SS.MmPerUnit());
SS.GW.offset = pt.ScaledBy(-1); SS.GW.offset = pt.ScaledBy(-1);
} else { } else {
Error("Bad format: specify x, y, z"); Error(_("Bad format: specify x, y, z"));
} }
break; break;
} }
@ -96,7 +96,7 @@ bool TextWindow::EditControlDoneForView(const char *s) {
case Edit::VIEW_PROJ_UP: { case Edit::VIEW_PROJ_UP: {
Vector pt; Vector pt;
if(sscanf(s, "%lf, %lf, %lf", &pt.x, &pt.y, &pt.z) != 3) { if(sscanf(s, "%lf, %lf, %lf", &pt.x, &pt.y, &pt.z) != 3) {
Error("Bad format: specify x, y, z"); Error(_("Bad format: specify x, y, z"));
break; break;
} }
if(edit.meaning == Edit::VIEW_PROJ_RIGHT) { if(edit.meaning == Edit::VIEW_PROJ_RIGHT) {