mirror of https://github.com/axmolengine/axmol.git
296 lines
8.9 KiB
C++
296 lines
8.9 KiB
C++
#include "TranslationHelper.h"
|
|
#include "PackageItem.h"
|
|
#include "UIPackage.h"
|
|
#if defined(AXIS_VERSION)
|
|
#include "pugixml/pugixml.hpp"
|
|
#else
|
|
#include "tinyxml2/tinyxml2.h"
|
|
#endif
|
|
#include "utils/ByteBuffer.h"
|
|
|
|
#include "base/format.h"
|
|
|
|
USING_NS_AX;
|
|
NS_FGUI_BEGIN
|
|
|
|
using namespace std;
|
|
|
|
hlookup::string_map<hlookup::string_map<std::string> > TranslationHelper::strings;
|
|
|
|
void TranslationHelper::loadFromXML(const char* xmlString, size_t nBytes)
|
|
{
|
|
TranslationHelper::strings.clear();
|
|
|
|
#if defined(AXIS_VERSION)
|
|
pugi::xml_document doc;
|
|
if (doc.load_buffer(xmlString, nBytes)) {
|
|
auto root = doc.document_element();
|
|
auto ele = doc.child("string"sv);
|
|
while (ele)
|
|
{
|
|
auto key = ele.attribute("name"sv).value();
|
|
auto text = ele.text().as_string();
|
|
size_t i = key.find("-");
|
|
if (i == std::string::npos)
|
|
continue;
|
|
|
|
auto key2 = key.substr(0, i);
|
|
auto key3 = key.substr(i + 1);
|
|
auto& col = TranslationHelper::strings[key2];
|
|
col[key3] = text;
|
|
|
|
ele = ele.next_sibling("string"sv);
|
|
}
|
|
}
|
|
#else
|
|
tinyxml2::XMLDocument* xml = new tinyxml2::XMLDocument();
|
|
xml->Parse(xmlString, nBytes);
|
|
|
|
tinyxml2::XMLElement* root = xml->RootElement();
|
|
tinyxml2::XMLElement* ele = root->FirstChildElement("string");
|
|
while (ele)
|
|
{
|
|
std::string key = ele->Attribute("name");
|
|
std::string text = ele->GetText();
|
|
size_t i = key.find("-");
|
|
if (i == std::string::npos)
|
|
continue;
|
|
|
|
std::string key2 = key.substr(0, i);
|
|
std::string key3 = key.substr(i + 1);
|
|
std::unordered_map<std::string, std::string>& col = strings[key2];
|
|
col[key3] = text;
|
|
|
|
ele = ele->NextSiblingElement("string");
|
|
}
|
|
|
|
delete xml;
|
|
#endif
|
|
}
|
|
|
|
void TranslationHelper::translateComponent(PackageItem* item)
|
|
{
|
|
if (TranslationHelper::strings.empty())
|
|
return;
|
|
|
|
auto col = TranslationHelper::strings.find(item->owner->getId() + item->id);
|
|
if (col == TranslationHelper::strings.end())
|
|
return;
|
|
|
|
auto& sstrings = col->second;
|
|
|
|
ByteBuffer* buffer = item->rawData;
|
|
|
|
buffer->seek(0, 2);
|
|
|
|
std::string fmtbuf;
|
|
|
|
int childCount = buffer->readShort();
|
|
for (int i = 0; i < childCount; i++)
|
|
{
|
|
int dataLen = buffer->readUshort();
|
|
int curPos = buffer->getPos();
|
|
|
|
buffer->seek(curPos, 0);
|
|
|
|
ObjectType baseType = (ObjectType)buffer->readByte();
|
|
ObjectType type = baseType;
|
|
|
|
buffer->skip(4);
|
|
const string& elementId = buffer->readS();
|
|
|
|
if (type == ObjectType::COMPONENT)
|
|
{
|
|
if (buffer->seek(curPos, 6))
|
|
type = (ObjectType)buffer->readByte();
|
|
}
|
|
|
|
buffer->seek(curPos, 1);
|
|
|
|
auto it = sstrings.find(elementId + "-tips");
|
|
if (it != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
|
|
buffer->seek(curPos, 2);
|
|
|
|
int gearCnt = buffer->readShort();
|
|
for (int j = 0; j < gearCnt; j++)
|
|
{
|
|
int nextPos = buffer->readUshort();
|
|
nextPos += buffer->getPos();
|
|
|
|
if (buffer->readByte() == 6) //gearText
|
|
{
|
|
buffer->skip(2); //controller
|
|
int valueCnt = buffer->readShort();
|
|
for (int k = 0; k < valueCnt; k++)
|
|
{
|
|
const string& page = buffer->readS();
|
|
if (!page.empty())
|
|
{
|
|
if ((it = sstrings.find(fmt::format_to(fmtbuf, "{}-texts_{}", elementId, k))) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
else
|
|
buffer->skip(2);
|
|
}
|
|
}
|
|
|
|
if (buffer->readBool() && (it = sstrings.find(elementId + "-texts_def")) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
}
|
|
|
|
buffer->setPos(nextPos);
|
|
}
|
|
|
|
if (baseType == ObjectType::COMPONENT && buffer->version >= 2)
|
|
{
|
|
buffer->seek(curPos, 4);
|
|
|
|
buffer->skip(2); //pageController
|
|
|
|
buffer->skip(4 * buffer->readShort());
|
|
|
|
int cpCount = buffer->readShort();
|
|
for (int k = 0; k < cpCount; k++)
|
|
{
|
|
std::string target = buffer->readS();
|
|
int propertyId = buffer->readShort();
|
|
if (propertyId == 0 && (it = sstrings.find(elementId + "-cp-" + target)) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
else
|
|
buffer->skip(2);
|
|
}
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case ObjectType::TEXT:
|
|
case ObjectType::RICHTEXT:
|
|
case ObjectType::INPUTTEXT:
|
|
{
|
|
if ((it = sstrings.find(elementId)) != sstrings.end())
|
|
{
|
|
buffer->seek(curPos, 6);
|
|
buffer->writeS(it->second);
|
|
}
|
|
if ((it = sstrings.find(elementId + "-prompt")) != sstrings.end())
|
|
{
|
|
buffer->seek(curPos, 4);
|
|
buffer->writeS(it->second);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ObjectType::LIST:
|
|
{
|
|
buffer->seek(curPos, 8);
|
|
buffer->skip(2);
|
|
int itemCount = buffer->readShort();
|
|
for (int j = 0; j < itemCount; j++)
|
|
{
|
|
int nextPos = buffer->readUshort();
|
|
nextPos += buffer->getPos();
|
|
|
|
buffer->skip(2); //url
|
|
if (type == ObjectType::TREE)
|
|
buffer->skip(2);
|
|
//title
|
|
if ((it = sstrings.find(fmt::format_to(fmtbuf, "{}-{}", elementId, j))) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
else
|
|
buffer->skip(2);
|
|
|
|
//selected title
|
|
if ((it = sstrings.find(fmt::format_to(fmtbuf, "{}-{}-0", elementId, j))) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
else
|
|
buffer->skip(2);
|
|
|
|
if (buffer->version >= 2)
|
|
{
|
|
buffer->skip(6);
|
|
buffer->skip(buffer->readShort() * 4); //controllers
|
|
|
|
int cpCount = buffer->readShort();
|
|
for (int k = 0; k < cpCount; k++)
|
|
{
|
|
std::string target = buffer->readS();
|
|
int propertyId = buffer->readShort();
|
|
if (propertyId == 0 && (it = sstrings.find(fmt::format_to(fmtbuf, "{}-{}-{}", elementId, j,
|
|
target))) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
else
|
|
buffer->skip(2);
|
|
}
|
|
}
|
|
|
|
buffer->setPos(nextPos);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ObjectType::LABEL:
|
|
{
|
|
if (buffer->seek(curPos, 6) && (ObjectType)buffer->readByte() == type)
|
|
{
|
|
if ((it = sstrings.find(elementId)) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
else
|
|
buffer->skip(2);
|
|
|
|
buffer->skip(2);
|
|
if (buffer->readBool())
|
|
buffer->skip(4);
|
|
buffer->skip(4);
|
|
if (buffer->readBool() && (it = sstrings.find(elementId + "-prompt")) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ObjectType::BUTTON:
|
|
{
|
|
if (buffer->seek(curPos, 6) && (ObjectType)buffer->readByte() == type)
|
|
{
|
|
if ((it = sstrings.find(elementId)) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
else
|
|
buffer->skip(2);
|
|
if ((it = sstrings.find(elementId + "-0")) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ObjectType::COMBOBOX:
|
|
{
|
|
if (buffer->seek(curPos, 6) && (ObjectType)buffer->readByte() == type)
|
|
{
|
|
int itemCount = buffer->readShort();
|
|
for (int j = 0; j < itemCount; j++)
|
|
{
|
|
int nextPos = buffer->readUshort();
|
|
nextPos += buffer->getPos();
|
|
|
|
if ((it = sstrings.find(fmt::format_to(fmtbuf, "{}-{}", elementId, j))) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
|
|
buffer->setPos(nextPos);
|
|
}
|
|
|
|
if ((it = sstrings.find(elementId)) != sstrings.end())
|
|
buffer->writeS(it->second);
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
buffer->setPos(curPos + dataLen);
|
|
}
|
|
}
|
|
|
|
NS_FGUI_END
|