first release of translation facility
* runtime - loading and translating * design-time - works with *.ts file (pip_tr utility) * compile-time - CMake macro for compile *.ts
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include "picli.h"
|
||||
|
||||
#include "pisysteminfo.h"
|
||||
#include "pitranslator.h"
|
||||
|
||||
|
||||
//! \class PICLI picli.h
|
||||
@@ -116,7 +117,7 @@ void PICLI::parse() {
|
||||
_args_opt << cra;
|
||||
continue;
|
||||
}
|
||||
piCoutObj << "Arguments overflow, \"" << cra << "\" ignored";
|
||||
piCoutObj << "Arguments overflow, \"%1\" ignored"_tr("PICLI").arg(cra);
|
||||
}
|
||||
if (last == 0 ? false : last->has_value) {
|
||||
last->value = cra;
|
||||
|
||||
@@ -108,14 +108,14 @@ bool PISystemMonitor::startOnProcess(int pID, PISystemTime interval) {
|
||||
PRIVATE->file.open(PRIVATE->proc_dir + "stat", PIIODevice::ReadOnly);
|
||||
PRIVATE->filem.open(PRIVATE->proc_dir + "statm", PIIODevice::ReadOnly);
|
||||
if (!PRIVATE->file.isOpened()) {
|
||||
piCoutObj << "Can`t find process with ID = " << pID_ << "!";
|
||||
piCoutObj << "Can`t find process with ID = %1!"_tr("PISystemMonitor").arg(pID_);
|
||||
return false;
|
||||
}
|
||||
# endif
|
||||
# else
|
||||
PRIVATE->hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID_);
|
||||
if (PRIVATE->hProc == 0) {
|
||||
piCoutObj << "Can`t open process with ID = "_tr << pID_ << "," << errorString();
|
||||
piCoutObj << "Can`t open process with ID = %1, %2!"_tr("PISystemMonitor").arg(pID_).arg(errorString());
|
||||
return false;
|
||||
}
|
||||
PRIVATE->tm.reset();
|
||||
@@ -377,12 +377,12 @@ void PISystemMonitor::gatherThread(llong id) {
|
||||
FILETIME times[4];
|
||||
HANDLE thdl = OpenThread(THREAD_QUERY_INFORMATION, FALSE, DWORD(id));
|
||||
if (!thdl) {
|
||||
piCout << "[PISystemMonitor] gatherThread(" << id << "):: OpenThread() error:" << errorString();
|
||||
piCoutObj << "GatherThread(" << id << "):: OpenThread() error:" << errorString();
|
||||
return;
|
||||
}
|
||||
if (GetThreadTimes(thdl, &(times[0]), &(times[1]), &(times[2]), &(times[3])) == 0) {
|
||||
CloseHandle(thdl);
|
||||
piCout << "[PISystemMonitor] gatherThread(" << id << "):: GetThreadTimes() error:" << errorString();
|
||||
piCoutObj << "GatherThread(" << id << "):: GetThreadTimes() error:" << errorString();
|
||||
return;
|
||||
}
|
||||
CloseHandle(thdl);
|
||||
|
||||
@@ -19,8 +19,11 @@
|
||||
|
||||
#include "pitranslator.h"
|
||||
|
||||
#include "pidir.h"
|
||||
#include "pifile.h"
|
||||
#include "piliterals_string.h"
|
||||
#include "pitranslator_p.h"
|
||||
#include "pivaluetree_conversions.h"
|
||||
#include "tr/pip_all.h"
|
||||
|
||||
|
||||
//! \class PITranslator pitranslator.h
|
||||
@@ -33,28 +36,38 @@
|
||||
//!
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PITranslator)
|
||||
PITranslatorPrivate::Translation content;
|
||||
PRIVATE_DEFINITION_END(PITranslator)
|
||||
|
||||
|
||||
PIString PITranslator::tr(const PIString & in, const PIString & context) {
|
||||
auto s = instance();
|
||||
auto c = s->contexts.value(context.hash());
|
||||
if (!c) return in;
|
||||
return c->strings.value(in.hash(), in);
|
||||
return instance()->PRIVATEWB->content.translate(in, context);
|
||||
}
|
||||
|
||||
|
||||
void PITranslator::clear() {
|
||||
instance()->clearInternal();
|
||||
instance()->PRIVATEWB->content.clear();
|
||||
}
|
||||
|
||||
|
||||
void PITranslator::loadLang(const PIString & short_lang) {
|
||||
auto s = instance();
|
||||
void PITranslator::loadLang(const PIString & short_lang, PIString dir) {
|
||||
if (dir.isEmpty()) dir = PIDir::current().absolute("lang");
|
||||
clear();
|
||||
auto files = PIDir(dir).entries();
|
||||
for (const auto & f: files) {
|
||||
if (!f.baseName().endsWith(short_lang)) continue;
|
||||
loadFile(f.path);
|
||||
}
|
||||
piCout << "Loaded %1 string for lang \"%2\""_a.arg(instance()->PRIVATEWB->content.count()).arg(short_lang);
|
||||
/*auto s = instance();
|
||||
auto vt = PIValueTreeConversions::fromText(getBuiltinConfig());
|
||||
auto lang = vt.child(short_lang.toLowerCase().trim());
|
||||
for (const auto & cn: lang.children()) {
|
||||
auto c = s->createContextInternal(cn.name());
|
||||
auto c = s->PRIVATEWB->content.createContext(cn.name());
|
||||
for (const auto & s: cn.children())
|
||||
c->add(s.name(), s.value().toString());
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
@@ -62,11 +75,11 @@ void PITranslator::loadConfig(const PIString & content) {
|
||||
auto s = instance();
|
||||
auto lang = PIValueTreeConversions::fromText(content);
|
||||
for (const auto & cn: lang.children()) {
|
||||
auto c = s->createContextInternal(cn.name());
|
||||
auto c = s->PRIVATEWB->content.createContext(cn.name());
|
||||
for (const auto & s: cn.children())
|
||||
c->add(s.name(), s.value().toString());
|
||||
}
|
||||
auto c = s->createContextInternal("");
|
||||
auto c = s->PRIVATEWB->content.createContext("");
|
||||
for (const auto & s: lang.children()) {
|
||||
if (s.hasChildren()) continue;
|
||||
c->add(s.name(), s.value().toString());
|
||||
@@ -74,11 +87,26 @@ void PITranslator::loadConfig(const PIString & content) {
|
||||
}
|
||||
|
||||
|
||||
bool PITranslator::load(const PIByteArray & content) {
|
||||
return instance()->PRIVATEWB->content.load(content);
|
||||
}
|
||||
|
||||
|
||||
bool PITranslator::loadFile(const PIString & path) {
|
||||
PIFile f(path, PIIODevice::ReadOnly);
|
||||
if (f.isClosed()) return false;
|
||||
if (!PITranslatorPrivate::checkHeader(&f)) return false;
|
||||
auto data = f.readAll();
|
||||
data.remove(0, PITranslatorPrivate::headerSize());
|
||||
return load(data);
|
||||
}
|
||||
|
||||
|
||||
PITranslator::PITranslator() {}
|
||||
|
||||
|
||||
PITranslator::~PITranslator() {
|
||||
clearInternal();
|
||||
PRIVATE->content.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,21 +114,3 @@ PITranslator * PITranslator::instance() {
|
||||
static PITranslator ret;
|
||||
return &ret;
|
||||
}
|
||||
|
||||
|
||||
void PITranslator::clearInternal() {
|
||||
piDeleteAll(contexts.values());
|
||||
contexts.clear();
|
||||
}
|
||||
|
||||
|
||||
PITranslator::Context * PITranslator::createContextInternal(const PIString & context) {
|
||||
auto & ret(contexts[context.hash()]);
|
||||
if (!ret) ret = new Context();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void PITranslator::Context::add(const PIString & in, const PIString & out) {
|
||||
strings[in.hash()] = out;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
#include "pistring.h"
|
||||
|
||||
|
||||
#define piTr PITranslator::tr
|
||||
#define piTr PITranslator::tr
|
||||
#define piTrNoOp PITranslator::trNoOp
|
||||
|
||||
//! \ingroup Application
|
||||
//! \~\brief
|
||||
@@ -39,34 +40,59 @@ class PIP_EXPORT PITranslator {
|
||||
public:
|
||||
static PIString tr(const PIString & in, const PIString & context = {});
|
||||
static PIString tr(const char * in, const PIString & context = {}) { return tr(PIString::fromUTF8(in), context); }
|
||||
static PIString trNoOp(const PIString & in, const PIString & context = {}) { return in; }
|
||||
static PIString trNoOp(const char * in, const PIString & context = {}) { return trNoOp(PIString::fromUTF8(in), context); }
|
||||
|
||||
static void clear();
|
||||
static void loadLang(const PIString & short_lang);
|
||||
static void loadLang(const PIString & short_lang, PIString dir = {});
|
||||
static void loadConfig(const PIString & content);
|
||||
static bool load(const PIByteArray & content);
|
||||
static bool loadFile(const PIString & path);
|
||||
|
||||
private:
|
||||
PITranslator();
|
||||
~PITranslator();
|
||||
NO_COPY_CLASS(PITranslator)
|
||||
|
||||
struct Context {
|
||||
void add(const PIString & in, const PIString & out);
|
||||
PIMap<uint, PIString> strings;
|
||||
};
|
||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||
|
||||
static PITranslator * instance();
|
||||
|
||||
void clearInternal();
|
||||
Context * createContextInternal(const PIString & context);
|
||||
|
||||
PIMap<uint, Context *> contexts;
|
||||
};
|
||||
|
||||
|
||||
class PIStringContextTr {
|
||||
public:
|
||||
PIStringContextTr(PIString && s): _s(s) {}
|
||||
operator PIString() const { return PITranslator::tr(_s); }
|
||||
PIString operator()(const PIString & ctx = {}) const { return PITranslator::tr(_s, ctx); }
|
||||
|
||||
private:
|
||||
PIString _s;
|
||||
};
|
||||
|
||||
|
||||
class PIStringContextTrNoOp {
|
||||
public:
|
||||
PIStringContextTrNoOp(PIString && s): _s(s) {}
|
||||
operator PIString() const { return _s; }
|
||||
PIString operator()(const PIString & ctx = {}) const { return _s; }
|
||||
|
||||
private:
|
||||
PIString _s;
|
||||
};
|
||||
|
||||
|
||||
//! \~\brief
|
||||
//! \~english PIString from UTF-8
|
||||
//! \~russian PIString из UTF-8
|
||||
inline PIString operator""_tr(const char * v, size_t sz) {
|
||||
return PITranslator::tr(PIString::fromUTF8(v, sz));
|
||||
//! \~english Translate string with \a PITranslator::tr()
|
||||
//! \~russian Перевести строку с помощью \a PITranslator::tr()
|
||||
inline PIStringContextTr operator""_tr(const char * v, size_t sz) {
|
||||
return PIStringContextTr(PIString::fromUTF8(v, sz));
|
||||
}
|
||||
|
||||
//! \~\brief
|
||||
//! \~english Translate string with \a PITranslator::tr()
|
||||
//! \~russian Перевести строку с помощью \a PITranslator::tr()
|
||||
inline PIStringContextTrNoOp operator""_trNoOp(const char * v, size_t sz) {
|
||||
return PIStringContextTrNoOp(PIString::fromUTF8(v, sz));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
124
libs/main/application/pitranslator_p.cpp
Normal file
124
libs/main/application/pitranslator_p.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Translation private
|
||||
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 "pitranslator_p.h"
|
||||
|
||||
#include "pichunkstream.h"
|
||||
#include "piiodevice.h"
|
||||
|
||||
constexpr int currentVersion = 1;
|
||||
const PIByteArray fileHeader("PIPBTF", 6);
|
||||
|
||||
|
||||
void PITranslatorPrivate::Context::add(const PIMap<uint, PIString> & sm) {
|
||||
auto it = sm.makeIterator();
|
||||
while (it.next())
|
||||
strings[it.key()] = it.value();
|
||||
}
|
||||
|
||||
|
||||
void PITranslatorPrivate::Translation::clear() {
|
||||
piDeleteAll(contexts.values());
|
||||
contexts.clear();
|
||||
lang.clear();
|
||||
}
|
||||
|
||||
|
||||
PITranslatorPrivate::Context * PITranslatorPrivate::Translation::createContext(const PIString & context) {
|
||||
return createContext(context.hash());
|
||||
}
|
||||
|
||||
|
||||
PITranslatorPrivate::Context * PITranslatorPrivate::Translation::createContext(uint hash) {
|
||||
auto & ret(contexts[hash]);
|
||||
if (!ret) ret = new Context();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString PITranslatorPrivate::Translation::translate(const PIString & in, const PIString & context) {
|
||||
auto c = contexts.value(context.hash());
|
||||
if (!c) return in;
|
||||
return c->strings.value(in.hash(), in);
|
||||
}
|
||||
|
||||
|
||||
bool PITranslatorPrivate::Translation::load(const PIByteArray & data) {
|
||||
if (data.size_s() <= 4) return false;
|
||||
PIChunkStream cs(data);
|
||||
Context * ctx = nullptr;
|
||||
PIMap<uint, PIString> strings;
|
||||
while (!cs.atEnd()) {
|
||||
switch (cs.read()) {
|
||||
case 1: {
|
||||
int version = cs.getData<int>();
|
||||
if (version != currentVersion) {
|
||||
piCout << "Invalid translation version!";
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
case 3: {
|
||||
uint ctx_hash = cs.getData<uint>();
|
||||
ctx = createContext(ctx_hash);
|
||||
} break;
|
||||
case 4: {
|
||||
cs.get(strings);
|
||||
if (ctx) ctx->add(strings);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int PITranslatorPrivate::Translation::count() const {
|
||||
int ret = 0;
|
||||
auto cit = contexts.makeIterator();
|
||||
while (cit.next())
|
||||
ret += cit.value()->strings.size_s();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PITranslatorPrivate::Translation::save() {
|
||||
PIChunkStream cs;
|
||||
cs.add(1, currentVersion).add(2, lang);
|
||||
auto cit = contexts.makeIterator();
|
||||
while (cit.next()) {
|
||||
cs.add(3, cit.key()).add(4, cit.value()->strings);
|
||||
}
|
||||
return cs.data();
|
||||
}
|
||||
|
||||
|
||||
int PITranslatorPrivate::headerSize() {
|
||||
return fileHeader.size_s();
|
||||
}
|
||||
|
||||
|
||||
bool PITranslatorPrivate::checkHeader(PIIODevice * d) {
|
||||
if (!d) return false;
|
||||
return d->read(fileHeader.size_s()) == fileHeader;
|
||||
}
|
||||
|
||||
|
||||
void PITranslatorPrivate::writeHeader(PIIODevice * d) {
|
||||
if (!d) return;
|
||||
d->write(fileHeader);
|
||||
}
|
||||
53
libs/main/application/pitranslator_p.h
Normal file
53
libs/main/application/pitranslator_p.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Translation private
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#ifndef pitranslator_p_H
|
||||
#define pitranslator_p_H
|
||||
|
||||
#include "pistring.h"
|
||||
|
||||
class PIIODevice;
|
||||
|
||||
namespace PITranslatorPrivate {
|
||||
|
||||
struct PIP_EXPORT Context {
|
||||
void add(const PIString & in, const PIString & out) { strings[in.hash()] = out; }
|
||||
void add(const PIMap<uint, PIString> & sm);
|
||||
PIMap<uint, PIString> strings;
|
||||
};
|
||||
|
||||
struct PIP_EXPORT Translation {
|
||||
void clear();
|
||||
Context * createContext(const PIString & context);
|
||||
Context * createContext(uint hash);
|
||||
PIString translate(const PIString & in, const PIString & context);
|
||||
bool load(const PIByteArray & data);
|
||||
int count() const;
|
||||
PIByteArray save();
|
||||
PIString lang;
|
||||
PIMap<uint, Context *> contexts;
|
||||
};
|
||||
|
||||
PIP_EXPORT int headerSize();
|
||||
PIP_EXPORT bool checkHeader(PIIODevice * d);
|
||||
PIP_EXPORT void writeHeader(PIIODevice * d);
|
||||
|
||||
} // namespace PITranslatorPrivate
|
||||
|
||||
#endif
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef pitr_pip_all_H
|
||||
#define pitr_pip_all_H
|
||||
|
||||
#include "pip_ru.h"
|
||||
#include "pistring.h"
|
||||
|
||||
PIString getBuiltinConfig() {
|
||||
// clang-format off
|
||||
static const PIString ret =
|
||||
PIString::fromUTF8(config_ru)
|
||||
;
|
||||
// clang-format on
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,25 +0,0 @@
|
||||
constexpr char config_ru[] = "\
|
||||
[ru.PIString] \n\
|
||||
B = Б \n\
|
||||
KiB = KиБ \n\
|
||||
MiB = MиБ \n\
|
||||
GiB = ГиБ \n\
|
||||
TiB = ТиБ \n\
|
||||
PiB = ПиБ \n\
|
||||
EiB = ЭиБ \n\
|
||||
ZiB = ЗиБ \n\
|
||||
YiB = ЙиБ \n\
|
||||
\n\
|
||||
[ru.PIDiag] \n\
|
||||
/s = /сек \n\
|
||||
\n\
|
||||
[ru.PITime] \n\
|
||||
Hz = Гц \n\
|
||||
KHz = КГц \n\
|
||||
kHz = кГц \n\
|
||||
MHz = МГц \n\
|
||||
GHz = ГГц \n\
|
||||
THz = ТГц \n\
|
||||
PHz = ПГц \n\
|
||||
\n\
|
||||
";
|
||||
Reference in New Issue
Block a user