static XMLNode* pseudolocalize_xml_node(const XMLNode* source, const PseudolocalizeSettings* settings) { if (source->Type() == XMLNode::TEXT) { return XMLNode::NewText(source->Position(), pseudolocalize_string(source->Text(), settings), source->Pretty()); } else { XMLNode* target; if (source->Namespace() == XLIFF_XMLNS && source->Name() == "g") { // XXX don't translate these target = XMLNode::NewElement(source->Position(), source->Namespace(), source->Name(), source->Attributes(), source->Pretty()); } else { target = XMLNode::NewElement(source->Position(), source->Namespace(), source->Name(), source->Attributes(), source->Pretty()); } const vector<XMLNode*>& children = source->Children(); const size_t I = children.size(); for (size_t i=0; i<I; i++) { target->EditChildren().push_back(pseudolocalize_xml_node(children[i], settings)); } return target; } }
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; } }
XMLNode* XLIFFFile::ToXMLNode() const { XMLNode* root; size_t N; // <xliff> { vector<XMLAttribute> attrs; XLIFF_NAMESPACES.AddToAttributes(&attrs); attrs.push_back(XMLAttribute(XLIFF_XMLNS, "version", "1.2")); root = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "xliff", attrs, XMLNode::PRETTY); } vector<TransUnit> groups; // <file> vector<File> files = m_files; sort(files.begin(), files.end()); const size_t I = files.size(); for (size_t i=0; i<I; i++) { const File& file = files[i]; vector<XMLAttribute> fileAttrs; fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "datatype", "x-android-res")); fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "original", file.filename)); struct timeval tv; struct timezone tz; gettimeofday(&tv, &tz); fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "date", trim_string(ctime(&tv.tv_sec)))); fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "source-language", m_sourceConfig.locale)); fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "target-language", m_targetConfig.locale)); fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "build-num", m_currentVersion)); XMLNode* fileNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "file", fileAttrs, XMLNode::PRETTY); root->EditChildren().push_back(fileNode); // <body> XMLNode* bodyNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "body", vector<XMLAttribute>(), XMLNode::PRETTY); fileNode->EditChildren().push_back(bodyNode); // <trans-unit> vector<TransUnit> transUnits = file.transUnits; sort(transUnits.begin(), transUnits.end(), compare_id); const size_t J = transUnits.size(); for (size_t j=0; j<J; j++) { const TransUnit& transUnit = transUnits[j]; vector<XMLAttribute> tuAttrs; // strings start with string: tuAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "id", transUnit.id)); XMLNode* transUnitNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "trans-unit", tuAttrs, XMLNode::PRETTY); bodyNode->EditChildren().push_back(transUnitNode); // <extradata> if (transUnit.source.comment != "") { vector<XMLAttribute> extradataAttrs; XMLNode* extraNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "extradata", extradataAttrs, XMLNode::EXACT); transUnitNode->EditChildren().push_back(extraNode); extraNode->EditChildren().push_back( XMLNode::NewText(GENERATED_POS, transUnit.source.comment, XMLNode::PRETTY)); } // <source> if (transUnit.source.id != "") { transUnitNode->EditChildren().push_back( create_string_node(transUnit.source, "source")); } // <target> if (transUnit.target.id != "") { transUnitNode->EditChildren().push_back( create_string_node(transUnit.target, "target")); } // <alt-trans> if (transUnit.altSource.id != "" || transUnit.altTarget.id != "" || transUnit.rejectComment != "") { vector<XMLAttribute> altTransAttrs; XMLNode* altTransNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "alt-trans", altTransAttrs, XMLNode::PRETTY); transUnitNode->EditChildren().push_back(altTransNode); // <extradata> if (transUnit.rejectComment != "") { vector<XMLAttribute> extradataAttrs; XMLNode* extraNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "extradata", extradataAttrs, XMLNode::EXACT); altTransNode->EditChildren().push_back(extraNode); extraNode->EditChildren().push_back( XMLNode::NewText(GENERATED_POS, transUnit.rejectComment, XMLNode::PRETTY)); } // <source> if (transUnit.altSource.id != "") { altTransNode->EditChildren().push_back( create_string_node(transUnit.altSource, "source")); } // <target> if (transUnit.altTarget.id != "") { altTransNode->EditChildren().push_back( create_string_node(transUnit.altTarget, "target")); } } } } return root; }
int convert_html_to_xliff(const XMLNode* original, const string& name, XMLNode* addTo, int* phID) { int err = 0; if (original->Type() == XMLNode::TEXT) { addTo->EditChildren().push_back(original->Clone()); return 0; } else { string ctype; if (original->Namespace() == "") { if (original->Name() == "b") { ctype = "bold"; } else if (original->Name() == "i") { ctype = "italic"; } else if (original->Name() == "u") { ctype = "underline"; } } if (ctype != "") { vector<XMLAttribute> attrs; attrs.push_back(XMLAttribute(XLIFF_XMLNS, "ctype", ctype)); XMLNode* copy = XMLNode::NewElement(original->Position(), XLIFF_XMLNS, "g", attrs, XMLNode::EXACT); const vector<XMLNode*>& children = original->Children(); size_t I = children.size(); for (size_t i=0; i<I; i++) { err |= convert_html_to_xliff(children[i], name, copy, phID); } return err; } else { if (original->Namespace() == XLIFF_XMLNS) { addTo->EditChildren().push_back(original->Clone()); return 0; } else { if (original->Namespace() == "") { // flatten out the tag into ph tags -- but only if there is no namespace // that's still unsupported because propagating the xmlns attribute is hard. vector<XMLAttribute> attrs; char idStr[30]; (*phID)++; sprintf(idStr, "id-%d", *phID); attrs.push_back(XMLAttribute(XLIFF_XMLNS, "id", idStr)); if (original->Children().size() == 0) { XMLNode* ph = XMLNode::NewElement(original->Position(), XLIFF_XMLNS, "ph", attrs, XMLNode::EXACT); ph->EditChildren().push_back( XMLNode::NewText(original->Position(), original->ToString(XLIFF_NAMESPACES), XMLNode::EXACT)); addTo->EditChildren().push_back(ph); } else { XMLNode* begin = XMLNode::NewElement(original->Position(), XLIFF_XMLNS, "bpt", attrs, XMLNode::EXACT); begin->EditChildren().push_back( XMLNode::NewText(original->Position(), original->OpenTagToString(XLIFF_NAMESPACES, XMLNode::EXACT), XMLNode::EXACT)); XMLNode* end = XMLNode::NewElement(original->Position(), XLIFF_XMLNS, "ept", attrs, XMLNode::EXACT); string endText = "</"; endText += original->Name(); endText += ">"; end->EditChildren().push_back(XMLNode::NewText(original->Position(), endText, XMLNode::EXACT)); addTo->EditChildren().push_back(begin); const vector<XMLNode*>& children = original->Children(); size_t I = children.size(); for (size_t i=0; i<I; i++) { err |= convert_html_to_xliff(children[i], name, addTo, phID); } addTo->EditChildren().push_back(end); } return err; } else { original->Position().Error("invalid <%s> element in <%s> tag\n", original->Name().c_str(), name.c_str()); return 1; } } } } }
static int create_string_node_test() { int err = 0; StringResource res; vector<XMLAttribute> attrs; res.value = XMLNode::NewElement(GENERATED_POS, "", "something", attrs, XMLNode::EXACT); res.value->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, " begin ", XMLNode::EXACT)); XMLNode* child; child = add_html_tag(res.value, "b"); child->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, "b", XMLNode::EXACT)); child = add_html_tag(res.value, "i"); child->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, "i", XMLNode::EXACT)); child = add_html_tag(child, "b"); child->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, "b", XMLNode::EXACT)); child = add_html_tag(res.value, "u"); child->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, "u", XMLNode::EXACT)); res.value->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, " end ", XMLNode::EXACT)); XMLNode* xliff = create_string_node(res, "blah"); string oldString = res.value->ToString(XLIFF_NAMESPACES); string newString = xliff->ToString(XLIFF_NAMESPACES); if (false) { printf("OLD=\"%s\"\n", oldString.c_str()); printf("NEW=\"%s\"\n", newString.c_str()); } const char* const EXPECTED_OLD = "<something> begin <b>b</b><i>i<b>b</b></i><u>u</u> end </something>"; if (oldString != EXPECTED_OLD) { fprintf(stderr, "oldString mismatch:\n"); fprintf(stderr, " expected='%s'\n", EXPECTED_OLD); fprintf(stderr, " actual='%s'\n", oldString.c_str()); err |= 1; } const char* const EXPECTED_NEW = "<blah xml:space=\"preserve\"> begin <g ctype=\"bold\">b</g>" "<g ctype=\"italic\">i<g ctype=\"bold\">b</g></g><g ctype=\"underline\">u</g>" " end </blah>"; if (newString != EXPECTED_NEW) { fprintf(stderr, "newString mismatch:\n"); fprintf(stderr, " expected='%s'\n", EXPECTED_NEW); fprintf(stderr, " actual='%s'\n", newString.c_str()); err |= 1; } if (err != 0) { fprintf(stderr, "create_string_node_test failed\n"); } return err; }
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; }