Moved out api translations as separated provider.

This commit is contained in:
23rd
2026-03-03 13:04:23 +03:00
parent 8a9409005f
commit cec580a645
4 changed files with 181 additions and 44 deletions
+2
View File
@@ -1230,6 +1230,8 @@ PRIVATE
lang/lang_numbers_animation.h
lang/lang_translator.cpp
lang/lang_translator.h
lang/translate_provider.cpp
lang/translate_provider.h
layout/layout_document_generic_preview.cpp
layout/layout_document_generic_preview.h
layout/layout_item_base.cpp
+12 -44
View File
@@ -7,8 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/translate_box.h"
#include "boxes/translate_box_content.h"
#include "lang/translate_provider.h"
#include "api/api_text_entities.h" // Api::EntitiesToMTP / EntitiesFromMTP.
#include "core/application.h"
#include "core/core_settings.h"
#include "core/ui_integration.h"
@@ -18,7 +18,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_instance.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "mtproto/sender.h"
#include "spellcheck/platform/platform_language.h"
#include "ui/boxes/choose_language_box.h"
#include "ui/layers/generic_box.h"
@@ -39,29 +38,24 @@ void TranslateBox(
TextWithEntities text,
bool hasCopyRestriction) {
struct State {
State(not_null<Main::Session*> session) : api(&session->mtp()) {
State(not_null<Main::Session*> session)
: provider(CreateTranslateProvider(session)) {
}
MTP::Sender api;
std::unique_ptr<TranslateProvider> provider;
rpl::variable<LanguageId> to;
};
const auto state = box->lifetime().make_state<State>(&peer->session());
state->to = ChooseTranslateTo(peer->owner().history(peer));
if (!IsServerMsgId(msgId)) {
msgId = 0;
}
using Flag = MTPmessages_TranslateText::Flag;
const auto flags = msgId
? (Flag::f_peer | Flag::f_id)
: !text.text.isEmpty()
? Flag::f_text
: Flag(0);
const auto requestText = text;
const auto request = std::make_shared<TranslateProviderRequest>(
PrepareTranslateProviderRequest(
state->provider.get(),
peer,
msgId,
std::move(text)));
TranslateBoxContent(box, {
.text = std::move(text),
.text = request->text,
.hasCopyRestriction = hasCopyRestriction,
.textContext = Core::TextContext({ .session = &peer->session() }),
.to = state->to.value(),
@@ -71,33 +65,7 @@ void TranslateBox(
crl::guard(box, [=](LanguageId id) { state->to = id; })));
},
.request = [=](LanguageId to, Fn<void(std::optional<TextWithEntities>)> done) {
const auto callback = std::make_shared<
Fn<void(std::optional<TextWithEntities>)>>(std::move(done));
state->api.request(MTPmessages_TranslateText(
MTP_flags(flags),
msgId ? peer->input() : MTP_inputPeerEmpty(),
(msgId
? MTP_vector<MTPint>(1, MTP_int(msgId))
: MTPVector<MTPint>()),
(msgId
? MTPVector<MTPTextWithEntities>()
: MTP_vector<MTPTextWithEntities>(1, MTP_textWithEntities(
MTP_string(requestText.text),
Api::EntitiesToMTP(
&peer->session(),
requestText.entities,
Api::ConvertOption::SkipLocal)))),
MTP_string(to.twoLetterCode())
)).done([=](const MTPmessages_TranslatedText &result) {
const auto &data = result.data();
const auto &list = data.vresult().v;
(*callback)(list.isEmpty()
? std::optional<TextWithEntities>()
: std::optional<TextWithEntities>(
Api::ParseTextWithEntities(&peer->session(), list.front())));
}).fail([=](const MTP::Error &) {
(*callback)(std::nullopt);
}).send();
state->provider->request(*request, to, std::move(done));
},
});
}
@@ -0,0 +1,121 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "lang/translate_provider.h"
#include "api/api_text_entities.h"
#include "data/data_msg_id.h"
#include "data/data_peer.h"
#include "data/data_session.h"
#include "history/history_item.h"
#include "main/main_session.h"
#include "mtproto/sender.h"
namespace Ui {
namespace {
enum class TranslateProviderKind {
MTProtoServer,
};
[[nodiscard]] TranslateProviderKind CurrentTranslateProviderKind() {
return TranslateProviderKind::MTProtoServer;
}
class MTProtoTranslateProvider final : public TranslateProvider {
public:
explicit MTProtoTranslateProvider(not_null<Main::Session*> session)
: _api(&session->mtp()) {
}
[[nodiscard]] bool supportsMessageId() const override {
return true;
}
void request(
TranslateProviderRequest request,
LanguageId to,
Fn<void(std::optional<TextWithEntities>)> done) override {
using Flag = MTPmessages_TranslateText::Flag;
const auto flags = request.msgId
? (Flag::f_peer | Flag::f_id)
: !request.text.text.isEmpty()
? Flag::f_text
: Flag(0);
if (!flags) {
done(std::nullopt);
return;
}
const auto callback = std::make_shared<
Fn<void(std::optional<TextWithEntities>)>>(std::move(done));
_api.request(MTPmessages_TranslateText(
MTP_flags(flags),
request.msgId ? request.peer->input() : MTP_inputPeerEmpty(),
(request.msgId
? MTP_vector<MTPint>(1, MTP_int(request.msgId))
: MTPVector<MTPint>()),
(request.msgId
? MTPVector<MTPTextWithEntities>()
: MTP_vector<MTPTextWithEntities>(1, MTP_textWithEntities(
MTP_string(request.text.text),
Api::EntitiesToMTP(
&request.peer->session(),
request.text.entities,
Api::ConvertOption::SkipLocal)))),
MTP_string(to.twoLetterCode())
)).done([=](const MTPmessages_TranslatedText &result) {
const auto &data = result.data();
const auto &list = data.vresult().v;
(*callback)(list.isEmpty()
? std::optional<TextWithEntities>()
: std::optional<TextWithEntities>(Api::ParseTextWithEntities(
&request.peer->session(),
list.front())));
}).fail([=](const MTP::Error &) {
(*callback)(std::nullopt);
}).send();
}
private:
MTP::Sender _api;
};
} // namespace
std::unique_ptr<TranslateProvider> CreateTranslateProvider(
not_null<Main::Session*> session) {
switch (CurrentTranslateProviderKind()) {
case TranslateProviderKind::MTProtoServer:
return std::make_unique<MTProtoTranslateProvider>(session);
}
return std::make_unique<MTProtoTranslateProvider>(session);
}
TranslateProviderRequest PrepareTranslateProviderRequest(
not_null<TranslateProvider*> provider,
not_null<PeerData*> peer,
MsgId msgId,
TextWithEntities text) {
auto result = TranslateProviderRequest{
.peer = peer,
.msgId = IsServerMsgId(msgId) ? msgId : MsgId(),
.text = std::move(text),
};
if (provider->supportsMessageId()) {
return result;
}
if (result.msgId) {
if (const auto item = peer->owner().message(peer, result.msgId)) {
result.text = item->originalText();
}
result.msgId = 0;
}
return result;
}
} // namespace Ui
@@ -0,0 +1,46 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "spellcheck/platform/platform_language.h"
#include "ui/text/text_entity.h"
class PeerData;
namespace Main {
class Session;
} // namespace Main
namespace Ui {
struct TranslateProviderRequest {
not_null<PeerData*> peer;
MsgId msgId = 0;
TextWithEntities text;
};
class TranslateProvider {
public:
virtual ~TranslateProvider() = default;
[[nodiscard]] virtual bool supportsMessageId() const = 0;
virtual void request(
TranslateProviderRequest request,
LanguageId to,
Fn<void(std::optional<TextWithEntities>)> done) = 0;
};
[[nodiscard]] std::unique_ptr<TranslateProvider> CreateTranslateProvider(
not_null<Main::Session*> session);
[[nodiscard]] TranslateProviderRequest PrepareTranslateProviderRequest(
not_null<TranslateProvider*> provider,
not_null<PeerData*> peer,
MsgId msgId,
TextWithEntities text);
} // namespace Ui