Moved generation of short string for large numbers in one place.

- Added new plural tag "kPluralShortTag".
 - Added support of new plural tag to code generator.
 - Removed FormatViewsCount from history_message.
 - Removed FormatLargeNumber from history_media_poll.
 - Added FormatCountToShort to lang_tag.
This commit is contained in:
23rd 2019-05-03 14:37:26 +03:00 committed by John Preston
parent 996bd942eb
commit 5d321f7c59
10 changed files with 65 additions and 74 deletions

View File

@ -124,6 +124,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_channel_admins_link#one" = "{count} administrator";
"lng_channel_admins_link#other" = "{count} administrators";
"lng_channel_views#one" = "{count_short}";
"lng_channel_views#other" = "{count_short}";
"lng_flood_error" = "Too many tries. Please try again later.";
"lng_gif_error" = "An error has occurred while reading GIF animation :(";
"lng_edit_error" = "You cannot edit this message";
@ -1968,6 +1971,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_polls_closed" = "Final results";
"lng_polls_votes_count#one" = "{count} vote";
"lng_polls_votes_count#other" = "{count} votes";
"lng_polls_votes_count_short#one" = "{count_short} vote";
"lng_polls_votes_count_short#other" = "{count_short} votes";
"lng_polls_votes_none" = "No votes";
"lng_polls_retract" = "Retract vote";
"lng_polls_stop" = "Stop poll";

View File

