Create basic gettext infrastructure and French language stub.

translation1
don bright 2014-01-31 19:16:24 +01:00 committed by Torsten Paul
parent 9fa66e37c0
commit 2cd87a5b91
37 changed files with 3538 additions and 155 deletions

85
doc/translation.txt Normal file
View File

@ -0,0 +1,85 @@
OpenSCAD human language translation
===================================
We use the GNU gettext system, both for c++ code as well as QT's .ui files.
The latter is accomplished by the '-tr' feature of QT's uic to insert
a gettext wrapper into the ui_xxxxx.h files.
For somewhat similar designs, see the source code of projects like celestia,
stellarium, licq, merkaartor, etc (although they typically use cmake).
Currently the build system does not auto-update anything. The .mo files must
be generated by running the gettext tools: xgettext, msgmerge, and msgfmt.
There is a script included, translation-update.sh, that automates this process.
File layout:
============
./po/*.po - .po files, one per language
./po/openscad.pot - .pot template, generated by xgettext
./po/POTFILES.in - list of source code files with translatable strings
./po/LINGUAS - list of language codes for which .po files exist
./src/qtgettext.h - wrapper code between QT and GNU gettext
./scripts/translation-update.sh - simple unix helper script
./po/xx/LC_MESSAGES/openscad.mo - 'binaries' of .po files, built by script
To translate the strings:
=========================
Use a text editor or special program (poedit or lokalize) to edit the .po file.
( See http://en.opensuse.org/SDB:Localization_work_with_po_files )
Then submit your new .po file as an OpenSCAD github issue or pull request:
https://github.com/openscad/openscad/issues/
In the future there might be a site to allow translations in a browser:
https://translations.launchpad.net/openscad
If all else fails, email the OpenSCAD mailing list with your new .po
file attached.
To make source code changes:
============================
In .cc files, #include "printutils.h" and change each "text" into
_("text"). In .ui files, #include "qtgettext.h" first in the .h file
(see MainWindow.h). Then clean and rebuild to recreate the ui_xxxx.h
files.
$ make clean && qmake && make
Now make sure your .cc and ui_xxxx.h files are listed in po/POTFILES.in.
Then run the script to scan them, and regenerate .pot & .po files.
$ ./scripts/translate.sh updateall
This will create new .po files with any new untranslated strings you
added to the source code. These .po files can be distributed to
translators for translation. After the translated .po file is obtained,
overwrite the old .po and run the same script to update the .mo files.
$ ./scripts/translate.sh updateall
To add a new language:
======================
First add the language code to file ./po/LINGUAS. Then run msginit, replacing
$LANGCODE with the language code you want.
$ msginit -l $LANGCODE -o ./po/$LANGCODE.po -i ./po/openscad.pot
You will now have a new ./po/xx.po file to edit and translate
Testing:
========
On unix, set the locale related environment variables. For example in
French, run this:
$ LANGUAGE=fr ./openscad
Linux system trace tools can help find errors. To show open()s on .mo files:
$ LANGUAGE=fr strace -f ./openscad 2>&1 | grep LC_MESSAGES

View File

@ -102,6 +102,8 @@ unix:!macx {
QMAKE_LIBS_OPENGL *= -lX11
}
#QTPLUGIN += qtaccessiblewidgets
netbsd* {
QMAKE_LFLAGS += -L/usr/X11R7/lib
QMAKE_LFLAGS += -Wl,-R/usr/X11R7/lib
@ -139,6 +141,8 @@ netbsd* {
QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-variable
QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-function
QMAKE_CXXFLAGS_WARN_ON += -Wno-c++11-extensions
# gettext
QMAKE_CXXFLAGS_WARN_ON += -Wno-format-security
# might want to actually turn this on once in a while
QMAKE_CXXFLAGS_WARN_ON += -Wno-sign-compare
}
@ -182,6 +186,8 @@ win* {
RESOURCES = openscad.qrc
QMAKE_UIC += -tr _
FORMS += src/MainWindow.ui \
src/Preferences.ui \
src/OpenCSGWarningDialog.ui \

2
po/LINGUAS Normal file
View File

@ -0,0 +1,2 @@
# available languages
fr

77
po/POTFILES.in Normal file
View File

@ -0,0 +1,77 @@
# see doc/translation.txt
# ui_xxxx.h files created by qt's uic when make is run.
# if you add new .ui files, add their .h counterpart here
objects/ui_AboutDialog.h
objects/ui_OpenCSGWarningDialog.h
objects/ui_ProgressWidget.h
objects/ui_MainWindow.h
objects/ui_Preferences.h
# C++
src/AppleEvents.cc
src/builtin.cc
src/cgaladv.cc
src/cgaladv_minkowski2.cc
src/CGALCache.cc
src/CGALEvaluator.cc
src/CGAL_Nef_polyhedron.cc
src/CGAL_Nef_polyhedron_DxfData.cc
src/CGALRenderer.cc
src/cgalutils.cc
src/cgalworker.cc
src/color.cc
src/context.cc
src/control.cc
src/csgops.cc
src/csgterm.cc
src/CSGTermEvaluator.cc
src/csgtermnormalizer.cc
src/dxfdata.cc
src/dxfdim.cc
src/dxftess.cc
src/dxftess-cgal.cc
src/dxftess-glu.cc
src/editor.cc
src/export.cc
src/expr.cc
src/func.cc
src/glview.cc
src/handle_dep.cc
src/highlighter.cc
src/import.cc
src/linalg.cc
src/linearextrude.cc
src/mainwin.cc
src/mathc99.cc
src/ModuleCache.cc
src/module.cc
src/node.cc
src/nodedumper.cc
src/OpenCSGRenderer.cc
src/OpenCSGWarningDialog.cc
src/openscad.cc
src/parsersettings.cc
src/PolySetCache.cc
src/polyset.cc
src/PolySetCGALEvaluator.cc
src/PolySetEvaluator.cc
src/Preferences.cc
src/primitives.cc
src/printutils.cc
src/progress.cc
src/ProgressWidget.cc
src/projection.cc
src/render.cc
src/renderer.cc
src/rendersettings.cc
src/rotateextrude.cc
src/stl-utils.cc
src/surface.cc
src/svg.cc
src/ThrownTogetherRenderer.cc
src/transform.cc
src/traverser.cc
src/Tree.cc
src/value.cc
src/version_check.cc

1556
po/fr.po Normal file

File diff suppressed because it is too large Load Diff

1553
po/openscad.pot Normal file

File diff suppressed because it is too large Load Diff

58
scripts/translation-update.sh Executable file
View File

@ -0,0 +1,58 @@
#!/bin/sh
# see doc/translation.txt for more info
updatepot()
{
if [ ! -e objects/ui_MainWindow.h ]; then
echo cannot find objects/ui_xxxxx.h files. perhaps if you run make...?
exit 1
fi
VER=`date +"%Y.%m.%d"`
OPTS=
OPTS=$OPTS' --package-name=OpenSCAD'
OPTS=$OPTS' --package-version='$VER
OPTS=$OPTS' --default-domain=openscad'
OPTS=$OPTS' --keyword=_'
OPTS=$OPTS' --files-from=./po/POTFILES.in'
cmd='xgettext '$OPTS' -o ./po/openscad.pot'
echo $cmd
$cmd
if [ ! $? = 0 ]; then
echo error running xgettext
exit 1
fi
sed -i s/"CHARSET"/"UTF-8"/g ./po/openscad.pot
}
updatepo()
{
for LANGCODE in `cat ./po/LINGUAS | grep -v "#"`; do
OPTS='--update --backup=t'
cmd='msgmerge '$OPTS' ./po/'$LANGCODE'.po ./po/openscad.pot'
echo $cmd
$cmd
if [ ! $? = 0 ]; then
echo error running msgmerge
exit 1
fi
done
}
updatemo()
{
for LANGCODE in `cat po/LINGUAS | grep -v "#"`; do
mkdir -p ./po/$LANGCODE/LC_MESSAGES
OPTS='-c -v'
cmd='msgfmt '$OPTS' -o ./po/'$LANGCODE'/LC_MESSAGES/openscad.mo ./po/'$LANGCODE'.po'
echo $cmd
$cmd
if [ ! $? = 0 ]; then
echo error running msgfmt
exit 1
fi
done
}
updatepot && updatepo && updatemo

View File

@ -1,6 +1,7 @@
#ifndef ABOUTDIALOG_H_
#define ABOUTDIALOG_H_
#include "qtgettext.h"
#include "ui_AboutDialog.h"
#define STRINGIFY(x) #x

View File

@ -71,7 +71,7 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() const
}
if (!err) err = createPolySetFromPolyhedron(P, *ps);
if (err) {
PRINT("ERROR: CGAL NefPolyhedron->Polyhedron conversion failed.");
PRINT(_("ERROR: CGAL NefPolyhedron->Polyhedron conversion failed."));
if (errmsg!="") PRINTB("ERROR: %s",errmsg);
delete ps; ps = NULL;
}

View File

@ -27,6 +27,7 @@ Some actions (showCrossHairs) only work properly on Gimbal Camera.
#include <iostream>
#include "renderer.h"
#include "Camera.h"
#include "qtgettext.h"
class GLView
{

View File

@ -1,6 +1,7 @@
#ifndef MAINWINDOW_H_
#define MAINWINDOW_H_
#include "qtgettext.h"
#include <QMainWindow>
#include "ui_MainWindow.h"
#include "openscad.h"

View File

@ -30,6 +30,12 @@
<pointsize>8</pointsize>
</font>
</property>
<property name="accessibleName">
<string>Editor</string>
</property>
<property name="accessibleDescription">
<string>Editor for SCAD code</string>
</property>
</widget>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
@ -40,6 +46,12 @@
</property>
<widget class="QGLView" name="qglview" native="true"/>
<widget class="QTextEdit" name="console">
<property name="accessibleName">
<string>Console</string>
</property>
<property name="accessibleDescription">
<string>Console messages</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
@ -116,7 +128,7 @@
<x>0</x>
<y>0</y>
<width>681</width>
<height>22</height>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">

View File

@ -67,10 +67,10 @@ FileModule *ModuleCache::evaluate(const std::string &filename)
if (shouldCompile) {
#ifdef DEBUG
if (this->entries.find(filename) != this->entries.end()) {
PRINTB("Recompiling cached library: %s (%s)", filename % cache_id);
PRINTB(_("Recompiling cached library: %s (%s)"), filename % cache_id);
}
else {
PRINTB("Compiling library '%s'.", filename);
PRINTB(_("Compiling library '%s'."), filename);
}
#endif
@ -78,7 +78,7 @@ FileModule *ModuleCache::evaluate(const std::string &filename)
{
std::ifstream ifs(filename.c_str());
if (!ifs.is_open()) {
PRINTB("WARNING: Can't open library file '%s'\n", filename);
PRINTB(_("WARNING: Can't open library file '%s'\n"), filename);
return NULL;
}
textbuf << ifs.rdbuf();
@ -96,7 +96,7 @@ FileModule *ModuleCache::evaluate(const std::string &filename)
std::string pathname = boosty::stringy(fs::path(filename).parent_path());
lib_mod = dynamic_cast<FileModule*>(parse(textbuf.str().c_str(), pathname.c_str(), false));
PRINTB_NOCACHE(" compiled module: %p", lib_mod);
PRINTB_NOCACHE(_(" compiled module: %p"), lib_mod);
if (lib_mod) {
// We defer deletion so we can ensure that the new module won't

View File

@ -1,6 +1,7 @@
#ifndef OPENCSGWARNINGDIALOG_H_
#define OPENCSGWARNINGDIALOG_H_
#include "qtgettext.h"
#include "ui_OpenCSGWarningDialog.h"
class OpenCSGWarningDialog : public QDialog, public Ui::OpenCSGWarningDialog

View File

@ -1,6 +1,7 @@
#ifndef PREFERENCES_H_
#define PREFERENCES_H_
#include "qtgettext.h"
#include <QMainWindow>
#include <QSettings>
#include "ui_Preferences.h"

View File

@ -1,6 +1,7 @@
#ifndef PROGRESSWIDGET_H_
#define PROGRESSWIDGET_H_
#include "qtgettext.h"
#include "ui_ProgressWidget.h"
#include <QTime>

View File

@ -938,7 +938,7 @@ bool createPolyhedronFromPolySet(const PolySet &ps, CGAL_Polyhedron &p)
p.delegate(builder);
}
catch (const CGAL::Assertion_exception &e) {
PRINTB("CGAL error in CGALUtils::createPolyhedronFromPolySet: %s", e.what());
PRINTB(_("CGAL error in CGALUtils::createPolyhedronFromPolySet: %s"), e.what());
err = true;
}
CGAL::set_error_behaviour(old_behaviour);

View File

@ -33,7 +33,7 @@ void CGALWorker::work()
root_geom = evaluator.evaluateGeometry(*this->tree->root(), true);
}
catch (const ProgressCancelException &e) {
PRINT("Rendering cancelled.");
PRINT(_("Rendering cancelled."));
}
emit done(root_geom);

View File

@ -66,7 +66,7 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
for (size_t i = 0; i < 4; i++) {
node->color[i] = i < v.toVector().size() ? v.toVector()[i].toDouble() : 1.0;
if (node->color[i] > 1)
PRINTB_NOCACHE("WARNING: color() expects numbers between 0.0 and 1.0. Value of %.1f is too large.", node->color[i]);
PRINTB_NOCACHE(_("WARNING: color() expects numbers between 0.0 and 1.0. Value of %.1f is too large."), node->color[i]);
}
} else if (v.type() == Value::STRING) {
std::string colorname = v.toString();
@ -78,8 +78,8 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
node->color[1] = color[1];
node->color[2] = color[2];
} else {
PRINTB_NOCACHE("WARNING: Color name \"%s\" unknown. Please see", colorname);
PRINT_NOCACHE("WARNING: http://en.wikipedia.org/wiki/Web_colors");
PRINTB_NOCACHE(_("WARNING: Color name \"%s\" unknown. Please see"), colorname);
PRINT_NOCACHE(_("WARNING: http://en.wikipedia.org/wiki/Web_colors"));
}
}
Value alpha = c.lookup_variable("alpha");

View File

@ -94,7 +94,7 @@ void Context::set_variable(const std::string &name, const Value &value)
void Context::set_constant(const std::string &name, const Value &value)
{
if (this->constants.find(name) != this->constants.end()) {
PRINTB("WARNING: Attempt to modify constant '%s'.", name);
PRINTB(_("WARNING: Attempt to modify constant '%s'."), name);
}
else {
this->constants[name] = value;
@ -118,21 +118,21 @@ Value Context::lookup_variable(const std::string &name, bool silent) const
if (this->parent)
return this->parent->lookup_variable(name, silent);
if (!silent)
PRINTB("WARNING: Ignoring unknown variable '%s'.", name);
PRINTB(_("WARNING: Ignoring unknown variable '%s'."), name);
return Value();
}
Value Context::evaluate_function(const std::string &name, const EvalContext *evalctx) const
{
if (this->parent) return this->parent->evaluate_function(name, evalctx);
PRINTB("WARNING: Ignoring unknown function '%s'.", name);
PRINTB(_("WARNING: Ignoring unknown function '%s'."), name);
return Value();
}
AbstractNode *Context::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const
{
if (this->parent) return this->parent->instantiate_module(inst, evalctx);
PRINTB("WARNING: Ignoring unknown module '%s'.", inst.name());
PRINTB(_("WARNING: Ignoring unknown module '%s'."), inst.name());
return NULL;
}

View File

@ -18,7 +18,7 @@ shared_ptr<CSGTerm> CSGTermNormalizer::normalize(const shared_ptr<CSGTerm> &root
temp = n;
if (this->nodecount > this->limit) {
PRINTB("WARNING: Normalized tree is growing past %d elements. Aborting normalization.\n", this->limit);
PRINTB(_("WARNING: Normalized tree is growing past %d elements. Aborting normalization.\n"), this->limit);
// Clean up any partially evaluated terms
shared_ptr<CSGTerm> newroot = root, tmproot;
while (newroot && newroot != tmproot) {
@ -66,7 +66,7 @@ shared_ptr<CSGTerm> CSGTermNormalizer::normalizePass(shared_ptr<CSGTerm> term)
while (term && match_and_replace(term)) { }
this->nodecount++;
if (nodecount > this->limit) {
PRINTB("WARNING: Normalized tree is growing past %d elements. Aborting normalization.\n", this->limit);
PRINTB(_("WARNING: Normalized tree is growing past %d elements. Aborting normalization.\n"), this->limit);
this->aborted = true;
return shared_ptr<CSGTerm>();
}

View File

@ -81,7 +81,7 @@ DxfData::DxfData(double fn, double fs, double fa,
std::ifstream stream(filename.c_str());
if (!stream.good()) {
PRINTB("WARNING: Can't open DXF file '%s'.", filename);
PRINTB(_("WARNING: Can't open DXF file '%s'."), filename);
return;
}
@ -145,7 +145,7 @@ DxfData::DxfData(double fn, double fs, double fa,
}
catch (const boost::bad_lexical_cast &blc) {
if (!stream.eof()) {
PRINTB("WARNING: Illegal ID '%s' in `%s'", id_str % filename);
PRINTB(_("WARNING: Illegal ID '%s' in `%s'"), id_str % filename);
}
break;
}
@ -384,16 +384,16 @@ DxfData::DxfData(double fn, double fs, double fa,
}
}
catch (boost::bad_lexical_cast &blc) {
PRINTB("WARNING: Illegal value %s in '%s'", data % filename);
PRINTB(_("WARNING: Illegal value %s in '%s'"), data % filename);
}
}
BOOST_FOREACH(const EntityList::value_type &i, unsupported_entities_list) {
if (layername.empty()) {
PRINTB("WARNING: Unsupported DXF Entity '%s' (%x) in %s.",
PRINTB(_("WARNING: Unsupported DXF Entity '%s' (%x) in %s."),
i.first % i.second % QuotedString(boosty::stringy(boostfs_uncomplete(filename, fs::current_path()))));
} else {
PRINTB("WARNING: Unsupported DXF Entity '%s' (%x) in layer '%s' of %s.",
PRINTB(_("WARNING: Unsupported DXF Entity '%s' (%x) in layer '%s' of %s."),
i.first % i.second % layername % QuotedString(boosty::stringy(boostfs_uncomplete(filename, fs::current_path()))));
}
}

View File

@ -128,12 +128,12 @@ Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx)
return dxf_dim_cache[key] = Value((d->type & 64) ? d->coords[3][0] : d->coords[3][1]);
}
PRINTB("WARNING: Dimension '%s' in '%s', layer '%s' has unsupported type!",
PRINTB(_("WARNING: Dimension '%s' in '%s', layer '%s' has unsupported type!"),
name % filename % layername);
return Value();
}
PRINTB("WARNING: Can't find dimension '%s' in '%s', layer '%s'!",
PRINTB(_("WARNING: Can't find dimension '%s' in '%s', layer '%s'!"),
name % filename % layername);
return Value();
@ -208,7 +208,7 @@ Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx)
}
}
PRINTB("WARNING: Can't find cross in '%s', layer '%s'!", filename % layername);
PRINTB(_("WARNING: Can't find cross in '%s', layer '%s'!"), filename % layername);
return Value();
}

View File

@ -177,14 +177,14 @@ static void export_stl(const CGAL_Polyhedron &P, std::ostream &output)
void export_stl(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
{
if (!root_N->p3->is_simple()) {
PRINT("Object isn't a valid 2-manifold! Modify your design.\n");
PRINT(_("Object isn't a valid 2-manifold! Modify your design.\n"));
}
bool usePolySet = false;
if (usePolySet) {
PolySet ps(3);
bool err = createPolySetFromNefPolyhedron3(*(root_N->p3), ps);
if (err) { PRINT("ERROR: Nef->PolySet failed"); }
if (err) { PRINT(_("ERROR: Nef->PolySet failed")); }
else {
export_stl(ps, output);
}
@ -231,7 +231,7 @@ void export_off(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
output << P;
}
catch (const CGAL::Assertion_exception &e) {
PRINTB("CGAL error in CGAL_Nef_polyhedron3::convert_to_Polyhedron(): %s", e.what());
PRINTB(_("CGAL error in CGAL_Nef_polyhedron3::convert_to_Polyhedron(): %s"), e.what());
}
CGAL::set_error_behaviour(old_behaviour);
}

View File

@ -1,4 +1,4 @@
/*
/*
* OpenSCAD (www.openscad.org)
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
* Marius Kintel <marius@kintel.net>
@ -500,7 +500,7 @@ Value builtin_search(const Context *, const EvalContext *evalctx)
if(ptr_ft) {
g_utf8_strncpy( utf8_of_cp, ptr_ft, 1 );
}
PRINTB(" WARNING: search term not found: \"%s\"", utf8_of_cp );
PRINTB(_(" WARNING: search term not found: \"%s\""), utf8_of_cp );
}
if (num_returns_per_match == 0 || num_returns_per_match > 1) {
returnvec.push_back(Value(resultvec));
@ -530,10 +530,10 @@ Value builtin_search(const Context *, const EvalContext *evalctx)
}
if (num_returns_per_match == 1 && matchCount == 0) {
if (findThis.toVector()[i].type() == Value::NUMBER) {
PRINTB(" WARNING: search term not found: %s",findThis.toVector()[i].toDouble());
PRINTB(_(" WARNING: search term not found: %s"),findThis.toVector()[i].toDouble());
}
else if (findThis.toVector()[i].type() == Value::STRING) {
PRINTB(" WARNING: search term not found: \"%s\"",findThis.toVector()[i].toString());
PRINTB(_(" WARNING: search term not found: \"%s\""),findThis.toVector()[i].toString());
}
returnvec.push_back(Value(resultvec));
}
@ -542,7 +542,7 @@ Value builtin_search(const Context *, const EvalContext *evalctx)
}
}
} else {
PRINTB(" WARNING: search: none performed on input %s", findThis);
PRINTB(_(" WARNING: search: none performed on input %s"), findThis);
return Value();
}
return Value(returnvec);

View File

@ -1,3 +1,4 @@
#include "printutils.h"
#include "handle_dep.h"
#include <string>
#include <sstream>
@ -32,7 +33,7 @@ bool write_deps(const std::string &filename, const std::string &output_file)
{
FILE *fp = fopen(filename.c_str(), "wt");
if (!fp) {
fprintf(stderr, "Can't open dependencies file `%s' for writing!\n", filename.c_str());
fprintf(stderr, _("Can't open dependencies file `%s' for writing!\n"), filename.c_str());
return false;
}
fprintf(fp, "%s:", output_file.c_str());

View File

@ -198,7 +198,7 @@ Geometry *ImportNode::createGeometry() const
// Open file and position at the end
std::ifstream f(this->filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
if (!f.good()) {
PRINTB("WARNING: Can't open import file '%s'.", this->filename);
PRINTB(_("WARNING: Can't open import file '%s'."), this->filename);
return g;
}
@ -248,7 +248,7 @@ Geometry *ImportNode::createGeometry() const
}
}
catch (const boost::bad_lexical_cast &blc) {
PRINTB("WARNING: Can't parse vertex line '%s'.", line);
PRINTB(_("WARNING: Can't parse vertex line '%s'."), line);
i = 10;
continue;
}
@ -292,7 +292,7 @@ Geometry *ImportNode::createGeometry() const
bool err = createPolySetFromPolyhedron(poly, *p);
}
#else
PRINT("WARNING: OFF import requires CGAL.");
PRINT(_("WARNING: OFF import requires CGAL."));
#endif
}
break;
@ -302,7 +302,7 @@ Geometry *ImportNode::createGeometry() const
}
break;
default:
PRINTB("ERROR: Unsupported file format while trying to import file '%s'", this->filename);
PRINTB(_("ERROR: Unsupported file format while trying to import file '%s'"), this->filename);
g = new PolySet(0);
}

View File

@ -74,7 +74,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
Value slices = c.lookup_variable("slices", true);
if (!file.isUndefined() && file.type() == Value::STRING) {
PRINT("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead.");
PRINT(_("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead."));
node->filename = lookup_file(file.toString(), inst->path(), c.documentPath());
}

View File

@ -114,13 +114,13 @@ static char helptitle[] =
" (git " QUOTED(OPENSCAD_COMMIT) ")"
#endif
"\nhttp://www.openscad.org\n\n";
static char copyrighttext[] =
"Copyright (C) 2009-2013 The OpenSCAD Developers\n"
static char *copyrighttext =
_("Copyright (C) 2009-2013 The OpenSCAD Developers\n"
"\n"
"This program is free software; you can redistribute it and/or modify "
"it under the terms of the GNU General Public License as published by "
"the Free Software Foundation; either version 2 of the License, or "
"(at your option) any later version.";
"(at your option) any later version.");
static void
settings_setValueList(const QString &key,const QList<int> &list)
@ -347,7 +347,7 @@ MainWindow::MainWindow(const QString &filename)
setCurrentOutput();
PRINT(helptitle);
PRINT(copyrighttext);
PRINTB("%s", copyrighttext);
PRINT("");
if (!filename.isEmpty()) {
@ -520,11 +520,11 @@ MainWindow::setFileName(const QString &filename)
if (filename.isEmpty()) {
this->fileName.clear();
this->top_ctx.setDocumentPath(currentdir);
setWindowTitle("OpenSCAD - New Document[*]");
setWindowTitle(_("OpenSCAD - New Document[*]"));
}
else {
QFileInfo fileinfo(filename);
setWindowTitle("OpenSCAD - " + fileinfo.fileName() + "[*]");
setWindowTitle(("OpenSCAD - ") + fileinfo.fileName() + _("[*]"));
// Check that the canonical file path exists - only update recent files
// if it does. Should prevent empty list items on initial open etc.
@ -598,14 +598,14 @@ void MainWindow::refreshDocument()
if (!this->fileName.isEmpty()) {
QFile file(this->fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
PRINTB("Failed to open file %s: %s",
PRINTB(_("Failed to open file %s: %s"),
this->fileName.toLocal8Bit().constData() % file.errorString().toLocal8Bit().constData());
}
else {
QTextStream reader(&file);
reader.setCodec("UTF-8");
QString text = reader.readAll();
PRINTB("Loaded design '%s'.", this->fileName.toLocal8Bit().constData());
PRINTB(_("Loaded design '%s'."), this->fileName.toLocal8Bit().constData());
editor->setPlainText(text);
}
}
@ -736,7 +736,7 @@ void MainWindow::instantiateRoot()
if (this->root_module) {
// Evaluate CSG tree
PRINT("Compiling design (CSG Tree generation)...");
PRINT(_("Compiling design (CSG Tree generation)..."));
if (this->procevents) QApplication::processEvents();
AbstractNode::resetIndexCounter();
@ -762,9 +762,9 @@ void MainWindow::instantiateRoot()
if (!this->root_node) {
if (parser_error_pos < 0) {
PRINT("ERROR: Compilation failed! (no top level object found)");
PRINT(_("ERROR: Compilation failed! (no top level object found)"));
} else {
PRINT("ERROR: Compilation failed!");
PRINT(_("ERROR: Compilation failed!"));
}
if (this->procevents) QApplication::processEvents();
}
@ -777,7 +777,7 @@ void MainWindow::instantiateRoot()
void MainWindow::compileCSG(bool procevents)
{
assert(this->root_node);
PRINT("Compiling design (CSG Products generation)...");
PRINT(_("Compiling design (CSG Products generation)..."));
if (procevents) QApplication::processEvents();
// Main CSG evaluation
@ -798,7 +798,7 @@ void MainWindow::compileCSG(bool procevents)
if (procevents) QApplication::processEvents();
this->root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms);
if (!root_raw_term) {
PRINT("ERROR: CSG generation failed! (no top level object found)");
PRINT(_("ERROR: CSG generation failed! (no top level object found)"));
}
GeometryCache::instance()->print();
#ifdef ENABLE_CGAL
@ -807,7 +807,7 @@ void MainWindow::compileCSG(bool procevents)
if (procevents) QApplication::processEvents();
}
catch (const ProgressCancelException &e) {
PRINT("CSG generation cancelled.");
PRINT(_("CSG generation cancelled."));
}
progress_report_fin();
this->statusBar()->removeWidget(this->progresswidget);
@ -815,7 +815,7 @@ void MainWindow::compileCSG(bool procevents)
this->progresswidget = NULL;
if (root_raw_term) {
PRINT("Compiling design (CSG Products normalization)...");
PRINT(_("Compiling design (CSG Products normalization)..."));
if (procevents) QApplication::processEvents();
size_t normalizelimit = 2 * Preferences::inst()->getValue("advanced/openCSGLimit").toUInt();
@ -827,13 +827,13 @@ void MainWindow::compileCSG(bool procevents)
}
else {
this->root_chain = NULL;
PRINT("WARNING: CSG normalization resulted in an empty tree");
PRINT(_("WARNING: CSG normalization resulted in an empty tree"));
if (procevents) QApplication::processEvents();
}
if (highlight_terms.size() > 0)
{
PRINTB("Compiling highlights (%d CSG Trees)...", highlight_terms.size());
PRINTB(_("Compiling highlights (%d CSG Trees)..."), highlight_terms.size());
if (procevents) QApplication::processEvents();
highlights_chain = new CSGChain();
@ -845,7 +845,7 @@ void MainWindow::compileCSG(bool procevents)
if (background_terms.size() > 0)
{
PRINTB("Compiling background (%d CSG Trees)...", background_terms.size());
PRINTB(_("Compiling background (%d CSG Trees)..."), background_terms.size());
if (procevents) QApplication::processEvents();
background_chain = new CSGChain();
@ -858,11 +858,11 @@ void MainWindow::compileCSG(bool procevents)
if (this->root_chain &&
(this->root_chain->objects.size() >
Preferences::inst()->getValue("advanced/openCSGLimit").toUInt())) {
PRINTB("WARNING: Normalized tree has %d elements!", this->root_chain->objects.size());
PRINT("WARNING: OpenCSG rendering has been disabled.");
PRINTB(_("WARNING: Normalized tree has %d elements!"), this->root_chain->objects.size());
PRINT(_("WARNING: OpenCSG rendering has been disabled."));
}
else {
PRINTB("Normalized CSG tree has %d elements",
PRINTB(_("Normalized CSG tree has %d elements"),
(this->root_chain ? this->root_chain->objects.size() : 0));
this->opencsgRenderer = new OpenCSGRenderer(this->root_chain,
this->highlights_chain,
@ -872,9 +872,9 @@ void MainWindow::compileCSG(bool procevents)
this->thrownTogetherRenderer = new ThrownTogetherRenderer(this->root_chain,
this->highlights_chain,
this->background_chain);
PRINT("CSG generation finished.");
PRINT(_("CSG generation finished."));
int s = t.elapsed() / 1000;
PRINTB("Total rendering time: %d hours, %d minutes, %d seconds", (s / (60*60)) % ((s / 60) % 60) % (s % 60));
PRINTB(_("Total rendering time: %d hours, %d minutes, %d seconds"), (s / (60*60)) % ((s / 60) % 60) % (s % 60));
if (procevents) QApplication::processEvents();
}
}
@ -901,8 +901,8 @@ void MainWindow::actionNew()
void MainWindow::actionOpen()
{
QString new_filename = QFileDialog::getOpenFileName(this, "Open File", "",
"OpenSCAD Designs (*.scad *.csg)");
QString new_filename = QFileDialog::getOpenFileName(this, _("Open File"), "",
_("OpenSCAD Designs (*.scad *.csg)"));
#ifdef ENABLE_MDI
if (!new_filename.isEmpty()) {
new MainWindow(new_filename);
@ -996,7 +996,7 @@ void MainWindow::actionSave()
setCurrentOutput();
QFile file(this->fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
PRINTB("Failed to open file for writing: %s (%s)", this->fileName.toLocal8Bit().constData() % file.errorString().toLocal8Bit().constData());
PRINTB(_("Failed to open file for writing: %s (%s)"), this->fileName.toLocal8Bit().constData() % file.errorString().toLocal8Bit().constData());
QMessageBox::warning(this, windowTitle(), tr("Failed to open file for writing:\n %1 (%2)")
.arg(this->fileName).arg(file.errorString()));
}
@ -1004,7 +1004,7 @@ void MainWindow::actionSave()
QTextStream writer(&file);
writer.setCodec("UTF-8");
writer << this->editor->toPlainText();
PRINTB("Saved design '%s'.", this->fileName.toLocal8Bit().constData());
PRINTB(_("Saved design '%s'."), this->fileName.toLocal8Bit().constData());
this->editor->setContentModified(false);
}
clearCurrentOutput();
@ -1014,9 +1014,9 @@ void MainWindow::actionSave()
void MainWindow::actionSaveAs()
{
QString new_filename = QFileDialog::getSaveFileName(this, "Save File",
this->fileName.isEmpty()?"Untitled.scad":this->fileName,
"OpenSCAD Designs (*.scad)");
QString new_filename = QFileDialog::getSaveFileName(this, _("Save File"),
this->fileName.isEmpty()?_("Untitled.scad"):this->fileName,
_("OpenSCAD Designs (*.scad)"));
if (!new_filename.isEmpty()) {
if (QFileInfo(new_filename).suffix().isEmpty()) {
new_filename.append(".scad");
@ -1026,7 +1026,7 @@ void MainWindow::actionSaveAs()
QFileInfo info(new_filename);
if (info.exists()) {
if (QMessageBox::warning(this, windowTitle(),
tr("%1 already exists.\nDo you want to replace it?").arg(info.fileName()),
tr(_("%1 already exists.\nDo you want to replace it?")).arg(info.fileName()),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) {
return;
}
@ -1178,9 +1178,9 @@ bool MainWindow::checkEditorModified()
{
if (editor->isContentModified()) {
QMessageBox::StandardButton ret;
ret = QMessageBox::warning(this, "Application",
"The document has been modified.\n"
"Do you really want to reload the file?",
ret = QMessageBox::warning(this, _("Application"),
_("The document has been modified.\n"
"Do you really want to reload the file?"),
QMessageBox::Yes | QMessageBox::No);
if (ret != QMessageBox::Yes) {
designActionAutoReload->setChecked(false);
@ -1229,7 +1229,7 @@ void MainWindow::actionRenderPreview()
autoReloadTimer->stop();
setCurrentOutput();
PRINT("Parsing design (AST generation)...");
PRINT(_("Parsing design (AST generation)..."));
QApplication::processEvents();
this->afterCompileSlot = "csgRender";
this->procevents = !viewActionAnimate->isChecked();
@ -1257,7 +1257,7 @@ void MainWindow::csgRender()
QString filename;
double s = this->e_fsteps->text().toDouble();
double t = this->e_tval->text().toDouble();
filename.sprintf("frame%05d.png", int(round(s*t)));
filename.sprintf(_("frame%05d.png"), int(round(s*t)));
img.save(filename, "PNG");
}
@ -1273,7 +1273,7 @@ void MainWindow::actionRender()
autoReloadTimer->stop();
setCurrentOutput();
PRINT("Parsing design (AST generation)...");
PRINT(_("Parsing design (AST generation)..."));
QApplication::processEvents();
this->afterCompileSlot = "cgalRender";
this->procevents = true;
@ -1291,7 +1291,7 @@ void MainWindow::cgalRender()
this->cgalRenderer = NULL;
this->root_geom.reset();
PRINT("Rendering Polygon Mesh using CGAL...");
PRINT(_("Rendering Polygon Mesh using CGAL..."));
this->progresswidget = new ProgressWidget(this);
connect(this->progresswidget, SIGNAL(requestShow()), this, SLOT(showProgress()));
@ -1312,34 +1312,34 @@ void MainWindow::actionRenderDone(shared_ptr<const Geometry> root_geom)
#endif
int s = this->progresswidget->elapsedTime() / 1000;
PRINTB("Total rendering time: %d hours, %d minutes, %d seconds", (s / (60*60)) % ((s / 60) % 60) % (s % 60));
PRINTB(_("Total rendering time: %d hours, %d minutes, %d seconds"), (s / (60*60)) % ((s / 60) % 60) % (s % 60));
if (const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(root_geom.get())) {
if (!N->isEmpty()) {
if (N->getDimension() == 3) {
PRINT(" Top level object is a 3D object:");
PRINTB(" Simple: %6s", (N->p3->is_simple() ? "yes" : "no"));
PRINTB(" Valid: %6s", (N->p3->is_valid() ? "yes" : "no"));
PRINTB(" Vertices: %6d", N->p3->number_of_vertices());
PRINTB(" Halfedges: %6d", N->p3->number_of_halfedges());
PRINTB(" Edges: %6d", N->p3->number_of_edges());
PRINTB(" Halffacets: %6d", N->p3->number_of_halffacets());
PRINTB(" Facets: %6d", N->p3->number_of_facets());
PRINTB(" Volumes: %6d", N->p3->number_of_volumes());
PRINT(_(" Top level object is a 3D object:"));
PRINTB(_(" Simple: %6s"), (N->p3->is_simple() ? _("yes") : _("no")));
PRINTB(_(" Valid: %6s"), (N->p3->is_valid() ? _("yes") : _("no")));
PRINTB(_(" Vertices: %6d"), N->p3->number_of_vertices());
PRINTB(_(" Halfedges: %6d"), N->p3->number_of_halfedges());
PRINTB(_(" Edges: %6d"), N->p3->number_of_edges());
PRINTB(_(" Halffacets: %6d"), N->p3->number_of_halffacets());
PRINTB(_(" Facets: %6d"), N->p3->number_of_facets());
PRINTB(_(" Volumes: %6d"), N->p3->number_of_volumes());
}
}
}
else if (const PolySet *ps = dynamic_cast<const PolySet *>(root_geom.get())) {
assert(ps->getDimension() == 3);
PRINT(" Top level object is a 3D object:");
PRINTB(" Facets: %6d", ps->numPolygons());
PRINT(_(" Top level object is a 3D object:"));
PRINTB(_(" Facets: %6d"), ps->numPolygons());
} else if (const Polygon2d *poly = dynamic_cast<const Polygon2d *>(root_geom.get())) {
PRINT(" Top level object is a 2D object:");
PRINTB(" Contours: %6d", poly->outlines().size());
PRINT(_(" Top level object is a 2D object:"));
PRINTB(_(" Contours: %6d"), poly->outlines().size());
} else {
assert(false && "Unknown geometry type");
assert(false && _("Unknown geometry type"));
}
PRINT("Rendering finished.");
PRINT(_("Rendering finished."));
this->root_geom = root_geom;
this->cgalRenderer = new CGALRenderer(root_geom);
@ -1348,7 +1348,7 @@ void MainWindow::actionRenderDone(shared_ptr<const Geometry> root_geom)
else viewModeSurface();
}
else {
PRINT("WARNING: No top level geometry to render");
PRINT(_("WARNING: No top level geometry to render"));
}
this->statusBar()->removeWidget(this->progresswidget);
@ -1365,12 +1365,12 @@ void MainWindow::actionDisplayAST()
QTextEdit *e = new QTextEdit(this);
e->setWindowFlags(Qt::Window);
e->setTabStopWidth(30);
e->setWindowTitle("AST Dump");
e->setWindowTitle(_("AST Dump"));
e->setReadOnly(true);
if (root_module) {
e->setPlainText(QString::fromLocal8Bit(root_module->dump("", "").c_str()));
} else {
e->setPlainText("No AST to dump. Please try compiling first...");
e->setPlainText(_("No AST to dump. Please try compiling first..."));
}
e->show();
e->resize(600, 400);
@ -1383,12 +1383,12 @@ void MainWindow::actionDisplayCSGTree()
QTextEdit *e = new QTextEdit(this);
e->setWindowFlags(Qt::Window);
e->setTabStopWidth(30);
e->setWindowTitle("CSG Tree Dump");
e->setWindowTitle(_("CSG Tree Dump"));
e->setReadOnly(true);
if (this->root_node) {
e->setPlainText(QString::fromLocal8Bit(this->tree.getString(*this->root_node).c_str()));
} else {
e->setPlainText("No CSG to dump. Please try compiling first...");
e->setPlainText(_("No CSG to dump. Please try compiling first..."));
}
e->show();
e->resize(600, 400);
@ -1401,9 +1401,9 @@ void MainWindow::actionDisplayCSGProducts()
QTextEdit *e = new QTextEdit(this);
e->setWindowFlags(Qt::Window);
e->setTabStopWidth(30);
e->setWindowTitle("CSG Products Dump");
e->setWindowTitle(_("CSG Products Dump"));
e->setReadOnly(true);
e->setPlainText(QString("\nCSG before normalization:\n%1\n\n\nCSG after normalization:\n%2\n\n\nCSG rendering chain:\n%3\n\n\nHighlights CSG rendering chain:\n%4\n\n\nBackground CSG rendering chain:\n%5\n")
e->setPlainText(QString(_("\nCSG before normalization:\n%1\n\n\nCSG after normalization:\n%2\n\n\nCSG rendering chain:\n%3\n\n\nHighlights CSG rendering chain:\n%4\n\n\nBackground CSG rendering chain:\n%5\n"))
.arg(root_raw_term ? QString::fromLocal8Bit(root_raw_term->dump().c_str()) : "N/A",
root_norm_term ? QString::fromLocal8Bit(root_norm_term->dump().c_str()) : "N/A",
this->root_chain ? QString::fromLocal8Bit(this->root_chain->dump().c_str()) : "N/A",
@ -1426,45 +1426,45 @@ void MainWindow::actionExportSTLorOFF(bool)
setCurrentOutput();
if (!this->root_geom) {
PRINT("Nothing to export! Try building first (press F6).");
PRINT(_("Nothing to export! Try building first (press F6)."));
clearCurrentOutput();
return;
}
if (this->root_geom->getDimension() != 3) {
PRINT("Current top level object is not a 3D object.");
PRINT(_("Current top level object is not a 3D object."));
clearCurrentOutput();
return;
}
const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(this->root_geom.get());
if (N && !N->p3->is_simple()) {
PRINT("Object isn't a valid 2-manifold! Modify your design. See http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export");
PRINT(_("Object isn't a valid 2-manifold! Modify your design. See http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export"));
clearCurrentOutput();
return;
}
QString suffix = stl_mode ? ".stl" : ".off";
QString stl_filename = QFileDialog::getSaveFileName(this,
stl_mode ? "Export STL File" : "Export OFF File",
stl_mode ? _("Export STL File") : _("Export OFF File"),
this->fileName.isEmpty() ? "Untitled"+suffix : QFileInfo(this->fileName).baseName()+suffix,
stl_mode ? "STL Files (*.stl)" : "OFF Files (*.off)");
stl_mode ? _("STL Files (*.stl)") : _("OFF Files (*.off)"));
if (stl_filename.isEmpty()) {
PRINTB("No filename specified. %s export aborted.", (stl_mode ? "STL" : "OFF"));
PRINTB(_("No filename specified. %s export aborted."), (stl_mode ? "STL" : "OFF"));
clearCurrentOutput();
return;
}
std::ofstream fstream(stl_filename.toUtf8());
if (!fstream.is_open()) {
PRINTB("Can't open file \"%s\" for export", stl_filename.toLocal8Bit().constData());
PRINTB(_("Can't open file \"%s\" for export"), stl_filename.toLocal8Bit().constData());
}
else {
if (stl_mode) exportFile(this->root_geom.get(), fstream, OPENSCAD_STL);
else exportFile(this->root_geom.get(), fstream, OPENSCAD_OFF);
fstream.close();
PRINTB("%s export finished.", (stl_mode ? "STL" : "OFF"));
PRINTB(_("%s export finished."), (stl_mode ? "STL" : "OFF"));
}
clearCurrentOutput();
@ -1487,35 +1487,35 @@ void MainWindow::actionExportDXF()
setCurrentOutput();
if (!this->root_geom) {
PRINT("Nothing to export! Try building first (press F6).");
PRINT(_("Nothing to export! Try building first (press F6)."));
clearCurrentOutput();
return;
}
if (this->root_geom->getDimension() != 2) {
PRINT("Current top level object is not a 2D object.");
PRINT(_("Current top level object is not a 2D object."));
clearCurrentOutput();
return;
}
QString dxf_filename = QFileDialog::getSaveFileName(this,
"Export DXF File",
this->fileName.isEmpty() ? "Untitled.dxf" : QFileInfo(this->fileName).baseName()+".dxf",
"DXF Files (*.dxf)");
_("Export DXF File"),
this->fileName.isEmpty() ? _("Untitled.dxf") : QFileInfo(this->fileName).baseName()+".dxf",
_("DXF Files (*.dxf)"));
if (dxf_filename.isEmpty()) {
PRINT("No filename specified. DXF export aborted.");
PRINT(_("No filename specified. DXF export aborted."));
clearCurrentOutput();
return;
}
std::ofstream fstream(dxf_filename.toUtf8());
if (!fstream.is_open()) {
PRINTB("Can't open file \"%s\" for export", dxf_filename.toLocal8Bit().constData());
PRINTB(_("Can't open file \"%s\" for export"), dxf_filename.toLocal8Bit().constData());
}
else {
exportFile(this->root_geom.get(), fstream, OPENSCAD_DXF);
fstream.close();
PRINT("DXF export finished.");
PRINT(_("DXF export finished."));
}
clearCurrentOutput();
@ -1527,28 +1527,28 @@ void MainWindow::actionExportCSG()
setCurrentOutput();
if (!this->root_node) {
PRINT("Nothing to export. Please try compiling first...");
PRINT(_("Nothing to export. Please try compiling first..."));
clearCurrentOutput();
return;
}
QString csg_filename = QFileDialog::getSaveFileName(this, "Export CSG File",
this->fileName.isEmpty() ? "Untitled.csg" : QFileInfo(this->fileName).baseName()+".csg",
"CSG Files (*.csg)");
QString csg_filename = QFileDialog::getSaveFileName(this, _("Export CSG File"),
this->fileName.isEmpty() ? _("Untitled.csg") : QFileInfo(this->fileName).baseName()+".csg",
_("CSG Files (*.csg)"));
if (csg_filename.isEmpty()) {
PRINT("No filename specified. CSG export aborted.");
PRINT(_("No filename specified. CSG export aborted."));
clearCurrentOutput();
return;
}
std::ofstream fstream(csg_filename.toUtf8());
if (!fstream.is_open()) {
PRINTB("Can't open file \"%s\" for export", csg_filename.toLocal8Bit().constData());
PRINTB(_("Can't open file \"%s\" for export"), csg_filename.toLocal8Bit().constData());
}
else {
fstream << this->tree.getString(*this->root_node) << "\n";
fstream.close();
PRINT("CSG export finished.");
PRINT(_("CSG export finished."));
}
clearCurrentOutput();
@ -1559,9 +1559,9 @@ void MainWindow::actionExportImage()
setCurrentOutput();
QString img_filename = QFileDialog::getSaveFileName(this,
"Export Image", "", "PNG Files (*.png)");
_("Export Image"), "", _("PNG Files (*.png)"));
if (img_filename.isEmpty()) {
PRINT("No filename specified. Image export aborted.");
PRINT(_("No filename specified. Image export aborted."));
} else {
qglview->save(img_filename.toLocal8Bit().constData());
}
@ -1828,7 +1828,7 @@ void MainWindow::helpLibrary()
info += QString( qglview->getRendererInfo().c_str() );
if (!this->openglbox) {
this->openglbox = new QMessageBox(QMessageBox::Information,
"OpenGL Info", "OpenSCAD Detailed Library and Build Information",
_("OpenGL Info"), _("OpenSCAD Detailed Library and Build Information"),
QMessageBox::Ok, this);
}
this->openglbox->setDetailedText( info );
@ -1843,10 +1843,9 @@ MainWindow::maybeSave()
{
if (editor->isContentModified()) {
QMessageBox::StandardButton ret;
ret = QMessageBox::warning(this, "Application",
"The document has been modified.\n"
"Do you want to save your changes?",
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
ret = QMessageBox::warning(this, _("Application"),
_("The document has been modified.\n"
"Do you want to save your changes?"));
if (ret == QMessageBox::Save) {
actionSave();
return true; // FIXME: Should return false on error

View File

@ -295,7 +295,7 @@ bool FileModule::handleDependencies()
if (!newmodule) {
// Only print warning if we're not part of an automatic reload
if (!oldmodule && !wasmissing) {
PRINTB_NOCACHE("WARNING: Failed to compile library '%s'.", filename);
PRINTB_NOCACHE(_("WARNING: Failed to compile library '%s'."), filename);
}
}
}

View File

@ -104,7 +104,7 @@ static void help(const char *progname)
for (int i=0;i<tablen;i++) tabstr[i] = ' ';
tabstr[tablen] = '\0';
PRINTB("Usage: %1% [ -o output_file [ -d deps_file ] ]\\\n"
PRINTB(_("Usage: %1% [ -o output_file [ -d deps_file ] ]\\\n"
"%2%[ -m make_command ] [ -D var=val [..] ] \\\n"
"%2%[ --version ] [ --info ] \\\n"
"%2%[ --camera=translatex,y,z,rotx,y,z,dist | \\\n"
@ -112,7 +112,7 @@ static void help(const char *progname)
"%2%[ --imgsize=width,height ] [ --projection=(o)rtho|(p)ersp] \\\n"
"%2%[ --render | --preview[=throwntogether] ] \\\n"
"%2%[ --enable=<feature> ] \\\n"
"%2%filename\n",
"%2%filename\n"),
progname % (const char *)tabstr);
exit(1);
}
@ -121,7 +121,7 @@ static void help(const char *progname)
#define TOSTRING(x) STRINGIFY(x)
static void version()
{
PRINTB("OpenSCAD version %s\n", TOSTRING(OPENSCAD_VERSION));
PRINTB(_("OpenSCAD version %s\n"), TOSTRING(OPENSCAD_VERSION));
exit(1);
}
@ -560,6 +560,11 @@ int gui(const vector<string> &inputFiles, const fs::path &original_path, int arg
int main(int argc, char **argv)
{
int rc = 0;
setlocale(LC_ALL,"");
bindtextdomain("openscad","./po");
textdomain("openscad");
#ifdef Q_WS_MAC
set_output_handler(CocoaUtils::nslog, NULL);
#endif
@ -575,7 +580,7 @@ int main(int argc, char **argv)
const char *output_file = NULL;
const char *deps_output_file = NULL;
po::options_description desc("Allowed options");
po::options_description desc(_("Allowed options"));
desc.add_options()
("help,h", "help message")
("version,v", "print the version")
@ -593,7 +598,7 @@ int main(int argc, char **argv)
("D,D", po::value<vector<string> >(), "var=val")
("enable", po::value<vector<string> >(), "enable experimental features");
po::options_description hidden("Hidden options");
po::options_description hidden(_("Hidden options"));
hidden.add_options()
("input-file", po::value< vector<string> >(), "input file");
@ -629,12 +634,12 @@ int main(int argc, char **argv)
output_file = vm["o"].as<string>().c_str();
}
if (vm.count("s")) {
PRINT("DEPRECATED: The -s option is deprecated. Use -o instead.\n");
PRINT(_("DEPRECATED: The -s option is deprecated. Use -o instead.\n"));
if (output_file) help(argv[0]);
output_file = vm["s"].as<string>().c_str();
}
if (vm.count("x")) {
PRINT("DEPRECATED: The -x option is deprecated. Use -o instead.\n");
PRINT(_("DEPRECATED: The -x option is deprecated. Use -o instead.\n"));
if (output_file) help(argv[0]);
output_file = vm["x"].as<string>().c_str();
}
@ -691,7 +696,7 @@ int main(int argc, char **argv)
rc = gui(inputFiles, original_path, argc, argv);
}
else {
PRINT("Requested GUI mode but can't open display!\n");
PRINT(_("Requested GUI mode but can't open display!\n"));
help(argv[0]);
}

View File

@ -24,6 +24,7 @@
*
*/
#include "printutils.h"
#include "polyset.h"
#include "linalg.h"
#include "printutils.h"
@ -59,23 +60,23 @@ PolySet::~PolySet()
std::string PolySet::dump() const
{
std::stringstream out;
out << "PolySet:"
<< "\n dimensions:" << this->dim
<< "\n convexity:" << this->convexity
<< "\n num polygons: " << polygons.size()
<< "\n num outlines: " << polygon.outlines().size()
<< "\n polygons data:";
out << _("PolySet:")
<< _("\n dimensions:") << this->dim
<< _("\n convexity:") << this->convexity
<< _("\n num polygons: ") << polygons.size()
<< _("\n num outlines: ") << polygon.outlines().size()
<< _("\n polygons data:");
for (size_t i = 0; i < polygons.size(); i++) {
out << "\n polygon begin:";
out << _("\n polygon begin:");
const Polygon *poly = &polygons[i];
for (size_t j = 0; j < poly->size(); j++) {
Vector3d v = poly->at(j);
out << "\n vertex:" << v.transpose();
out << _("\n vertex:") << v.transpose();
}
}
out << "\n outlines data:";
out << _("\n outlines data:");
out << polygon.dump();
out << "\nPolySet end";
out << _("\nPolySet end");
return out.str();
}

