blob: d8f6ff0728b55e6b9c19961735680d60ccfb6651 [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>
Jack Palevichbdb087c2009-06-24 19:01:27 -070010#include <cstdio>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011
12using namespace std;
13
14const char *const NS_MAP[] = {
15 "xml", XMLNS_XMLNS,
16 NULL, NULL
17};
18
19set<string> g_tags;
20
21static string
22strip_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
37static int
38rename_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
54static int
55convert_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
81XMLNode*
82resource_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
121int
122do_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