• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
strip_newlines(const string & str)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
rename_id_attribute(XMLNode * node)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
convert_xliff_to_ph(XMLNode * node,int * phID)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*
resource_to_xmb_msg(const StringResource & res)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
do_xlb_export(const string & outfile,const vector<string> & resFiles)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