View File

@ -184,11 +184,11 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
node->fa = c.lookup_variable("$fa").toDouble();
if (node->fs < F_MINIMUM) {
PRINTB("WARNING: $fs too small - clamping to %f", F_MINIMUM);
PRINTB(_("WARNING: $fs too small - clamping to %f"), F_MINIMUM);
node->fs = F_MINIMUM;
}
if (node->fa < F_MINIMUM) {
PRINTB("WARNING: $fa too small - clamping to %f", F_MINIMUM);
PRINTB(_("WARNING: $fa too small - clamping to %f"), F_MINIMUM);
node->fa = F_MINIMUM;
}
@ -572,7 +572,7 @@ Geometry *PrimitiveNode::createGeometry() const
const Value &val = vec[i];
if (!val.getVec2(x, y) ||
isinf(x) || isinf(y)) {
PRINTB("ERROR: Unable to convert point %s at index %d to a vec2 of numbers",
PRINTB(_("ERROR: Unable to convert point %s at index %d to a vec2 of numbers"),
val.toString() % i);
delete p;
return NULL;

View File

@ -6,6 +6,10 @@
#include <iostream>
#include <boost/format.hpp>
#include <libintl.h>
#include <locale.h>
inline char * _( const char * msgid ) { return gettext( msgid ); }
typedef void (OutputHandlerFunc)(const std::string &msg, void *userdata);
extern OutputHandlerFunc *outputhandler;
extern void *outputhandler_data;

18
src/qtgettext.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef __openscad_qtgettext_h__
#define __openscad_qtgettext_h__
// see doc/translation.txt
#include "printutils.h"
#include <libintl.h>
#include <locale.h>
#include <QString>
inline QString _( const char *msgid, int category )
{
Q_UNUSED( category );
return QString::fromUtf8( _( msgid ) );
}
#endif

View File

@ -68,7 +68,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI
Value scale = c.lookup_variable("scale", true);
if (!file.isUndefined()) {
PRINT("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead.");
PRINT(_("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead."));
node->filename = lookup_file(file.toString(), inst->path(), c.documentPath());
}

View File

@ -104,7 +104,7 @@ Geometry *SurfaceNode::createGeometry() const
std::ifstream stream(filename.c_str());
if (!stream.good()) {
PRINTB("WARNING: Can't open DAT file '%s'.", filename);
PRINTB(_("WARNING: Can't open DAT file '%s'."), filename);
return NULL;
}
@ -136,7 +136,7 @@ Geometry *SurfaceNode::createGeometry() const
}
catch (const boost::bad_lexical_cast &blc) {
if (!stream.eof()) {
PRINTB("WARNING: Illegal value in '%s': %s", filename % blc.what());
PRINTB(_("WARNING: Illegal value in '%s': %s"), filename % blc.what());
}
break;
}