#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; }