183 lines
4.7 KiB
C++
183 lines
4.7 KiB
C++
|
#include "xmb.h"
|
||
|
|
||
|
#include "file_utils.h"
|
||
|
#include "localize.h"
|
||
|
#include "ValuesFile.h"
|
||
|
#include "XMLHandler.h"
|
||
|
#include "XLIFFFile.h"
|
||
|
|
||
|
#include <map>
|
||
|
#include <cstdio>
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
const char *const NS_MAP[] = {
|
||
|
"xml", XMLNS_XMLNS,
|
||
|
NULL, NULL
|
||
|
};
|
||
|
|
||
|
set<string> g_tags;
|
||
|
|
||
|
static string
|
||
|
strip_newlines(const string& str)
|
||
|
{
|
||
|
string res;
|
||
|
const size_t N = str.length();
|
||
|
for (size_t i=0; i<N; i++) {
|
||
|
char c = str[i];
|
||
|
if (c != '\n' && c != '\r') {
|
||
|
res += c;
|
||
|
} else {
|
||
|
res += ' ';
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
rename_id_attribute(XMLNode* node)
|
||
|
{
|
||
|
vector<XMLAttribute>& attrs = node->EditAttributes();
|
||
|
const size_t I = attrs.size();
|
||
|
for (size_t i=0; i<I; i++) {
|
||
|
XMLAttribute attr = attrs[i];
|
||
|
if (attr.name == "id") {
|
||
|
attr.name = "name";
|
||
|
attrs.erase(attrs.begin()+i);
|
||
|
attrs.push_back(attr);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
convert_xliff_to_ph(XMLNode* node, int* phID)
|
||
|
{
|
||
|
int err = 0;
|
||
|
if (node->Type() == XMLNode::ELEMENT) {
|
||
|
if (node->Namespace() == XLIFF_XMLNS) {
|
||
|
g_tags.insert(node->Name());
|
||
|
node->SetName("", "ph");
|
||
|
|
||
|
err = rename_id_attribute(node);
|
||
|
if (err != 0) {
|
||
|
char name[30];
|
||
|
(*phID)++;
|
||
|
sprintf(name, "id-%d", *phID);
|
||
|
node->EditAttributes().push_back(XMLAttribute("", "name", name));
|
||
|
err = 0;
|
||
|
}
|
||
|
}
|
||
|
vector<XMLNode*>& children = node->EditChildren();
|
||
|
const size_t I = children.size();
|
||
|
for (size_t i=0; i<I; i++) {
|
||
|
err |= convert_xliff_to_ph(children[i], phID);
|
||
|
}
|
||
|
}
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
XMLNode*
|
||
|
resource_to_xmb_msg(const StringResource& res)
|
||
|
{
|
||
|
// the msg element
|
||
|
vector<XMLAttribute> attrs;
|
||
|
string name = res.pos.file;
|
||
|
name += ":";
|
||
|
name += res.TypedID();
|
||
|
attrs.push_back(XMLAttribute("", "name", name));
|
||
|
attrs.push_back(XMLAttribute("", "desc", strip_newlines(res.comment)));
|
||
|
attrs.push_back(XMLAttribute(XMLNS_XMLNS, "space", "preserve"));
|
||
|
XMLNode* msg = XMLNode::NewElement(res.pos, "", "msg", attrs, XMLNode::EXACT);
|
||
|
|
||
|
// the contents are in xliff/html, convert it to xliff
|
||
|
int err = 0;
|
||
|
XMLNode* value = res.value;
|
||
|
string tag = value->Name();
|
||
|
int phID = 0;
|
||
|
for (vector<XMLNode*>::const_iterator it=value->Children().begin();
|
||
|
it!=value->Children().end(); it++) {
|
||
|
err |= convert_html_to_xliff(*it, tag, msg, &phID);
|
||
|
}
|
||
|
|
||
|
if (err != 0) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// and then convert that to xmb
|
||
|
for (vector<XMLNode*>::iterator it=msg->EditChildren().begin();
|
||
|
it!=msg->EditChildren().end(); it++) {
|
||
|
err |= convert_xliff_to_ph(*it, &phID);
|
||
|
}
|
||
|
|
||
|
if (err == 0) {
|
||
|
return msg;
|
||
|
} else {
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int
|
||
|
do_xlb_export(const string& outfile, const vector<string>& resFiles)
|
||
|
{
|
||
|
int err = 0;
|
||
|
|
||
|
size_t totalFileCount = resFiles.size();
|
||
|
|
||
|
Configuration english;
|
||
|
english.locale = "en_US";
|
||
|
|
||
|
set<StringResource> allResources;
|
||
|
|
||
|
const size_t J = resFiles.size();
|
||
|
for (size_t j=0; j<J; j++) {
|
||
|
string resFile = resFiles[j];
|
||
|
|
||
|
ValuesFile* valuesFile = get_local_values_file(resFile, english, CURRENT_VERSION, "", true);
|
||
|
if (valuesFile != NULL) {
|
||
|
set<StringResource> resources = valuesFile->GetStrings();
|
||
|
allResources.insert(resources.begin(), resources.end());
|
||
|
} else {
|
||
|
fprintf(stderr, "error reading file %s\n", resFile.c_str());
|
||
|
}
|
||
|
|
||
|
delete valuesFile;
|
||
|
}
|
||
|
|
||
|
// Construct the XLB xml
|
||
|
vector<XMLAttribute> attrs;
|
||
|
attrs.push_back(XMLAttribute("", "locale", "en"));
|
||
|
XMLNode* localizationbundle = XMLNode::NewElement(GENERATED_POS, "", "localizationbundle",
|
||
|
attrs, XMLNode::PRETTY);
|
||
|
|
||
|
for (set<StringResource>::iterator it=allResources.begin(); it!=allResources.end(); it++) {
|
||
|
XMLNode* msg = resource_to_xmb_msg(*it);
|
||
|
if (msg) {
|
||
|
localizationbundle->EditChildren().push_back(msg);
|
||
|
} else {
|
||
|
err = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
for (set<string>::iterator it=g_tags.begin(); it!=g_tags.end(); it++) {
|
||
|
printf("tag: %s\n", it->c_str());
|
||
|
}
|
||
|
printf("err=%d\n", err);
|
||
|
#endif
|
||
|
if (err == 0) {
|
||
|
FILE* f = fopen(outfile.c_str(), "wb");
|
||
|
if (f == NULL) {
|
||
|
fprintf(stderr, "can't open outputfile: %s\n", outfile.c_str());
|
||
|
return 1;
|
||
|
}
|
||
|
fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||
|
fprintf(f, "%s\n", localizationbundle->ToString(NS_MAP).c_str());
|
||
|
fclose(f);
|
||
|
}
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|