Browse Source

Add initial source code and .pro file

Neal Wilson 8 years ago
parent
commit
9872412649
2 changed files with 314 additions and 0 deletions
  1. 302
    0
      src/main.cpp
  2. 12
    0
      src/ttsg.pro

+ 302
- 0
src/main.cpp View File

@@ -0,0 +1,302 @@
1
+// ttsg
2
+// Typica .ts Generator
3
+// This is a program that scrapes configuration files for Typica
4
+// and generates a .ts file translators can use so that user
5
+// visible text in a configuration can be translated into another
6
+// language.
7
+//
8
+// This is very slapdash with a minimal feature set focusing on
9
+// having something usable for initial translations starting with
10
+// the Typica 1.7 release. There are certain valid Typica
11
+// configurations that this will fail on. This is very much
12
+// tailored to use with the currently provided example
13
+// configuration. If you're using Typica for something strange
14
+// this tool might need to be altered.
15
+//
16
+// Copyright 2016, Neal Evan Wilson
17
+// See LICENSE for more details.
18
+
19
+#include <QCoreApplication>
20
+#include <QString>
21
+#include <QStringList>
22
+#include <QFile>
23
+#include <QFileInfo>
24
+#include <QDir>
25
+#include <QDomDocument>
26
+#include <QDomElement>
27
+#include <QXmlStreamWriter>
28
+#include <QtDebug>
29
+
30
+struct Context
31
+{
32
+    QString name;
33
+    QString filename;
34
+    QStringList messages;
35
+    QStringList locations;
36
+    QString reportDirectory;
37
+};
38
+
39
+Context* buildContext(QString filename, QString basedir);
40
+int generate(QString configfile, QString transfile);
41
+int main(int argc, char **argv);
42
+
43
+// Create a Context* with messages from a file.
44
+Context* buildContext(QString filename, QString basedir)
45
+{
46
+    Context *context = new Context;
47
+    context->filename = filename;
48
+    QFile source(QString("%1/%2").arg(basedir).arg(filename));
49
+    if(source.open(QIODevice::ReadOnly))
50
+    {
51
+        QDomDocument document;
52
+        document.setContent(&source, true);
53
+        QDomElement root = document.documentElement();
54
+        context->name = root.attribute("id");
55
+        QDomNodeList currentSet = document.elementsByTagName("button");
56
+        QDomNode currentNode;
57
+        QDomElement currentElement;
58
+        for(int i = 0; i < currentSet.length(); i++)
59
+        {
60
+            currentNode = currentSet.at(i);
61
+            context->locations.append(QString("%1").arg(currentNode.lineNumber()));
62
+            currentElement = currentNode.toElement();
63
+            context->messages.append(currentElement.attribute("name"));
64
+        }
65
+        currentSet = document.elementsByTagName("reporttitle");
66
+        for(int i = 0; i < currentSet.length(); i++)
67
+        {
68
+            currentNode = currentSet.at(i);
69
+            context->locations.append(QString("%1").arg(currentNode.lineNumber()));
70
+            currentElement = currentNode.toElement();
71
+            context->messages.append(currentElement.text());
72
+        }
73
+        currentSet = document.elementsByTagName("menu");
74
+        for(int i = 0; i < currentSet.length(); i++)
75
+        {
76
+            currentNode = currentSet.at(i);
77
+            context->locations.append(QString("%1").arg(currentNode.lineNumber()));
78
+            currentElement = currentNode.toElement();
79
+            context->messages.append(currentElement.attribute("name"));
80
+            if(currentElement.attribute("type") == "reports")
81
+            {
82
+                context->reportDirectory = currentElement.attribute("src");
83
+            }
84
+        }
85
+        currentSet = document.elementsByTagName("item");
86
+        for(int i = 0; i < currentSet.length(); i++)
87
+        {
88
+            currentNode = currentSet.at(i);
89
+            context->locations.append(QString("%1").arg(currentNode.lineNumber()));
90
+            currentElement = currentNode.toElement();
91
+            context->messages.append(currentElement.text());
92
+        }
93
+        currentSet = document.elementsByTagName("label");
94
+        for(int i = 0; i < currentSet.length(); i++)
95
+        {
96
+            currentNode = currentSet.at(i);
97
+            context->locations.append(QString("%1").arg(currentNode.lineNumber()));
98
+            currentElement = currentNode.toElement();
99
+            context->messages.append(currentElement.text());
100
+        }
101
+        currentSet = document.elementsByTagName("decoration");
102
+        for(int i = 0; i < currentSet.length(); i++)
103
+        {
104
+            currentNode = currentSet.at(i);
105
+            context->locations.append(QString("%1").arg(currentNode.lineNumber()));
106
+            currentElement = currentNode.toElement();
107
+            context->messages.append(currentElement.attribute("name"));
108
+        }
109
+        currentSet = document.elementsByTagName("spinbox");
110
+        for(int i = 0; i < currentSet.length(); i++)
111
+        {
112
+            currentNode = currentSet.at(i);
113
+            currentElement = currentNode.toElement();
114
+            if(currentElement.hasAttribute("pretext"))
115
+            {
116
+                context->locations.append(QString("%1").arg(currentNode.lineNumber()));
117
+                context->messages.append(currentElement.attribute("pretext"));
118
+            }
119
+            if(currentElement.hasAttribute("posttext"))
120
+            {
121
+                context->locations.append(QString("%1").arg(currentNode.lineNumber()));
122
+                context->messages.append(currentElement.attribute("posttext"));
123
+            }
124
+        }
125
+        currentSet = document.elementsByTagName("measurementtable");
126
+        for(int i = 0; i < currentSet.length(); i++)
127
+        {
128
+            currentNode = currentSet.at(i);
129
+            currentElement = currentNode.toElement();
130
+            if(currentElement.hasChildNodes())
131
+            {
132
+                for(int j = 0; j < currentElement.childNodes().count(); j++)
133
+                {
134
+                    QDomNode childNode = currentElement.childNodes().at(j);
135
+                    if(childNode.isElement())
136
+                    {
137
+                        QDomElement childElement = childNode.toElement();
138
+                        if(childElement.tagName() == "column")
139
+                        {
140
+                            context->locations.append(QString("%1").arg(childNode.lineNumber()));
141
+                            context->messages.append(childElement.text());
142
+                        }
143
+                    }
144
+                }
145
+            }
146
+        }
147
+        currentSet = document.elementsByTagName("sqltablearray");
148
+        for(int i = 0; i < currentSet.length(); i++)
149
+        {
150
+            currentNode = currentSet.at(i);
151
+            currentElement = currentNode.toElement();
152
+            if(currentElement.hasChildNodes())
153
+            {
154
+                for(int j = 0; j < currentElement.childNodes().count(); j++)
155
+                {
156
+                    QDomNode childNode = currentElement.childNodes().at(j);
157
+                    if(childNode.isElement())
158
+                    {
159
+                        QDomElement childElement = childNode.toElement();
160
+                        if(childElement.tagName() == "column")
161
+                        {
162
+                            context->locations.append(QString("%1").arg(childNode.lineNumber()));
163
+                            context->messages.append(childElement.attribute("name"));
164
+                        }
165
+                    }
166
+                }
167
+            }
168
+        }
169
+        currentSet = document.elementsByTagName("program");
170
+        for(int i = 0; i < currentSet.length(); i++)
171
+        {
172
+            currentNode = currentSet.at(i);
173
+            currentElement = currentNode.toElement();
174
+            QString script = currentElement.text();
175
+            QStringList scriptLines = script.split("\n");
176
+            for(int j = 0; j < scriptLines.length(); j++)
177
+            {
178
+                if(scriptLines.at(j).contains("TTR"))
179
+                {
180
+                    QString currentLine = scriptLines.at(j);
181
+                    context->locations.append(QString("%1").arg(currentNode.lineNumber() + j + 1));
182
+                    currentLine = currentLine.remove(0, currentLine.indexOf("TTR"));
183
+                    currentLine = currentLine.remove(0, currentLine.indexOf("\"")+1);
184
+                    currentLine = currentLine.remove(0, currentLine.indexOf("\"")+1);
185
+                    currentLine = currentLine.remove(0, currentLine.indexOf("\"")+1);
186
+                    currentLine = currentLine.remove(currentLine.indexOf("\""), currentLine.length());
187
+                    context->messages.append(currentLine);
188
+                }
189
+            }
190
+        }
191
+    }
192
+    source.close();
193
+    return context;
194
+}
195
+
196
+// Produce a .ts file from a Typica configuration file.
197
+int generate(QString configfile, QString transfile)
198
+{
199
+    QFile source(configfile);
200
+    QFileInfo info(configfile);
201
+    QDir directory = info.dir();
202
+    if(!source.open(QIODevice::ReadOnly))
203
+    {
204
+        qDebug() << "Failed to open: " << configfile;
205
+        return 1;
206
+    }
207
+    QDomDocument configuration;
208
+    configuration.setContent(&source, true);
209
+    QDomElement root = configuration.documentElement();
210
+    QDomNodeList children = root.childNodes();
211
+    QList<Context *> contexts;
212
+    for(int i = 0; i < children.size(); i++)
213
+    {
214
+        QDomNode currentNode = children.at(i);
215
+        QDomElement currentElement;
216
+        if(currentNode.nodeName() == "include")
217
+        {
218
+            currentElement = currentNode.toElement();
219
+            if(currentElement.hasAttribute("src"))
220
+            {
221
+                Context *context = buildContext(currentElement.attribute("src"), directory.path());
222
+                if(context)
223
+                {
224
+                    contexts.append(context);
225
+                    if(context->reportDirectory.length() > 0)
226
+                    {
227
+                        QDir reportsDirectory(QString("%1/%2").arg(directory.path()).arg(context->reportDirectory));
228
+                        reportsDirectory.setFilter(QDir::Files);
229
+                        reportsDirectory.setSorting(QDir::Name);
230
+                        QStringList nameFilter;
231
+                        nameFilter << "*.xml";
232
+                        reportsDirectory.setNameFilters(nameFilter);
233
+                        QStringList reportFiles = reportsDirectory.entryList();
234
+                        for(int j = 0; j < reportFiles.size(); j++)
235
+                        {
236
+                            Context *reportContext = buildContext(QString("%1/%2").arg(context->reportDirectory).arg(reportFiles.at(j)), directory.path());
237
+                            if(reportContext)
238
+                            {
239
+                                contexts.append(reportContext);
240
+                            }
241
+                        }
242
+                    }
243
+                }
244
+            }
245
+        }
246
+    }
247
+    source.close();
248
+    QFile ts(transfile);
249
+    if(!ts.open(QIODevice::WriteOnly | QIODevice::Text))
250
+    {
251
+        qDebug() << "Failed to open output file: " << transfile;
252
+        return 1;
253
+    }
254
+    QXmlStreamWriter xmlout(&ts);
255
+    xmlout.setAutoFormatting(true);
256
+    xmlout.writeStartDocument("1.0");
257
+    xmlout.writeDTD("<!DOCTYPE TS>");
258
+    xmlout.writeStartElement("TS");
259
+    xmlout.writeAttribute("version", "2.0");
260
+    foreach(Context *c, contexts)
261
+    {
262
+        xmlout.writeStartElement("context");
263
+        xmlout.writeStartElement("name");
264
+        xmlout.writeCharacters(c->name);
265
+        xmlout.writeEndElement();
266
+        for(int i = 0; i < c->messages.length(); i++)
267
+        {
268
+            xmlout.writeStartElement("message");
269
+            xmlout.writeStartElement("location");
270
+            xmlout.writeAttribute("filename", c->filename);
271
+            xmlout.writeAttribute("line", c->locations.at(i));
272
+            xmlout.writeEndElement();
273
+            xmlout.writeStartElement("source");
274
+            xmlout.writeCharacters(c->messages.at(i));
275
+            xmlout.writeEndElement();
276
+            xmlout.writeStartElement("translation");
277
+            xmlout.writeCharacters("Translated");
278
+            xmlout.writeEndElement();
279
+            xmlout.writeEndElement();
280
+        }
281
+        xmlout.writeEndElement();
282
+    }
283
+    xmlout.writeEndElement();
284
+    xmlout.writeEndDocument();
285
+    ts.close();
286
+    return 0;
287
+}
288
+
289
+// Take the source and destination files from the command line arguments and
290
+// pass them to generate.
291
+int main(int argc, char **argv)
292
+{
293
+    QCoreApplication app(argc, argv);
294
+    QStringList arguments = app.arguments();
295
+    if(arguments.length() != 3) {
296
+        qDebug() << "Usage: ttsg configuration.xml translation.ts";
297
+        return 1;
298
+    }
299
+    QString configfile = arguments.at(1);
300
+    QString transfile = arguments.at(2);
301
+    return generate(configfile, transfile);
302
+}

+ 12
- 0
src/ttsg.pro View File

@@ -0,0 +1,12 @@
1
+######################################################################
2
+# Automatically generated by qmake (3.0) Tue Jan 5 15:52:13 2016
3
+######################################################################
4
+
5
+TEMPLATE = app
6
+TARGET = ttsg
7
+INCLUDEPATH += .
8
+
9
+QT += xml
10
+
11
+# Input
12
+SOURCES += main.cpp

Loading…
Cancel
Save