* runtime - loading and translating * design-time - works with *.ts file (pip_tr utility) * compile-time - CMake macro for compile *.ts
152 lines
5.3 KiB
C++
152 lines
5.3 KiB
C++
/*
|
|
PIP - Platform Independent Primitives
|
|
ValueTree translator
|
|
Ivan Pelipenko peri4ko@yandex.ru
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "picli.h"
|
|
#include "pidir.h"
|
|
#include "pifile.h"
|
|
#include "pijson.h"
|
|
#include "pivaluetree.h"
|
|
#include "pivaluetree_conversions.h"
|
|
#include "ts_file.h"
|
|
|
|
using namespace PICoutManipulators;
|
|
using Attribute = PIValueTree::Attribute;
|
|
|
|
const char help_string[] = "Read input files or entire directories as PIValueTree\n"
|
|
"according to extension, and create QtLinguist translation\n"
|
|
"file (*.ts). Extensions:\n"
|
|
" * conf - PIValueTreeConversions::fromText\n"
|
|
" * json - PIValueTreeConversions::fromJSON\n"
|
|
" * bin - binary deserialization\n"
|
|
"Output file can be translated by QtLinguist and used\n"
|
|
"by QAD PIValueTreeEdit widget to translate strings.\n"
|
|
"";
|
|
|
|
void header() {
|
|
piCout << Bold << "PIP ValueTree translator";
|
|
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
|
piCout << Green << Bold << "Usage:" << Default
|
|
<< "\"pip_vtt [-hHqn] -l <lang> -o <output_file> <file1/dir1> [<file2/dir2>] [<file3/dir3>] [...]\"" << NewLine;
|
|
}
|
|
|
|
void usage() {
|
|
header();
|
|
piCout << Green << Bold << "Details:";
|
|
piCout << Bold << "Debug control";
|
|
piCout << "-h " << Green << "- display this message and exit";
|
|
piCout << "-H " << Green << "- display details help";
|
|
piCout << "-q " << Green << "- quiet, no debug output to console";
|
|
piCout << "";
|
|
piCout << Bold << "Output control";
|
|
piCout << "-l <lang> " << Green << "- translation language (e.g. en_US, ru_RU)";
|
|
piCout << "-n, --no-obsolete " << Green << "- drop unused translations in output file";
|
|
piCout << "-o <output_file> " << Green << "- output file for translation (QtLinguist *.ts file)";
|
|
piCout << "";
|
|
piCout << Bold << "Input control";
|
|
piCout << "<file/dir> " << Green << "- add file or dir translation";
|
|
}
|
|
|
|
void help() {
|
|
header();
|
|
piCout << help_string;
|
|
}
|
|
|
|
|
|
const PIString contextName = "QAD::PIValueTreeEdit";
|
|
|
|
|
|
void gatherStrings(TSFile::Context & context, const PIValueTree & vt, const PIString & loc) {
|
|
const static PIStringList attrs({Attribute::prefix, Attribute::suffix});
|
|
for (const auto & c: vt.children()) {
|
|
context.confirm(c.name(), loc);
|
|
context.confirm(c.comment(), loc);
|
|
for (const auto & a: attrs) {
|
|
if (c.attributes().contains(a)) {
|
|
context.confirm(c.attributes().value(a).toString(), loc);
|
|
}
|
|
}
|
|
if (!c.isArray()) gatherStrings(context, c, loc);
|
|
}
|
|
}
|
|
|
|
|
|
int main(int argc, char * argv[]) {
|
|
PICLI cli(argc, argv);
|
|
// piCout << cli.rawArguments();
|
|
cli.setOptionalArgumentsCount(-1);
|
|
cli.addArgument("output", true);
|
|
cli.addArgument("language", true);
|
|
cli.addArgument("help");
|
|
cli.addArgument("Help");
|
|
cli.addArgument("quiet");
|
|
cli.addArgument("no-obsolete");
|
|
if (cli.hasArgument("Help")) {
|
|
help();
|
|
return 0;
|
|
}
|
|
if (cli.hasArgument("help") || cli.argumentValue("output").isEmpty() || cli.argumentValue("language").isEmpty() ||
|
|
cli.optionalArguments().isEmpty()) {
|
|
usage();
|
|
return 0;
|
|
}
|
|
piDebug = !cli.hasArgument("quiet");
|
|
PIString out_path = cli.argumentValue("output");
|
|
|
|
PIStringList files;
|
|
const static PIStringList ext({"conf", "json", "bin"});
|
|
for (const PIString & a: cli.optionalArguments()) {
|
|
if (PIDir::isExists(a)) {
|
|
auto dl = PIDir(a).allEntries();
|
|
for (const auto & i: dl) {
|
|
if (!i.isFile()) continue;
|
|
if (ext.contains(i.extension().toLowerCase().trim())) files << i.path;
|
|
}
|
|
} else {
|
|
if (PIFile::isExists(a)) files << a;
|
|
}
|
|
}
|
|
|
|
piCout << Cyan << Bold << "Reading ts file ...";
|
|
auto content = TSFile::read(out_path);
|
|
if (content.lang.isEmpty()) content.lang = cli.argumentValue("language");
|
|
content.markAllMissing();
|
|
piCout << Cyan << Bold << "Reading done";
|
|
|
|
piCout << Cyan << Bold << "Read" << files.size_s() << "files ...";
|
|
auto & context(content.contexts[contextName]);
|
|
PIDir out_dir(PIFile::FileInfo(out_path).dir());
|
|
for (const auto & p: files) {
|
|
PIString ext = PIFile::FileInfo(p).extension().toLowerCase().trim();
|
|
PIFile f(p, PIIODevice::ReadOnly);
|
|
if (ext == "conf") gatherStrings(context, PIValueTreeConversions::fromText(PIString::fromUTF8(f.readAll())), out_dir.relative(p));
|
|
if (ext == "json")
|
|
gatherStrings(context,
|
|
PIValueTreeConversions::fromJSON(PIJSON::fromJSON(PIString::fromUTF8(f.readAll()))),
|
|
out_dir.relative(p));
|
|
if (ext == "bin") gatherStrings(context, piDeserialize<PIValueTree>(f.readAll()), PIString());
|
|
}
|
|
piCout << Cyan << Bold << "Reading done";
|
|
|
|
piCout << Cyan << Bold << "Writing ts file ...";
|
|
if (!TSFile::write(out_path, content, cli.hasArgument("no-obsolete"))) return 1;
|
|
piCout << Cyan << Bold << "Writing done";
|
|
|
|
return 0;
|
|
}
|