static int Parse_test() { XLIFFFile* xf = XLIFFFile::Parse("testdata/xliff1.xliff"); if (xf == NULL) { return 1; } set<StringResource> const& strings = xf->GetStringResources(); if (false) { for (set<StringResource>::iterator it=strings.begin(); it!=strings.end(); it++) { const StringResource& str = *it; printf("STRING!!! id=%s index=%d value='%s' pos=%s file=%s version=%d(%s)\n", str.id.c_str(), str.index, str.value->ContentsToString(ANDROID_NAMESPACES).c_str(), str.pos.ToString().c_str(), str.file.c_str(), str.version, str.versionString.c_str()); } printf("XML:[[%s]]\n", xf->ToString().c_str()); } delete xf; return 0; }
static int do_pseudo(const string& infile, const string& outfile, bool expand) { int err; XLIFFFile* xliff = XLIFFFile::Parse(infile); if (xliff == NULL) { return 1; } pseudolocalize_xliff(xliff, expand); err = write_to_file(outfile, xliff->ToString()); delete xliff; return err; }
XLIFFFile* XLIFFFile::Parse(const string& filename) { XLIFFFile* result = new XLIFFFile(); XMLNode* root = NodeHandler::ParseFile(filename, XMLNode::PRETTY); if (root == NULL) { return NULL; } // <file> vector<XMLNode*> files = root->GetElementsByName(XLIFF_XMLNS, "file"); for (size_t i=0; i<files.size(); i++) { XMLNode* file = files[i]; string datatype = file->GetAttribute("", "datatype", ""); string originalFile = file->GetAttribute("", "original", ""); Configuration sourceConfig; sourceConfig.locale = file->GetAttribute("", "source-language", ""); result->m_sourceConfig = sourceConfig; Configuration targetConfig; targetConfig.locale = file->GetAttribute("", "target-language", ""); result->m_targetConfig = targetConfig; result->m_currentVersion = file->GetAttribute("", "build-num", ""); result->m_oldVersion = "old"; // <body> XMLNode* body = get_unique_node(file, XLIFF_XMLNS, "body", true); if (body == NULL) continue; // <trans-unit> vector<XMLNode*> transUnits = body->GetElementsByName(XLIFF_XMLNS, "trans-unit"); for (size_t j=0; j<transUnits.size(); j++) { XMLNode* transUnit = transUnits[j]; string rawID = transUnit->GetAttribute("", "id", ""); if (rawID == "") { transUnit->Position().Error("<trans-unit> tag requires an id"); continue; } string id; int index; if (!StringResource::ParseTypedID(rawID, &id, &index)) { transUnit->Position().Error("<trans-unit> has invalid id '%s'\n", rawID.c_str()); continue; } // <source> XMLNode* source = get_unique_node(transUnit, XLIFF_XMLNS, "source", false); if (source != NULL) { XMLNode* node = source->Clone(); node->SetPrettyRecursive(XMLNode::EXACT); result->AddStringResource(StringResource(source->Position(), originalFile, sourceConfig, id, index, node, CURRENT_VERSION, result->m_currentVersion)); } // <target> XMLNode* target = get_unique_node(transUnit, XLIFF_XMLNS, "target", false); if (target != NULL) { XMLNode* node = target->Clone(); node->SetPrettyRecursive(XMLNode::EXACT); result->AddStringResource(StringResource(target->Position(), originalFile, targetConfig, id, index, node, CURRENT_VERSION, result->m_currentVersion)); } // <alt-trans> XMLNode* altTrans = get_unique_node(transUnit, XLIFF_XMLNS, "alt-trans", false); if (altTrans != NULL) { // <source> XMLNode* altSource = get_unique_node(altTrans, XLIFF_XMLNS, "source", false); if (altSource != NULL) { XMLNode* node = altSource->Clone(); node->SetPrettyRecursive(XMLNode::EXACT); result->AddStringResource(StringResource(altSource->Position(), originalFile, sourceConfig, id, index, node, OLD_VERSION, result->m_oldVersion)); } // <target> XMLNode* altTarget = get_unique_node(altTrans, XLIFF_XMLNS, "target", false); if (altTarget != NULL) { XMLNode* node = altTarget->Clone(); node->SetPrettyRecursive(XMLNode::EXACT); result->AddStringResource(StringResource(altTarget->Position(), originalFile, targetConfig, id, index, node, OLD_VERSION, result->m_oldVersion)); } } } } delete root; return result; }
static int do_export(const string& settingsFile, const string& rootDir, const string& outDir, const string& targetLocale, const vector<string>& configs) { bool success = true; int err; if (false) { printf("settingsFile=%s\n", settingsFile.c_str()); printf("rootDir=%s\n", rootDir.c_str()); printf("outDir=%s\n", outDir.c_str()); for (size_t i=0; i<configs.size(); i++) { printf("config[%zd]=%s\n", i, configs[i].c_str()); } } map<string,Settings> settings; err = read_settings(settingsFile, &settings, rootDir); if (err != 0) { return err; } err = validate_configs(settingsFile, settings, configs); if (err != 0) { return err; } vector<vector<string> > allResFiles; err = select_files(&allResFiles, configs, settings, rootDir); if (err != 0) { return err; } size_t totalFileCount = 0; for (size_t i=0; i<allResFiles.size(); i++) { totalFileCount += allResFiles[i].size(); } totalFileCount *= 3; // we try all 3 versions of the file size_t fileProgress = 0; vector<Stats> stats; vector<pair<string,XLIFFFile*> > xliffs; for (size_t i=0; i<configs.size(); i++) { const string& config = configs[i]; const Settings& setting = settings[config]; if (false) { fprintf(stderr, "Configuration: %s (%zd of %zd)\n", config.c_str(), i+1, configs.size()); fprintf(stderr, " Old CL: %s\n", setting.oldVersion.c_str()); fprintf(stderr, " Current CL: %s\n", setting.currentVersion.c_str()); } Configuration english; english.locale = "en_US"; Configuration translated; translated.locale = targetLocale; XLIFFFile* xliff = XLIFFFile::Create(english, translated, setting.currentVersion); const vector<string>& resFiles = allResFiles[i]; const size_t J = resFiles.size(); for (size_t j=0; j<J; j++) { string resFile = resFiles[j]; // parse the files into a ValuesFile // pull out the strings and add them to the XLIFFFile // current file print_file_status(++fileProgress, totalFileCount); ValuesFile* currentFile = get_values_file(resFile, english, CURRENT_VERSION, setting.currentVersion, true); if (currentFile != NULL) { ValuesFile_to_XLIFFFile(currentFile, xliff, resFile); //printf("currentFile=[%s]\n", currentFile->ToString().c_str()); } else { fprintf(stderr, "error reading file %s@%s\n", resFile.c_str(), setting.currentVersion.c_str()); success = false; } // old file print_file_status(++fileProgress, totalFileCount); ValuesFile* oldFile = get_values_file(resFile, english, OLD_VERSION, setting.oldVersion, false); if (oldFile != NULL) { ValuesFile_to_XLIFFFile(oldFile, xliff, resFile); //printf("oldFile=[%s]\n", oldFile->ToString().c_str()); } // translated version // (get the head of the tree for the most recent translation, but it's considered // the old one because the "current" one hasn't been made yet, and this goes into // the <alt-trans> tag if necessary print_file_status(++fileProgress, totalFileCount); string transFilename = translated_file_name(resFile, targetLocale); ValuesFile* transFile = get_values_file(transFilename, translated, OLD_VERSION, setting.currentVersion, false); if (transFile != NULL) { ValuesFile_to_XLIFFFile(transFile, xliff, resFile); } delete currentFile; delete oldFile; delete transFile; } Stats beforeFilterStats = xliff->GetStats(config); // run through the XLIFFFile and strip out TransUnits that have identical // old and current source values and are not in the reject list, or just // old values and no source values xliff->Filter(keep_this_trans_unit, (void*)&setting); Stats afterFilterStats = xliff->GetStats(config); afterFilterStats.totalStrings = beforeFilterStats.totalStrings; // add the reject comments for (vector<Reject>::const_iterator reject = setting.reject.begin(); reject != setting.reject.end(); reject++) { TransUnit* tu = xliff->EditTransUnit(reject->file, reject->name); tu->rejectComment = reject->comment; } // config-locale-current_cl.xliff stringstream filename; if (outDir != "") { filename << outDir << '/'; } filename << config << '-' << targetLocale << '-' << setting.currentVersion << ".xliff"; xliffs.push_back(pair<string,XLIFFFile*>(filename.str(), xliff)); stats.push_back(afterFilterStats); } // today is a good day to die if (!success || SourcePos::HasErrors()) { return 1; } // write the XLIFF files printf("\nWriting %zd file%s...\n", xliffs.size(), xliffs.size() == 1 ? "" : "s"); for (vector<pair<string,XLIFFFile*> >::iterator it = xliffs.begin(); it != xliffs.end(); it++) { const string& filename = it->first; XLIFFFile* xliff = it->second; string text = xliff->ToString(); write_to_file(filename, text); } // the stats printf("\n" " to without total\n" " config files translate comments strings\n" "-----------------------------------------------------------------------\n"); Stats totals; totals.config = "total"; totals.files = 0; totals.toBeTranslated = 0; totals.noComments = 0; totals.totalStrings = 0; for (vector<Stats>::iterator it=stats.begin(); it!=stats.end(); it++) { string cfg = it->config; if (cfg.length() > 20) { cfg.resize(20); } printf(" %-20s %-9zd %-9zd %-9zd %-19zd\n", cfg.c_str(), it->files, it->toBeTranslated, it->noComments, it->totalStrings); totals.files += it->files; totals.toBeTranslated += it->toBeTranslated; totals.noComments += it->noComments; totals.totalStrings += it->totalStrings; } if (stats.size() > 1) { printf("-----------------------------------------------------------------------\n" " %-20s %-9zd %-9zd %-9zd %-19zd\n", totals.config.c_str(), totals.files, totals.toBeTranslated, totals.noComments, totals.totalStrings); } printf("\n"); return 0; }