Retranslate Settings when language is changed.

Also suggest user to change language from 'en' to his for one time.
This commit is contained in:
John Preston 2017-04-18 20:37:14 +03:00
parent f5dfeb0c50
commit 3f0b57ec11
17 changed files with 183 additions and 59 deletions

View file

@ -87,9 +87,9 @@ void LanguageBox::Inner::languageChanged(int languageIndex) {
}
void LanguageBox::prepare() {
refreshLangItems();
refreshLang();
subscribe(Lang::Current().updated(), [this] {
refreshLangItems();
refreshLang();
});
_inner = setInnerWidget(object_ptr<Inner>(this, &_languages), st::boxLayerScroll);
@ -100,7 +100,7 @@ void LanguageBox::prepare() {
});
}
void LanguageBox::refreshLangItems() {
void LanguageBox::refreshLang() {
clearButtons();
addButton(lang(lng_box_ok), [this] { closeBox(); });

View file

@ -42,7 +42,7 @@ private:
void refresh();
void refreshLanguages();
void refreshLangItems();
void refreshLang();
Languages _languages;

View file

@ -26,6 +26,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "messenger.h"
#include "apiwrap.h"
#include "auth_session.h"
#include "boxes/confirm_box.h"
namespace Lang {
@ -35,12 +36,11 @@ CloudManager::CloudManager(Instance &langpack, gsl::not_null<MTP::Instance*> mtp
}
void CloudManager::requestLangPackDifference() {
auto &langpack = Lang::Current();
if (langpack.isCustom() || _langPackRequestId) {
if (_langpack.isCustom() || _langPackRequestId) {
return;
}
auto version = langpack.version();
auto version = _langpack.version();
if (version > 0) {
_langPackRequestId = request(MTPlangpack_GetDifference(MTP_int(version))).done([this](const MTPLangPackDifference &result) {
_langPackRequestId = 0;
@ -60,24 +60,24 @@ void CloudManager::requestLangPackDifference() {
void CloudManager::applyLangPackDifference(const MTPLangPackDifference &difference) {
Expects(difference.type() == mtpc_langPackDifference);
auto &current = Lang::Current();
if (current.isCustom()) {
if (_langpack.isCustom()) {
return;
}
auto &langpack = difference.c_langPackDifference();
switchLangPackId(qs(langpack.vlang_code));
if (current.version() < langpack.vfrom_version.v) {
requestLangPackDifference();
} else if (!langpack.vstrings.v.isEmpty()) {
current.applyDifference(langpack);
Local::writeLangPack();
auto fullLangPackUpdated = (langpack.vfrom_version.v == 0);
if (fullLangPackUpdated) {
Lang::Current().updated().notify();
auto langpackId = qs(langpack.vlang_code);
if (needToApplyLangPack(langpackId)) {
applyLangPackData(langpack);
} else if (_langpack.id().isEmpty()) {
_offerSwitchToId = langpackId;
if (langpack.vfrom_version.v == 0) {
_offerSwitchToData = std::make_unique<MTPLangPackDifference>(difference);
} else {
_offerSwitchToData.reset();
}
offerSwitchLangPack();
} else {
LOG(("Lang Info: Up to date."));
LOG(("Lang Warning: Ignoring update for '%1' because our language is '%2'").arg(langpackId).arg(_langpack.id()));
}
}
@ -99,21 +99,98 @@ void CloudManager::requestLanguageList() {
}).send();
}
bool CloudManager::needToApplyLangPack(const QString &id) {
auto currentId = _langpack.id();
if (currentId == id) {
return true;
} else if (currentId.isEmpty() && id == DefaultLanguageId()) {
return true;
}
return false;
}
void CloudManager::offerSwitchLangPack() {
Expects(!_offerSwitchToId.isEmpty());
Expects(_offerSwitchToId != DefaultLanguageId());
if (!showOfferSwitchBox()) {
subscribe(languageListChanged(), [this] {
showOfferSwitchBox();
});
requestLanguageList();
}
}
QString CloudManager::findOfferedLanguageName() {
for_const (auto &language, _languages) {
if (language.id == _offerSwitchToId) {
return language.name;
}
}
return QString();
}
bool CloudManager::showOfferSwitchBox() {
auto name = findOfferedLanguageName();
if (name.isEmpty()) {
return false;
}
Ui::show(Box<ConfirmBox>("Do you want to switch your language to " + name + "? You can always change your language in Settings.", "Change", lang(lng_cancel), [this] {
Ui::hideLayer();
if (_offerSwitchToId.isEmpty()) {
return;
}
if (_offerSwitchToData) {
t_assert(_offerSwitchToData->type() == mtpc_langPackDifference);
applyLangPackData(base::take(_offerSwitchToData)->c_langPackDifference());
} else {
switchToLanguage(_offerSwitchToId);
}
}, [this] {
Ui::hideLayer();
changeIdAndReInitConnection(DefaultLanguageId());
Local::writeLangPack();
}));
return true;
}
void CloudManager::applyLangPackData(const MTPDlangPackDifference &data) {
switchLangPackId(qs(data.vlang_code));
if (_langpack.version() < data.vfrom_version.v) {
requestLangPackDifference();
} else if (!data.vstrings.v.isEmpty()) {
_langpack.applyDifference(data);
Local::writeLangPack();
auto fullLangPackUpdated = (data.vfrom_version.v == 0);
if (fullLangPackUpdated) {
_langpack.updated().notify();
}
} else {
LOG(("Lang Info: Up to date."));
}
}
void CloudManager::switchToLanguage(const QString &id) {
switchLangPackId(id);
requestLangPackDifference();
}
void CloudManager::switchLangPackId(const QString &id) {
auto &current = Lang::Current();
if (current.id() != id) {
current.switchToId(id);
auto mtproto = requestMTP();
mtproto->reInitConnection(mtproto->mainDcId());
auto currentId = _langpack.id();
auto notChanged = (currentId == id) || (currentId.isEmpty() && id == DefaultLanguageId());
if (!notChanged) {
changeIdAndReInitConnection(id);
}
}
void CloudManager::changeIdAndReInitConnection(const QString &id) {
_langpack.switchToId(id);
auto mtproto = requestMTP();
mtproto->reInitConnection(mtproto->mainDcId());
}
CloudManager &CurrentCloudManager() {
auto result = Messenger::Instance().langCloudManager();
t_assert(result != nullptr);

View file

@ -30,7 +30,7 @@ namespace Lang {
class Instance;
class CloudManager : private MTP::Sender {
class CloudManager : private MTP::Sender, private base::Subscriber {
public:
CloudManager(Instance &langpack, gsl::not_null<MTP::Instance*> mtproto);
@ -53,8 +53,14 @@ public:
void switchToLanguage(const QString &id);
private:
void applyLangPack(const MTPUpdates &updates);
void offerSwitchLangPack();
bool showOfferSwitchBox();
QString findOfferedLanguageName();
bool needToApplyLangPack(const QString &id);
void applyLangPackData(const MTPDlangPackDifference &data);
void switchLangPackId(const QString &id);
void changeIdAndReInitConnection(const QString &id);
Instance &_langpack;
Languages _languages;
@ -62,6 +68,9 @@ private:
mtpRequestId _langPackRequestId = 0;
mtpRequestId _languagesRequestId = 0;
QString _offerSwitchToId;
std::unique_ptr<MTPLangPackDifference> _offerSwitchToData;
};
inline bool operator==(const CloudManager::Language &a, const CloudManager::Language &b) {

View file

@ -230,6 +230,10 @@ bool ValueParser::parse() {
} // namespace
QString DefaultLanguageId() {
return str_const_toString(kDefaultLanguage);
}
void Instance::switchToId(const QString &id) {
reset();
_id = id;
@ -260,16 +264,12 @@ void Instance::fillDefaults() {
}
}
QString Instance::DefaultLanguageId() {
return str_const_toString(kDefaultLanguage);
}
QString Instance::cloudLangCode() const {
if (isCustom() || id().isEmpty()) {
if (_systemLanguage.isEmpty()) {
_systemLanguage = Platform::SystemLanguage();
if (_systemLanguage.isEmpty()) {
_systemLanguage = Instance::DefaultLanguageId();
_systemLanguage = DefaultLanguageId();
}
}
return _systemLanguage;
@ -410,7 +410,9 @@ void Instance::fillFromLegacy(int legacyId, const QString &legacyPath) {
}
void Instance::applyDifference(const MTPDlangPackDifference &difference) {
Expects(qs(difference.vlang_code) == _id);
auto updateLanguageId = qs(difference.vlang_code);
auto isValidUpdate = (updateLanguageId == _id) || (_id.isEmpty() && updateLanguageId == DefaultLanguageId());
Expects(isValidUpdate);
Expects(difference.vfrom_version.v <= _version);
_version = difference.vversion.v;

View file

@ -28,6 +28,11 @@ constexpr auto kLegacyLanguageNone = -2;
constexpr auto kLegacyCustomLanguage = -1;
constexpr auto kLegacyDefaultLanguage = 0;
QString DefaultLanguageId();
class Instance;
Instance &Current();
class Instance {
public:
Instance() {
@ -41,7 +46,6 @@ public:
Instance(Instance &&other) = default;
Instance &operator=(Instance &&other) = default;
static QString DefaultLanguageId();
QString cloudLangCode() const;
QString id() const {
@ -93,6 +97,4 @@ private:
};
Instance &Current();
} // namespace Lang

View file

@ -5690,11 +5690,11 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
////// Cloud langpacks
case mtpc_updateLangPack: {
auto &langpack = update.c_updateLangPack();
Messenger::Instance().langCloudManager()->applyLangPackDifference(langpack.vdifference);
Lang::CurrentCloudManager().applyLangPackDifference(langpack.vdifference);
} break;
case mtpc_updateLangPackTooLong: {
Messenger::Instance().langCloudManager()->requestLangPackDifference();
Lang::CurrentCloudManager().requestLangPackDifference();
} break;
}

View file

@ -43,10 +43,6 @@ LabeledLink::LabeledLink(QWidget *parent, const QString &label, const QString &t
connect(_link, SIGNAL(clicked()), parent, slot);
}
void LabeledLink::setLink(const QString &text) {
_link.create(this, text);
}
Ui::LinkButton *LabeledLink::link() const {
return _link;
}

View file

@ -36,8 +36,6 @@ public:
};
LabeledLink(QWidget *parent, const QString &label, const QString &text, Type type, const char *slot);
void setLink(const QString &text);
Ui::LinkButton *link() const;
int naturalWidth() const override;

View file

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "settings/settings_inner_widget.h"
#include "lang/lang_instance.h"
#include "styles/style_settings.h"
#include "settings/settings_cover.h"
#include "settings/settings_block_widget.h"
@ -37,10 +38,11 @@ namespace Settings {
InnerWidget::InnerWidget(QWidget *parent) : LayerInner(parent)
, _self(App::self()) {
refreshBlocks();
subscribe(Global::RefSelfChanged(), [this]() { selfUpdated(); });
subscribe(Global::RefSelfChanged(), [this] { fullRebuild(); });
subscribe(Lang::Current().updated(), [this] { fullRebuild(); });
}
void InnerWidget::selfUpdated() {
void InnerWidget::fullRebuild() {
_self = App::self();
refreshBlocks();

View file

@ -52,7 +52,7 @@ protected:
int resizeGetHeight(int newWidth) override;
private:
void selfUpdated();
void fullRebuild();
void refreshBlocks();
// Returns the new height value.

View file

@ -37,7 +37,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Settings {
LocalPasscodeState::LocalPasscodeState(QWidget *parent) : TWidget(parent)
, _edit(this, lang(Global::LocalPasscode() ? lng_passcode_change : lng_passcode_turn_on), st::boxLinkButton)
, _edit(this, GetEditPasscodeText(), st::boxLinkButton)
, _turnOff(this, lang(lng_passcode_turn_off), st::boxLinkButton) {
updateControls();
connect(_edit, SIGNAL(clicked()), this, SLOT(onEdit()));
@ -60,11 +60,15 @@ void LocalPasscodeState::onTurnOff() {
}
void LocalPasscodeState::updateControls() {
_edit->setText(lang(Global::LocalPasscode() ? lng_passcode_change : lng_passcode_turn_on));
_edit->setText(GetEditPasscodeText());
_edit->moveToLeft(0, 0);
_turnOff->setVisible(Global::LocalPasscode());
}
QString LocalPasscodeState::GetEditPasscodeText() {
return lang(Global::LocalPasscode() ? lng_passcode_change : lng_passcode_turn_on);
}
CloudPasswordState::CloudPasswordState(QWidget *parent) : TWidget(parent)
, _edit(this, lang(lng_cloud_password_set), st::boxLinkButton)
, _turnOff(this, lang(lng_passcode_turn_off), st::boxLinkButton) {
@ -169,6 +173,10 @@ PrivacyWidget::PrivacyWidget(QWidget *parent, UserData *self) : BlockWidget(pare
subscribe(Global::RefLocalPasscodeChanged(), [this]() { autoLockUpdated(); });
}
QString PrivacyWidget::GetAutoLockText() {
return (Global::AutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, Global::AutoLock() / 60) : lng_passcode_autolock_hours(lt_count, Global::AutoLock() / 3600);
}
void PrivacyWidget::createControls() {
style::margins marginSmall(0, 0, 0, st::settingsSmallSkip);
style::margins marginSkip(0, 0, 0, st::settingsSkip);
@ -180,7 +188,7 @@ void PrivacyWidget::createControls() {
addChildRow(_groupsInvitePrivacy, marginSmall, lang(lng_settings_groups_invite_privacy), SLOT(onGroupsInvitePrivacy()));
addChildRow(_localPasscodeState, marginSmall);
auto label = lang(psIdleSupported() ? lng_passcode_autolock_away : lng_passcode_autolock_inactive);
auto value = (Global::AutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, Global::AutoLock() / 60) : lng_passcode_autolock_hours(lt_count, Global::AutoLock() / 3600);
auto value = GetAutoLockText();
addChildRow(_autoLock, marginSmall, slidedPadding, label, value, LabeledLink::Type::Primary, SLOT(onAutoLock()));
if (!Global::LocalPasscode()) {
_autoLock->hideFast();
@ -192,7 +200,7 @@ void PrivacyWidget::createControls() {
void PrivacyWidget::autoLockUpdated() {
if (Global::LocalPasscode()) {
auto value = (Global::AutoLock() % 3600) ? lng_passcode_autolock_minutes(lt_count, Global::AutoLock() / 60) : lng_passcode_autolock_hours(lt_count, Global::AutoLock() / 3600);
auto value = GetAutoLockText();
_autoLock->entity()->link()->setText(value);
resizeToWidth(width());
}

View file

@ -39,6 +39,8 @@ private slots:
void onTurnOff();
private:
static QString GetEditPasscodeText();
void updateControls();
object_ptr<Ui::LinkButton> _edit;
@ -94,6 +96,8 @@ private slots:
void onSelfDestruction();
private:
static QString GetAutoLockText();
void createControls();
void autoLockUpdated();

View file

@ -197,13 +197,23 @@ void codesFeedString(const QString &text) {
} // namespace
Widget::Widget(QWidget *parent) {
setTitle(lang(lng_menu_settings));
refreshLang();
subscribe(Lang::Current().updated(), [this] {
refreshLang();
});
_inner = setInnerWidget(object_ptr<InnerWidget>(this));
setCloseClickHandler([]() {
Ui::hideSettingsAndLayer();
});
}
void Widget::refreshLang() {
setTitle(lang(lng_menu_settings));
update();
}
void Widget::showFinished() {
_inner->showFinished();
}

View file

@ -26,12 +26,14 @@ namespace Settings {
class InnerWidget;
class Widget : public Layer {
class Widget : public Layer, private base::Subscriber {
Q_OBJECT
public:
Widget(QWidget*);
void refreshLang();
void showFinished() override;
void parentResized() override;

View file

@ -39,22 +39,32 @@ Checkbox::Checkbox(QWidget *parent, const QString &text, bool checked, const sty
, _st(st)
, _text(_st.style, text, _checkboxOptions)
, _checked(checked) {
if (_st.width <= 0) {
resizeToWidth(_text.maxWidth() - _st.width);
} else {
resizeToWidth(_st.width);
}
_checkRect = myrtlrect(_st.margin.left(), _st.margin.top(), _st.diameter, _st.diameter);
resizeToText();
connect(this, SIGNAL(clicked()), this, SLOT(onClicked()));
setCursor(style::cur_pointer);
}
void Checkbox::setText(const QString &text) {
_text.setText(_st.style, text, _checkboxOptions);
resizeToText();
update();
}
bool Checkbox::checked() const {
return _checked;
}
void Checkbox::resizeToText() {
if (_st.width <= 0) {
resizeToWidth(_text.maxWidth() - _st.width);
} else {
resizeToWidth(_st.width);
}
_checkRect = myrtlrect(_st.margin.left(), _st.margin.top(), _st.diameter, _st.diameter);
}
void Checkbox::setChecked(bool checked, NotifyAboutChange notify) {
if (_checked != checked) {
_checked = checked;

View file

@ -31,6 +31,8 @@ class Checkbox : public RippleButton {
public:
Checkbox(QWidget *parent, const QString &text, bool checked = false, const style::Checkbox &st = st::defaultCheckbox);
void setText(const QString &text);
bool checked() const;
enum class NotifyAboutChange {
Notify,
@ -61,6 +63,8 @@ signals:
void changed();
private:
void resizeToText();
const style::Checkbox &_st;
Text _text;