view src/gui/locale.cc @ 139:478f3b366199

dep/animia: separate lots of things, use base class for OS stuff
author Paper <mrpapersonic@gmail.com>
date Sun, 12 Nov 2023 16:43:07 -0500
parents 39521c47c7a3
children 9613d72b097e
line wrap: on
line source

#include "gui/locale.h"
#include "core/strings.h"
#include <QTranslator>
#include <QLocale>
#include <QDir>
#include <QString>
#include <QApplication>
#include <iostream>

namespace Locale {

std::string GetLocaleFullName(const QLocale& locale) {
	QString res = QLocale::languageToString(locale.language());
	if (locale.country() != QLocale::AnyCountry)
		res += " (" + QLocale::countryToString(locale.country()) + ")";
	return Strings::ToUtf8String(res);
}

Locale::Locale() {
	RefreshAvailableLocales();

	/* default to en_US */
	if (!IsLocaleAvailable(QLocale()))
		SetActiveLocale(QLocale("en_US"));
	else /* TODO: is this needed? */
		SetActiveLocale(QLocale());
}

Locale::Locale(const std::string& name) {
	RefreshAvailableLocales();
	SetActiveLocale(QLocale(Strings::ToQString(name)));
}

QLocale Locale::GetLocale() const {
	return _locale;
}

std::vector<QLocale> Locale::GetAvailableLocales() const {
	return _available_translations;
}

void Locale::RefreshAvailableLocales() {
	_available_translations.clear();

	/* we will always have en_US */
	_available_translations.push_back(QLocale("en_US"));

	QDir dir(":/locale");
	if (!dir.exists())
		return;

	QStringList translations = dir.entryList({"*.qm"}, QDir::Files);

	_available_translations.reserve(translations.size());
	for (const QString& str : translations) {
		_available_translations.push_back(QLocale(str.mid(0, str.lastIndexOf("."))));
	}
}

bool Locale::IsLocaleAvailable(const QLocale& locale) const {
	for (const QLocale& l : _available_translations)
		if (l == locale)
			return true;
	return false;
}

bool Locale::SetActiveLocale(const QLocale& locale) {
	if (!IsLocaleAvailable(locale))
		return false;
	if (_locale == locale)
		return true; /* we're... already on this locale :) */

	_locale = locale;
	QLocale::setDefault(_locale);

	/* we can still do stuff even if one thing fails! */
	bool return_value = true;

	const QString name = _locale.name();
	if (!SwitchTranslator(_translator, QString(":/locale/%1.qm").arg(name)))
		return_value = false;

	const QString path = qApp->applicationDirPath();
	if (!SwitchTranslator(_translator_qt, path + QString("/translations/qt_%1.qm").arg(name))) {
		/* Sometimes Qt will have proper translations for the language, but not the specific
		   country. In that case, we still want to use that language. */
		const int underscore_index = name.lastIndexOf("_");
		if (!underscore_index)
			return false;

		const QString short_name = name.mid(0, underscore_index);
		if (!SwitchTranslator(_translator_qt, path + QString("/translations/qt_%1.qm").arg(short_name)))
			return_value = false;
	}

	return return_value;
}

bool Locale::SwitchTranslator(QTranslator& translator, const QString& path) {
	qApp->removeTranslator(&translator);

	if (!translator.load(path))
		return false;
	qApp->installTranslator(&translator);
	return true;
}

}