@ -136,11 +136,12 @@ QString lang(LangKey key);\n\
auto nonPluralTagFound = false;
for (auto &tagData : entry.tags) {
auto &tag = tagData.tag;
auto isPluralTag = isPlural && (tag == kPluralTag);
auto isPluralTag = isPlural && (tag == kPluralTag || tag == kPluralShortTag);
genericParams.push_back("lngtag_" + tag + ", " + (isPluralTag ? "float64 " : "const ResultString &") + tag + "__val");
params.push_back("lngtag_" + tag + ", " + (isPluralTag ? "float64 " : "const QString &") + tag + "__val");
if (isPluralTag) {
plural = "\tauto plural = Lang::Plural(" + key + ", " + kPluralTag + "__val);\n";
const auto isShortTag = (tag == kPluralShortTag) ? ("true") : ("false");
plural = "\tauto plural = Lang::Plural(" + key + ", " + tag + "__val, " + isShortTag + ");\n";
applyTags.push_back("\tresult = Lang::ReplaceTag<ResultString>::Call(std::move(result), lt_" + tag + ", Lang::StartReplacements<ResultString>::Call(std::move(plural.replacement)));\n");
} else {
nonPluralTagFound = true;

View File

@ -75,6 +75,7 @@ const std::array<QString, kPluralPartCount> kPluralParts = { {
} };
const QString kPluralTag = "count";
const QString kPluralShortTag = kPluralTag + "_short";
QString ComputePluralKey(const QString &base, int index) {
return base + "__plural" + QString::number(index);
@ -144,7 +145,7 @@ void ParsedFile::fillPluralTags() {
}
}
logAssert(!tags.empty());
logAssert(tags.front().tag == kPluralTag);
logAssert(tags.front().tag == kPluralTag || tags.front().tag == kPluralShortTag);
// Set this tags list to all plural variants.
for (auto j = i; j != i + kPluralPartCount; ++j) {
@ -208,6 +209,15 @@ QString ParsedFile::extractTagData(const QString &tagText, LangPack *to) {
logErrorBadString() << "duplicate found for tag '" << tagText.toStdString() << "'";
return QString();
}
//Don't use both plural tags in one string.
if (previousTag.tag.startsWith(kPluralTag) && tag.startsWith(kPluralTag)) {
logErrorBadString() <<
"duplicate found for count tag '" <<
previousTag.tag.toStdString() <<
"' and '" <<
tag.toStdString() << "'";
return QString();
}
}
auto index = 0;
auto tagIndex = result_.tags.size();
@ -250,7 +260,7 @@ void ParsedFile::addEntity(QString key, const QString &value) {
auto pluralPart = key.mid(pluralPartOffset + 1);
pluralIndex = std::find(kPluralParts.begin(), kPluralParts.end(), pluralPart) - kPluralParts.begin();
if (pluralIndex < 0 || pluralIndex >= kPluralParts.size()) {
logError(kErrorBadString) << "bad plural part for key '" << key.toStdString() << "': '" << pluralPart.toStdString() << "'";
logErrorBadString() << "bad plural part for key '" << key.toStdString() << "': '" << pluralPart.toStdString() << "'";
return;
}
key = key.mid(0, pluralPartOffset);
@ -260,7 +270,7 @@ void ParsedFile::addEntity(QString key, const QString &value) {
if (entry.key == key) {
if (entry.keyBase.isEmpty() || !entry.tags.empty()) {
// Empty tags in plural entry means it was not encountered yet.
logError(kErrorBadString) << "duplicate found for key '" << key.toStdString() << "'";
logErrorBadString() << "duplicate found for key '" << key.toStdString() << "'";
return false;
}
}
@ -308,12 +318,20 @@ void ParsedFile::addEntity(QString key, const QString &value) {
realEntry.value = entry.value;
// Add all new tags to the existing ones.
realEntry.tags = std::vector<LangPack::Tag>(1, LangPack::Tag { kPluralTag });
realEntry.tags = std::vector<LangPack::Tag>(0);
for (auto &tag : entry.tags) {
if (std::find(realEntry.tags.begin(), realEntry.tags.end(), tag) == realEntry.tags.end()) {
realEntry.tags.push_back(tag);
if (tag.tag == kPluralTag || tag.tag == kPluralShortTag) {
realEntry.tags.insert(realEntry.tags.begin(), tag);
} else {
realEntry.tags.push_back(tag);
}
}
}
if (realEntry.tags.empty()) {
realEntry.tags.push_back(LangPack::Tag { kPluralTag });
}
} else {
result_.entries.push_back(entry);
for (auto &pluralEntry : tagsData.entries) {

View File

@ -21,6 +21,7 @@ namespace lang {
constexpr auto kPluralPartCount = 6;
extern const std::array<QString, kPluralPartCount> kPluralParts;
extern const QString kPluralTag;
extern const QString kPluralShortTag;
QString ComputePluralKey(const QString &base, int index);
struct LangPack {

View File

@ -721,25 +721,6 @@ void HistoryMessage::setupForwardedComponent(const CreateConfig &config) {
forwarded->savedFromMsgId = config.savedFromMsgId;
}
QString FormatViewsCount(int views) {
if (views > 999999) {
views /= 100000;
if (views % 10) {
return QString::number(views / 10) + '.' + QString::number(views % 10) + 'M';
}
return QString::number(views / 10) + 'M';
} else if (views > 9999) {
views /= 100;
if (views % 10) {
return QString::number(views / 10) + '.' + QString::number(views % 10) + 'K';
}
return QString::number(views / 10) + 'K';
} else if (views > 0) {
return QString::number(views);
}
return qsl("1");
}
void HistoryMessage::refreshMedia(const MTPMessageMedia *media) {
_media = nullptr;
if (media) {
@ -1118,7 +1099,7 @@ void HistoryMessage::setViewsCount(int32 count) {
const auto was = views->_viewsWidth;
views->_views = count;
views->_viewsText = (views->_views >= 0)
? FormatViewsCount(views->_views)
? lng_channel_views(lt_count_short, views->_views)
: QString();
views->_viewsWidth = views->_viewsText.isEmpty()
? 0

View File

@ -22,7 +22,6 @@ QString GetErrorTextForForward(
not_null<PeerData*> peer,
const HistoryItemsList &items);
void FastShareMessage(not_null<HistoryItem*> item);
QString FormatViewsCount(int views);
class HistoryMessage
: public HistoryItem {

View File

@ -30,38 +30,6 @@ namespace {
using TextState = HistoryView::TextState;
struct FormattedLargeNumber {
int rounded = 0;
bool shortened = false;
QString text;
};
FormattedLargeNumber FormatLargeNumber(int64 number) {
auto result = FormattedLargeNumber();
const auto abs = std::abs(number);
const auto shorten = [&](int64 divider, char multiplier) {
const auto sign = (number > 0) ? 1 : -1;
const auto rounded = abs / (divider / 10);
result.rounded = sign * rounded * (divider / 10);
result.text = QString::number(sign * rounded / 10);
if (rounded % 10) {
result.text += '.' + QString::number(rounded % 10) + multiplier;
} else {
result.text += multiplier;
}
result.shortened = true;
};
if (abs >= 1'000'000) {
shorten(1'000'000, 'M');
} else if (abs >= 10'000) {
shorten(1'000, 'K');
} else {
result.rounded = number;
result.text = QString::number(number);
}
return result;
}
struct PercentCounterItem {
int index = 0;
int percent = 0;
@ -417,17 +385,9 @@ void HistoryPoll::updateTotalVotes() {
return;
}
_totalVotes = _poll->totalVoters;
const auto string = [&] {
if (!_totalVotes) {
return lang(lng_polls_votes_none);
}
const auto format = FormatLargeNumber(_totalVotes);
auto text = lng_polls_votes_count(lt_count, format.rounded);
if (format.shortened) {
text.replace(QString::number(format.rounded), format.text);
}
return text;
}();
const auto string = !_totalVotes
? lang(lng_polls_votes_none)
: lng_polls_votes_count_short(lt_count_short, _totalVotes);
_totalVotesLabel.setText(st::msgDateTextStyle, string);
}

View File

@ -1798,7 +1798,7 @@ void Message::initTime() {
}
if (const auto views = item->Get<HistoryMessageViews>()) {
views->_viewsText = (views->_views >= 0)
? FormatViewsCount(views->_views)
? lng_channel_views(lt_count_short, views->_views)
: QString();
views->_viewsWidth = views->_viewsText.isEmpty()
? 0

View File

@ -914,7 +914,30 @@ int NonZeroPartToInt(QString value) {
: (value.isEmpty() ? 0 : value.toInt());
}
PluralResult Plural(ushort keyBase, float64 value) {
inline QString FormatCountToShort(int64 number) {
const auto abs = std::abs(number);
auto result = QString();
const auto shorten = [&](int64 divider, char multiplier) {
const auto sign = (number > 0) ? 1 : -1;
const auto rounded = abs / (divider / 10);
result = QString::number(sign * rounded / 10);
if (rounded % 10) {
result += '.' + QString::number(rounded % 10) + multiplier;
} else {
result += multiplier;
}
};
if (abs >= 1'000'000) {
shorten(1'000'000, 'M');
} else if (abs >= 10'000) {
shorten(1'000, 'K');
} else {
result = QString::number(number);
}
return result;
}
PluralResult Plural(ushort keyBase, float64 value, bool shortCount) {
// Simplified.
const auto n = qAbs(value);
const auto i = qFloor(n);
@ -939,6 +962,9 @@ PluralResult Plural(ushort keyBase, float64 value) {
t);
auto string = langpack.getValue(LangKey(keyBase + shift));
if (integer) {
if (shortCount) {
return { string, FormatCountToShort(qRound(value)) };
}
return { string, QString::number(qRound(value)) };
}
return { string, FormatDouble(value) };

View File

@ -17,7 +17,7 @@ struct PluralResult {
QString string;
QString replacement;
};
PluralResult Plural(ushort keyBase, float64 value);
PluralResult Plural(ushort keyBase, float64 value, bool shortCount = false);
void UpdatePluralRules(const QString &languageId);
template <typename ResultString>