Home | History | Annotate | Download | only in localize
      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