Added simple error handler for translations.

This commit is contained in:
23rd
2026-03-02 16:20:30 +03:00
parent 1e0a16a214
commit ccce8756ed
7 changed files with 81 additions and 31 deletions
+19 -2
View File
@@ -64,8 +64,25 @@ void TranslateBox(
state->to.current(),
crl::guard(box, [=](LanguageId id) { state->to = id; })));
},
.request = [=](LanguageId to, Fn<void(std::optional<TextWithEntities>)> done) {
state->provider->request(*request, to, std::move(done));
.request = [=](
LanguageId to,
Fn<void(TranslateBoxContentResult)> done) {
state->provider->request(
*request,
to,
[done = std::move(done)](TranslateProviderResult result) {
using ProviderError = TranslateProviderError;
using UiError = TranslateBoxContentError;
done(TranslateBoxContentResult{
.text = std::move(result.text),
.error = (result.error
== ProviderError::LocalLanguagePackMissing)
? UiError::LocalLanguagePackMissing
: (result.error == ProviderError::None)
? UiError::None
: UiError::Unknown,
});
});
},
});
}
@@ -86,7 +86,7 @@ void TranslateBoxContent(
const auto textContext = std::move(args.textContext);
const auto chooseTo = std::make_shared<Fn<void()>>(std::move(args.chooseTo));
const auto request = std::make_shared<
Fn<void(LanguageId, Fn<void(std::optional<TextWithEntities>)>)>>(
Fn<void(LanguageId, Fn<void(TranslateBoxContentResult)>)>>(
std::move(args.request));
auto to = std::move(args.to) | rpl::start_spawning(box->lifetime());
@@ -181,9 +181,12 @@ void TranslateBoxContent(
};
const auto state = box->lifetime().make_state<State>();
const auto showText = [=](std::optional<TextWithEntities> translatedText) {
auto value = translatedText.value_or(
tr::italic(tr::lng_translate_box_error(tr::now)));
const auto showText = [=](TranslateBoxContentResult result) {
using UiError = TranslateBoxContentError;
auto value = result.text.value_or(
tr::italic(((result.error == UiError::LocalLanguagePackMissing)
? tr::lng_translate_box_error_language_pack_not_installed
: tr::lng_translate_box_error)(tr::now)));
translated->entity()->setMarkedText(value, textContext);
translated->show(anim::type::instant);
loading->hide(anim::type::instant);
@@ -192,11 +195,11 @@ void TranslateBoxContent(
const auto requestId = ++state->requestId;
loading->show(anim::type::instant);
translated->hide(anim::type::instant);
(*request)(id, [=](std::optional<TextWithEntities> translatedText) {
(*request)(id, [=](TranslateBoxContentResult result) {
if (state->requestId != requestId) {
return;
}
showText(std::move(translatedText));
showText(std::move(result));
});
};
std::move(to) | rpl::on_next(send, box->lifetime());
@@ -15,6 +15,17 @@ struct MarkedContext;
namespace Ui {
enum class TranslateBoxContentError {
None = 0,
Unknown,
LocalLanguagePackMissing,
};
struct TranslateBoxContentResult {
std::optional<TextWithEntities> text;
TranslateBoxContentError error = TranslateBoxContentError::None;
};
class GenericBox;
struct TranslateBoxContentArgs {
@@ -23,7 +34,7 @@ struct TranslateBoxContentArgs {
Text::MarkedContext textContext;
rpl::producer<LanguageId> to;
Fn<void()> chooseTo;
Fn<void(LanguageId, Fn<void(std::optional<TextWithEntities>)>)> request;
Fn<void(LanguageId, Fn<void(TranslateBoxContentResult)>)> request;
};
void TranslateBoxContent(
@@ -28,7 +28,7 @@ public:
void request(
TranslateProviderRequest request,
LanguageId to,
Fn<void(std::optional<TextWithEntities>)> done) override {
Fn<void(TranslateProviderResult)> done) override {
using Flag = MTPmessages_TranslateText::Flag;
const auto flags = request.msgId
? (Flag::f_peer | Flag::f_id)
@@ -36,7 +36,9 @@ public:
? Flag::f_text
: Flag(0);
if (!flags) {
done(std::nullopt);
done(TranslateProviderResult{
.error = TranslateProviderError::Unknown,
});
return;
}
_api.request(MTPmessages_TranslateText(
@@ -58,12 +60,18 @@ public:
const auto &data = result.data();
const auto &list = data.vresult().v;
done(list.isEmpty()
? std::optional<TextWithEntities>()
: std::optional<TextWithEntities>(Api::ParseTextWithEntities(
&request.peer->session(),
list.front())));
? TranslateProviderResult{
.error = TranslateProviderError::Unknown,
}
: TranslateProviderResult{
.text = Api::ParseTextWithEntities(
&request.peer->session(),
list.front()),
});
}).fail([=](const MTP::Error &) {
done(std::nullopt);
done(TranslateProviderResult{
.error = TranslateProviderError::Unknown,
});
}).send();
}
@@ -17,6 +17,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Platform {
namespace {
[[nodiscard]] Ui::TranslateProviderError ParseErrorCode(
const char *errorUtf8) {
return !std::strcmp(errorUtf8, "local-language-pack-missing")
? Ui::TranslateProviderError::LocalLanguagePackMissing
: Ui::TranslateProviderError::Unknown;
}
class TranslateProvider final : public Ui::TranslateProvider
, public base::has_weak_ptr {
public:
@@ -27,20 +34,24 @@ public:
void request(
Ui::TranslateProviderRequest request,
LanguageId to,
Fn<void(std::optional<TextWithEntities>)> done) override {
Fn<void(Ui::TranslateProviderResult)> done) override {
if (request.text.text.isEmpty()) {
done(std::nullopt);
done(Ui::TranslateProviderResult{
.error = Ui::TranslateProviderError::Unknown,
});
return;
}
const auto text = request.text.text.toUtf8();
const auto target = to.twoLetterCode().toUtf8();
if (target.isEmpty()) {
done(std::nullopt);
done(Ui::TranslateProviderResult{
.error = Ui::TranslateProviderError::Unknown,
});
return;
}
struct CallbackContext {
base::weak_ptr<TranslateProvider> provider;
Fn<void(std::optional<TextWithEntities>)> done;
Fn<void(Ui::TranslateProviderResult)> done;
};
auto ownedContext = std::make_unique<CallbackContext>(CallbackContext{
.provider = base::make_weak(this),
@@ -55,27 +66,26 @@ public:
static_cast<CallbackContext*>(context));
auto done = std::move(guard->done);
const auto isAlive = (guard->provider.get() != nullptr);
auto translatedText = QString();
auto hasError = (resultUtf8 == nullptr);
auto result = Ui::TranslateProviderResult();
if (resultUtf8 != nullptr) {
translatedText = QString::fromUtf8(resultUtf8);
result.text = TextWithEntities{
.text = QString::fromUtf8(resultUtf8),
};
std::free(const_cast<char*>(resultUtf8));
}
if (errorUtf8 != nullptr) {
hasError = true;
result.error = ParseErrorCode(errorUtf8);
std::free(const_cast<char*>(errorUtf8));
} else if (!result.text.has_value()) {
result.error = Ui::TranslateProviderError::Unknown;
}
if (!isAlive) {
return;
}
crl::on_main([=,
done = std::move(done),
translatedText = std::move(translatedText)] {
done(hasError
? std::optional<TextWithEntities>()
: std::optional<TextWithEntities>(TextWithEntities{
.text = std::move(translatedText),
}));
result = std::move(result)] {
done(std::move(result));
});
});
}