local int HigherThan(Player *a, Player *b) { char cap[MAXGROUPLEN+16]; const char *bgrp = ((pdata*)PPDATA(b, pdkey))->group; snprintf(cap, sizeof(cap), "higher_than_%s", bgrp); return HasCapability(a, cap); }
void Catalog::ExportToHTML(std::ostream& f) { const bool translated = HasCapability(Catalog::Cap::Translations); f << "<!DOCTYPE html>\n" "<html>\n" "<head>\n" " <title>" << str::to_utf8(m_header.Project) << "</title>\n" " <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>\n" " <style>\n" << CSS_STYLE << "\n" " </style>\n" "</head>\n" "<body>\n" "<div class='container'>\n"; // Metadata section: f << "<table class='metadata'>\n"; if (!m_header.Project.empty()) TableRow(f, _("Project:"), m_header.Project); if (translated && m_header.Lang.IsValid()) TableRow(f, _("Language:"), m_header.Lang.DisplayName()); f << "</table>\n"; // Statistics: if (translated) { int all = 0; int fuzzy = 0; int untranslated = 0; int unfinished = 0; GetStatistics(&all, &fuzzy, nullptr, &untranslated, &unfinished); int percent = (all == 0 ) ? 0 : (100 * (all - unfinished) / all); f << "<div class='stats'>\n" << " <div class='graph'>\n"; if (all > unfinished) f << " <div class='percent-done' style='width: " << 100.0 * (all - unfinished) / all << "%'> </div>\n"; if (fuzzy > 0) f << " <div class='percent-fuzzy' style='width: " << 100.0 * fuzzy / all << "%'> </div>\n"; if (untranslated > 0) f << " <div class='percent-untrans' style='width: " << 100.0 * untranslated / all << "%'> </div>\n"; f << " </div>\n" << " <div class='legend'>"; f << str::to_utf8(wxString::Format(_("Translated: %d of %d (%d %%)"), all - unfinished, all, percent)); if (unfinished > 0) f << str::to_utf8(L" • ") << str::to_utf8(wxString::Format(_("Remaining: %d"), unfinished)); f << " </div>\n" << "</div>\n"; } else { int all = (int)items().size(); f << "<div class='stats'>\n" << " <div class='graph'>\n" << " <div class='percent-untrans' style='width: 100%'> </div>\n" << " </div>\n" << " <div class='legend'>" << str::to_utf8(wxString::Format(wxPLURAL("%d entry", "%d entries", all), all)) << " </div>\n" << "</div>\n"; } // Translations: std::string lang_src, lang_tra; if (m_sourceLanguage.IsValid()) lang_src = " lang='" + m_sourceLanguage.RFC3066() + "'"; if (m_header.Lang.IsValid()) { lang_tra = " lang='" + m_header.Lang.RFC3066() + "'"; if (m_header.Lang.IsRTL()) lang_tra += " dir='rtl'"; } auto thead_src = m_sourceLanguage.IsValid() ? (wxString::Format(_(L"Source text — %s"), m_sourceLanguage.DisplayName())) : _("Source text"); auto thead_tra = wxString::Format(_(L"Translation — %s"), m_header.Lang.IsValid() ? m_header.Lang.DisplayName() : _("unknown language")); f << "<table class='translations'>\n" " <thead>\n" " <tr>\n" " <th>" << str::to_utf8(thead_src) << "</th>\n"; if (translated) { f << " <th>" << str::to_utf8(thead_tra) << "</th>\n"; } f << " </tr>\n" " </thead>\n" " <tbody>\n"; for (auto& item: items()) { bool hasComments = item->HasComment() || item->HasExtractedComments(); std::string klass("i"); if (!item->IsTranslated()) klass += " untrans"; if (item->IsFuzzy()) klass += " fuzzy"; if (hasComments) klass += " with-comments"; f << "<tr class='" << klass << "'>\n"; // Source string: f << "<td class='src' " << lang_src << ">\n"; if (item->HasPlural()) { f << "<ol class='plurals'>\n" << " <li>" << fmt_trans(item->GetString()) << "</li>\n" << " <li>" << fmt_trans(item->GetPluralString()) << "</li>\n" << "</ol>\n"; } else { f << fmt_trans(item->GetString()); } if (item->HasContext()) f << " <span class='msgctxt'>[" << fmt_trans(item->GetContext()) << "]</span>"; f << "</td>\n"; // Translation: if (translated) { f << "<td class='tra' " << lang_tra << ">\n"; if (item->HasPlural()) { if (item->IsTranslated()) { f << "<ol class='plurals'>\n"; for (auto t: item->GetTranslations()) f << " <li>" << fmt_trans(t) << "</li>\n"; f << "</ol>\n"; } } else { f << fmt_trans(item->GetTranslation()); } f << "</td>\n"; } // Notes, if present: if (hasComments) { f << "</tr>\n" << "<tr class='comments'>\n" << " <td colspan='" << (translated ? 2 : 1) << "'><div>"; if (item->HasExtractedComments()) { f << "<p>\n"; for (auto& n: item->GetExtractedComments()) f << fmt_trans(n) << "<br>\n"; f << "</p>\n"; } if (item->HasComment()) { f << "<p>\n" << fmt_trans(item->GetComment()) << "</p>\n"; } f << "</div></td>\n"; } f << "</tr>\n"; } f << "</tbody>\n" "</table>\n" "</div>\n" "</body>\n" "</html>\n"; }