1 #include "xmb.h" 2 3 #include "file_utils.h" 4 #include "localize.h" 5 #include "ValuesFile.h" 6 #include "XMLHandler.h" 7 #include "XLIFFFile.h" 8 9 #include <map> 10 #include <cstdio> 11 12 using namespace std; 13 14 const char *const NS_MAP[] = { 15 "xml", XMLNS_XMLNS, 16 NULL, NULL 17 }; 18 19 set<string> g_tags; 20 21 static string 22 strip_newlines(const string& str) 23 { 24 string res; 25 const size_t N = str.length(); 26 for (size_t i=0; i<N; i++) { 27 char c = str[i]; 28 if (c != '\n' && c != '\r') { 29 res += c; 30 } else { 31 res += ' '; 32 } 33 } 34 return res; 35 } 36 37 static int 38 rename_id_attribute(XMLNode* node) 39 { 40 vector<XMLAttribute>& attrs = node->EditAttributes(); 41 const size_t I = attrs.size(); 42 for (size_t i=0; i<I; i++) { 43 XMLAttribute attr = attrs[i]; 44 if (attr.name == "id") { 45 attr.name = "name"; 46 attrs.erase(attrs.begin()+i); 47 attrs.push_back(attr); 48 return 0; 49 } 50 } 51 return 1; 52 } 53 54 static int 55 convert_xliff_to_ph(XMLNode* node, int* phID) 56 { 57 int err = 0; 58 if (node->Type() == XMLNode::ELEMENT) { 59 if (node->Namespace() == XLIFF_XMLNS) { 60 g_tags.insert(node->Name()); 61 node->SetName("", "ph"); 62 63 err = rename_id_attribute(node); 64 if (err != 0) { 65 char name[30]; 66 (*phID)++; 67 sprintf(name, "id-%d", *phID); 68 node->EditAttributes().push_back(XMLAttribute("", "name", name)); 69 err = 0; 70 } 71 } 72 vector<XMLNode*>& children = node->EditChildren(); 73 const size_t I = children.size(); 74 for (size_t i=0; i<I; i++) { 75 err |= convert_xliff_to_ph(children[i], phID); 76 } 77 } 78 return err; 79 } 80 81 XMLNode* 82 resource_to_xmb_msg(const StringResource& res) 83 { 84 // the msg element 85 vector<XMLAttribute> attrs; 86 string name = res.pos.file; 87 name += ":"; 88 name += res.TypedID(); 89 attrs.push_back(XMLAttribute("", "name", name)); 90 attrs.push_back(XMLAttribute("", "desc", strip_newlines(res.comment))); 91 attrs.push_back(XMLAttribute(XMLNS_XMLNS, "space", "preserve")); 92 XMLNode* msg = XMLNode::NewElement(res.pos, "", "msg", attrs, XMLNode::EXACT); 93 94 // the contents are in xliff/html, convert it to xliff 95 int err = 0; 96 XMLNode* value = res.value; 97 string tag = value->Name(); 98 int phID = 0; 99 for (vector<XMLNode*>::const_iterator it=value->Children().begin(); 100 it!=value->Children().end(); it++) { 101 err |= convert_html_to_xliff(*it, tag, msg, &phID); 102 } 103 104 if (err != 0) { 105 return NULL; 106 } 107 108 // and then convert that to xmb 109 for (vector<XMLNode*>::iterator it=msg->EditChildren().begin(); 110 it!=msg->EditChildren().end(); it++) { 111 err |= convert_xliff_to_ph(*it, &phID); 112 } 113 114 if (err == 0) { 115 return msg; 116 } else { 117 return NULL; 118 } 119 } 120 121 int 122 do_xlb_export(const string& outfile, const vector<string>& resFiles) 123 { 124 int err = 0; 125 126 size_t totalFileCount = resFiles.size(); 127 128 Configuration english; 129 english.locale = "en_US"; 130 131 set<StringResource> allResources; 132 133 const size_t J = resFiles.size(); 134 for (size_t j=0; j<J; j++) { 135 string resFile = resFiles[j]; 136 137 ValuesFile* valuesFile = get_local_values_file(resFile, english, CURRENT_VERSION, "", true); 138 if (valuesFile != NULL) { 139 set<StringResource> resources = valuesFile->GetStrings(); 140 allResources.insert(resources.begin(), resources.end()); 141 } else { 142 fprintf(stderr, "error reading file %s\n", resFile.c_str()); 143 } 144 145 delete valuesFile; 146 } 147 148 // Construct the XLB xml 149 vector<XMLAttribute> attrs; 150 attrs.push_back(XMLAttribute("", "locale", "en")); 151 XMLNode* localizationbundle = XMLNode::NewElement(GENERATED_POS, "", "localizationbundle", 152 attrs, XMLNode::PRETTY); 153 154 for (set<StringResource>::iterator it=allResources.begin(); it!=allResources.end(); it++) { 155 XMLNode* msg = resource_to_xmb_msg(*it); 156 if (msg) { 157 localizationbundle->EditChildren().push_back(msg); 158 } else { 159 err = 1; 160 } 161 } 162 163 #if 0 164 for (set<string>::iterator it=g_tags.begin(); it!=g_tags.end(); it++) { 165 printf("tag: %s\n", it->c_str()); 166 } 167 printf("err=%d\n", err); 168 #endif 169 if (err == 0) { 170 FILE* f = fopen(outfile.c_str(), "wb"); 171 if (f == NULL) { 172 fprintf(stderr, "can't open outputfile: %s\n", outfile.c_str()); 173 return 1; 174 } 175 fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); 176 fprintf(f, "%s\n", localizationbundle->ToString(NS_MAP).c_str()); 177 fclose(f); 178 } 179 180 return err; 181 } 182 183