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