[rkward-cvs] SF.net SVN: rkward-code:[4929] trunk/rkward
tfry at users.sf.net
tfry at users.sf.net
Sat Oct 18 13:39:22 UTC 2014
Revision: 4929
http://sourceforge.net/p/rkward/code/4929
Author: tfry
Date: 2014-10-18 13:39:21 +0000 (Sat, 18 Oct 2014)
Log Message:
-----------
Ok, the first few strings from pluginmaps are actually translatable, now.
Modified Paths:
--------------
trunk/rkward/ChangeLog
trunk/rkward/rkward/main.cpp
trunk/rkward/rkward/misc/rkmessagecatalog.cpp
trunk/rkward/rkward/misc/rkmessagecatalog.h
trunk/rkward/rkward/misc/xmlhelper.cpp
trunk/rkward/rkward/misc/xmlhelper.h
trunk/rkward/rkward/plugin/rkcomponentmap.cpp
trunk/rkward/rkward/plugins/analysis.pluginmap
Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog 2014-10-18 11:20:39 UTC (rev 4928)
+++ trunk/rkward/ChangeLog 2014-10-18 13:39:21 UTC (rev 4929)
@@ -1,5 +1,9 @@
- Fixed some erroneous plugin debug messages
- IN PROGESS: Allow plugins to be translated
+ + Notes:
+ - Is it a problem to sync KDE_LANG and LANGUAGE? Should that also be set for the backend?
+ - Message extraction: Should we do this in R, using XiMpLe? That might allow us to give better context / comments
+ - Don't forget to write documentation
--- Version 0.6.2 - Oct-20-2014
- In data editor, indicate NAs, explicitly
Modified: trunk/rkward/rkward/main.cpp
===================================================================
--- trunk/rkward/rkward/main.cpp 2014-10-18 11:20:39 UTC (rev 4928)
+++ trunk/rkward/rkward/main.cpp 2014-10-18 13:39:21 UTC (rev 4929)
@@ -170,6 +170,9 @@
RKGlobals::startup_options["backend-debugger"] = decodeArgument (args->getOption ("backend-debugger"));
RKWardApplication app;
+ // No, I do not really understand the point of separating KDE_LANG from LANGUAGE. We do honor it in so far as not
+ // forcing LANGUAGE on the backend, though. Having language as LANGUAGE makes code in RKMessageCatalog much easier compared to KCatalog.
+ qputenv ("LANGUAGE", QFile::encodeName (KGlobal::locale ()->language ()));
// install message handler *after* the componentData has been initialized
RKSettingsModuleDebug::debug_file = new QTemporaryFile (QDir::tempPath () + "/rkward.frontend");
RKSettingsModuleDebug::debug_file->setAutoRemove (false);
Modified: trunk/rkward/rkward/misc/rkmessagecatalog.cpp
===================================================================
--- trunk/rkward/rkward/misc/rkmessagecatalog.cpp 2014-10-18 11:20:39 UTC (rev 4928)
+++ trunk/rkward/rkward/misc/rkmessagecatalog.cpp 2014-10-18 13:39:21 UTC (rev 4929)
@@ -2,7 +2,7 @@
rkmessagecatalog - description
-------------------
begin : Mon Jun 24 2013
- copyright : (C) 2013 by Thomas Friedrichsmeier
+ copyright : (C) 2013, 2014 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -22,12 +22,18 @@
#include "../debug.h"
+// statics
+QHash<QString, RKMessageCatalog*> RKMessageCatalog::catalogs;
+QMutex RKMessageCatalog::setup_mutex;
+RKMessageCatalog* RKMessageCatalog::null_catalog = 0;
+
RKMessageCatalog::RKMessageCatalog (const QString &name, const QString& path) {
RK_TRACE (MISC);
- bound = false;
- catalog_path = path;
catalog_name = QFile::encodeName (name);
+ char *res = bindtextdomain (catalog_name, QFile::encodeName (path));
+ RK_DO (qDebug ("Opening catalog %s, expected at %s, found at %s", qPrintable (name), qPrintable (path), res), MISC, DL_WARNING);
+ bind_textdomain_codeset (catalog_name, "UTF-8");
}
RKMessageCatalog::~RKMessageCatalog () {
@@ -40,7 +46,6 @@
QString RKMessageCatalog::translate (const QString &msgctxt, const QString &msgid) const {
RK_TRACE (MISC);
- if (!bound) const_cast<RKMessageCatalog *> (this)->setup ();
QByteArray key = (msgctxt + GETTEXT_CONTEXT_GLUE + msgid).toUtf8 ();
const char *trans = dgettext (catalog_name, key);
@@ -50,19 +55,29 @@
QString RKMessageCatalog::translate (const QString &msgid) const {
RK_TRACE (MISC);
- if (!bound) const_cast<RKMessageCatalog *> (this)->setup ();
return QString::fromUtf8 (dgettext (catalog_name, msgid.toUtf8 ()));
}
-void RKMessageCatalog::setup () {
+// static
+RKMessageCatalog* RKMessageCatalog::getCatalog (const QString& name, const QString& pathhint) {
RK_TRACE (MISC);
+ RKMessageCatalog *ret = catalogs.value (name, 0);
+ if (ret) return ret;
setup_mutex.lock ();
- if (!bound) {
- bindtextdomain (catalog_name, QFile::encodeName (catalog_path));
- bind_textdomain_codeset (catalog_name, "UTF-8");
- bound = true;
- }
+ // try to look up again, in case initialized from another thread
+ ret = catalogs.value (name, 0);
+ if (!ret) {
+ ret = new RKMessageCatalog (name, pathhint);
+ catalogs.insert (name, ret);
+ }
setup_mutex.unlock ();
+ return ret;
}
+
+RKMessageCatalog* RKMessageCatalog::nullCatalog () {
+ // ok, not thread-safe, here, but the worst that can happen is creating more than one dummy catalog.
+ if (!null_catalog) null_catalog = getCatalog ("rkward_dummy", QString ());
+ return null_catalog;
+}
Modified: trunk/rkward/rkward/misc/rkmessagecatalog.h
===================================================================
--- trunk/rkward/rkward/misc/rkmessagecatalog.h 2014-10-18 11:20:39 UTC (rev 4928)
+++ trunk/rkward/rkward/misc/rkmessagecatalog.h 2014-10-18 13:39:21 UTC (rev 4929)
@@ -2,7 +2,7 @@
rkmessagecatalog - description
-------------------
begin : Mon Jun 24 2013
- copyright : (C) 2013 by Thomas Friedrichsmeier
+ copyright : (C) 2013, 2014 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -20,25 +20,32 @@
#include <QString>
#include <QMutex>
+#include <QHash>
/** This class - heavily inspired by KCatalog - wraps a gettext message catalog. Contrary to KCatalog, this does not currently support using a language other than
- * the system language, or switching languages at runtime. It allows (the base directory of) message catalogs to be at an arbitrary location.
+ * the system language, or switching languages at runtime. It allows (the base directory of) message catalogs to be at an arbitrary location, however, which is
+ * important for plugins (installed at runtime and outside of system path)
*
* Also, msgids are passed as QStrings, since in our use cases, that's the source data format, anyway.
*/
class RKMessageCatalog {
public:
+ QString translate (const QString &msgctxt, const QString &msgid) const;
+ QString translate (const QString &msgid) const;
+
+/** Get the catalog identified by name. This could be an already open catalog, or a new one. In the latter case, the catalog is expected at pathhint. In the former case, pathhint is ignored. This function is guaranteed to return a non-null RKMessageCatalog, although that does not imply the catalog could actually be loaded. */
+ static RKMessageCatalog *getCatalog (const QString &name, const QString &pathhint);
+/** Returns a dummy null-catalog */
+ static RKMessageCatalog *nullCatalog ();
+private:
RKMessageCatalog (const QString &name, const QString &path);
~RKMessageCatalog ();
- QString translate (const QString &msgctxt, const QString &msgid) const;
- QString translate (const QString &msgid) const;
-private:
- void setup ();
- QString catalog_path;
QByteArray catalog_name;
- bool bound;
- QMutex setup_mutex;
+
+ static QHash<QString, RKMessageCatalog*> catalogs;
+ static QMutex setup_mutex;
+ static RKMessageCatalog *null_catalog;
};
#endif
Modified: trunk/rkward/rkward/misc/xmlhelper.cpp
===================================================================
--- trunk/rkward/rkward/misc/xmlhelper.cpp 2014-10-18 11:20:39 UTC (rev 4928)
+++ trunk/rkward/rkward/misc/xmlhelper.cpp 2014-10-18 13:39:21 UTC (rev 4929)
@@ -25,11 +25,15 @@
#include <qdir.h>
#include <QTextStream>
+#include <rkmessagecatalog.h>
+
#include "../debug.h"
-XMLHelper::XMLHelper (const QString &filename) {
+XMLHelper::XMLHelper (const QString &filename, const RKMessageCatalog *default_catalog) {
RK_TRACE (XML);
XMLHelper::filename = filename;
+ if (!default_catalog) catalog = RKMessageCatalog::nullCatalog ();
+ else catalog = default_catalog;
}
XMLHelper::~XMLHelper () {
@@ -52,6 +56,10 @@
f.close();
QDomElement ret = doc.documentElement ();
+ if (ret.hasAttribute ("po_id")) {
+ QDir path = QFileInfo (filename).absoluteDir ();
+ catalog = RKMessageCatalog::getCatalog ("rkward__" + ret.attribute ("po_id"), path.absoluteFilePath (getStringAttribute (ret, "po_path", "po", DL_INFO)));
+ }
if (with_includes) {
XMLChildList includes = nodeListToChildList (doc.elementsByTagName ("include"));
for (XMLChildList::const_iterator it = includes.constBegin (); it != includes.constEnd (); ++it) {
@@ -232,6 +240,19 @@
return (element.attribute (name));
}
+QString XMLHelper::i18nStringAttribute (const QDomElement& element, const QString& name, const QString& def, int debug_level) {
+ RK_TRACE (XML);
+ if (!element.hasAttribute (name)) {
+ const QString no18nname = "noi18n_" + name;
+ if (element.hasAttribute (no18nname)) return element.attribute (no18nname);
+ displayError (&element, i18n ("'%1'-attribute not given. Assuming '%2'", name, def), debug_level);
+ return def;
+ }
+ const QString context_element ("i18ncontext");
+ if (element.hasAttribute (context_element)) return (catalog->translate (context_element, element.attribute (name)));
+ return (catalog->translate (element.attribute (name)));
+}
+
int XMLHelper::getMultiChoiceAttribute (const QDomElement &element, const QString &name, const QString &values, int def, int debug_level) {
RK_TRACE (XML);
Modified: trunk/rkward/rkward/misc/xmlhelper.h
===================================================================
--- trunk/rkward/rkward/misc/xmlhelper.h 2014-10-18 11:20:39 UTC (rev 4928)
+++ trunk/rkward/rkward/misc/xmlhelper.h 2014-10-18 13:39:21 UTC (rev 4929)
@@ -20,6 +20,8 @@
#include <qdom.h>
+class RKMessageCatalog;
+
/** a helper type used to pass a list of direct child elements of a node */
typedef QList<QDomElement> XMLChildList;
@@ -33,11 +35,15 @@
class XMLHelper {
public:
/** create an instance of XMLHelper.
- @param filename the name of the file to parse. The file is not yet opened on construction. Use openXMLFile() for that. */
- XMLHelper (const QString &filename);
-/** destrcutor */
+ @param filename the name of the file to parse. The file is not yet opened on construction. Use openXMLFile() for that.
+ @param default_catalog message catalog to use in case none is specified in the xml file itself. */
+ XMLHelper (const QString &filename, const RKMessageCatalog *default_catalog=0);
+/** destructor */
~XMLHelper ();
-
+/** Return the a pointer to the message catalog in use. This may - or may not - be the same as specified as default catalog in the constructor.
+ Guaranteed to be non-null (but not guaranteed to be non-empty). */
+ const RKMessageCatalog *messageCatalog () const { return catalog; };
+
/** Open the filename set in the constructor (read-only) and do basic parsing. Internally, the file will be closed right away, so there is no need to call an additional closeFile-equivalent. Once the returned element (and any copies you make of it) goes out of scope, the entire element-tree allocated will be freed,
but you can re-open the file, if needed.
@param debug_level level of debug message to generate if opening/parsing fails
@@ -88,6 +94,8 @@
@param debug_level level of debug message to generate in case of failure (i.e. no such attribute was found)
@returns the value of the given attribute or the given default */
QString getStringAttribute (const QDomElement &element, const QString &name, const QString &def, int debug_level);
+/** same as getStringAttribute(), but tries to translate the string, before returning it. Does not translate def! */
+ QString i18nStringAttribute (const QDomElement &element, const QString &name, const QString &def, int debug_level);
/** checks whether the given attribute is one of the allowed string values and returns the number of the value in the list (or the default)
@param element the element whose attributes to search
@@ -114,7 +122,6 @@
@returns the value of the given attribute or the given default */
double getDoubleAttribute (const QDomElement &element, const QString &name, double def, int debug_level);
-
/** returns the value of a boolean attribute ("true" or "false")
@param element the element whose attributes to search
@param name the name of the attribute to read
@@ -135,12 +142,12 @@
@param debug_level the debug level to show the message at (highestError () will be adujsted if applicable)
@param message_level sometime you may want to make sure your message is being shown even if it is not very important to your code. For instance, if there is a typo/illegal value in an optional setting, your code can continue using a reasonable default, but the user should still be notified of this error. If you omit this parameter or set it to something smaller that debug_level, debug_level will be used instead. */
void displayError (const QDomNode *in_node, const QString &message, int debug_level, int message_level=-1);
-
private:
/** copy the node list into a child list. The main effect is that a child list is not updated according to document changes */
XMLChildList nodeListToChildList (const QDomNodeList &from);
void replaceWithChildren (QDomNode *replaced, const QDomElement &replacement_parent);
QString filename;
+ const RKMessageCatalog *catalog;
};
#endif
Modified: trunk/rkward/rkward/plugin/rkcomponentmap.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentmap.cpp 2014-10-18 11:20:39 UTC (rev 4928)
+++ trunk/rkward/rkward/plugin/rkcomponentmap.cpp 2014-10-18 13:39:21 UTC (rev 4929)
@@ -465,7 +465,7 @@
QString filename = xml.getStringAttribute((*it), "file", QString (), DL_WARNING);
int type = xml.getMultiChoiceAttribute ((*it), "type", "standard", 0, DL_WARNING);
- QString label = xml.getStringAttribute ((*it), "label", i18n ("(no label)"), DL_WARNING);
+ QString label = xml.i18nStringAttribute ((*it), "label", i18n ("(no label)"), DL_WARNING);
if (components.contains (id)) {
ret.addAndPrintError (DL_WARNING, i18n ("RKComponentMap already contains a component with id \"%1\". Ignoring second entry.", id));
Modified: trunk/rkward/rkward/plugins/analysis.pluginmap
===================================================================
--- trunk/rkward/rkward/plugins/analysis.pluginmap 2014-10-18 11:20:39 UTC (rev 4928)
+++ trunk/rkward/rkward/plugins/analysis.pluginmap 2014-10-18 13:39:21 UTC (rev 4929)
@@ -1,6 +1,6 @@
<!DOCTYPE rkpluginmap>
-<document base_prefix="" namespace="rkward" id="analysis">
+<document base_prefix="" namespace="rkward" id="analysis" po_id="analysis">
<include file="pluginmap_meta.inc"/>
<components>
More information about the rkward-tracker
mailing list