4b3f7eb209
- Don't stick this in Settings, though, it becomes overly complicated.
274 lines
7.6 KiB
C++
274 lines
7.6 KiB
C++
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
|
*
|
|
* Copyright 2014, Teo Mrnjavac <teo@kde.org>
|
|
*
|
|
* Calamares is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Calamares is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "Retranslator.h"
|
|
|
|
#include "Settings.h"
|
|
#include "utils/Dirs.h"
|
|
#include "utils/Logger.h"
|
|
|
|
#include <QCoreApplication>
|
|
#include <QDir>
|
|
#include <QEvent>
|
|
#include <QTranslator>
|
|
|
|
static bool s_allowLocalTranslations = false;
|
|
|
|
/** @brief Helper class for loading translations
|
|
*
|
|
* This is used by the loadSingletonTranslator() function to hand off
|
|
* work to translation-type specific code.
|
|
*/
|
|
struct TranslationLoader
|
|
{
|
|
static QString mungeLocaleName( const QLocale& locale )
|
|
{
|
|
QString localeName = locale.name();
|
|
localeName.replace( "-", "_" );
|
|
|
|
if ( localeName == "C" )
|
|
{
|
|
localeName = "en";
|
|
}
|
|
|
|
// Special case of sr@latin
|
|
//
|
|
// See top-level CMakeLists.txt about special cases for translation loading.
|
|
if ( locale.language() == QLocale::Language::Serbian && locale.script() == QLocale::Script::LatinScript )
|
|
{
|
|
localeName = QStringLiteral( "sr@latin" );
|
|
}
|
|
return localeName;
|
|
}
|
|
|
|
TranslationLoader( const QLocale& locale )
|
|
: m_locale( locale )
|
|
, m_localeName( mungeLocaleName( locale ) )
|
|
{
|
|
}
|
|
|
|
virtual ~TranslationLoader();
|
|
/// @brief Loads @p translator with the specific translations of this type
|
|
virtual bool tryLoad( QTranslator* translator ) = 0;
|
|
|
|
const QLocale& m_locale;
|
|
QString m_localeName;
|
|
};
|
|
|
|
/// @brief Loads translations for branding
|
|
struct BrandingLoader : public TranslationLoader
|
|
{
|
|
BrandingLoader( const QLocale& locale, const QString& prefix )
|
|
: TranslationLoader( locale )
|
|
, m_prefix( prefix )
|
|
{
|
|
}
|
|
|
|
bool tryLoad( QTranslator* translator ) override;
|
|
|
|
QString m_prefix;
|
|
};
|
|
|
|
/// @brief Loads regular Calamares translations (program text)
|
|
struct CalamaresLoader : public TranslationLoader
|
|
{
|
|
using TranslationLoader::TranslationLoader;
|
|
bool tryLoad( QTranslator* translator ) override;
|
|
};
|
|
|
|
/// @brief Loads timezone name translations
|
|
struct TZLoader : public TranslationLoader
|
|
{
|
|
using TranslationLoader::TranslationLoader;
|
|
bool tryLoad( QTranslator* translator ) override;
|
|
};
|
|
|
|
TranslationLoader::~TranslationLoader() {}
|
|
|
|
bool
|
|
BrandingLoader::tryLoad( QTranslator* translator )
|
|
{
|
|
if ( m_prefix.isEmpty() )
|
|
{
|
|
return false;
|
|
}
|
|
QString brandingTranslationsDirPath( m_prefix );
|
|
brandingTranslationsDirPath.truncate( m_prefix.lastIndexOf( QDir::separator() ) );
|
|
QDir brandingTranslationsDir( brandingTranslationsDirPath );
|
|
if ( brandingTranslationsDir.exists() )
|
|
{
|
|
QString filenameBase( m_prefix );
|
|
filenameBase.remove( 0, m_prefix.lastIndexOf( QDir::separator() ) + 1 );
|
|
if ( translator->load( m_locale, filenameBase, "_", brandingTranslationsDir.absolutePath() ) )
|
|
{
|
|
cDebug() << Logger::SubEntry << "Branding using locale:" << m_localeName;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
cDebug() << Logger::SubEntry << "Branding using default, system locale not found:" << m_localeName;
|
|
// TODO: this loads something completely different
|
|
return translator->load( m_prefix + "en" );
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool
|
|
tryLoad( QTranslator* translator, const QString& prefix, const QString& localeName )
|
|
{
|
|
// In debug-mode, try loading from the current directory
|
|
if ( s_allowLocalTranslations && translator->load( prefix + localeName ) )
|
|
{
|
|
cDebug() << Logger::SubEntry << "Loaded local translation" << prefix << localeName;
|
|
return true;
|
|
}
|
|
|
|
// Or load from appDataDir -- often /usr/share/calamares -- subdirectory land/
|
|
QDir localeData( CalamaresUtils::appDataDir() );
|
|
if ( localeData.exists()
|
|
&& translator->load( localeData.absolutePath() + QStringLiteral( "/lang/" ) + prefix + localeName ) )
|
|
{
|
|
cDebug() << Logger::SubEntry << "Loaded appdata translation" << prefix << localeName;
|
|
return true;
|
|
}
|
|
|
|
// Or from QRC (most common)
|
|
if ( translator->load( QStringLiteral( ":/lang/" ) + prefix + localeName ) )
|
|
{
|
|
cDebug() << Logger::SubEntry << "Loaded QRC translation" << prefix << localeName;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
cDebug() << Logger::SubEntry << "No translation for" << prefix << localeName << "using default (en)";
|
|
return translator->load( QStringLiteral( ":/lang/" ) + prefix + QStringLiteral( "en" ) );
|
|
}
|
|
}
|
|
|
|
bool
|
|
CalamaresLoader::tryLoad( QTranslator* translator )
|
|
{
|
|
return ::tryLoad( translator, QStringLiteral( "calamares_" ), m_localeName );
|
|
}
|
|
|
|
bool
|
|
TZLoader::tryLoad( QTranslator* translator )
|
|
{
|
|
return ::tryLoad( translator, QStringLiteral( "tz_" ), m_localeName );
|
|
}
|
|
|
|
static void
|
|
loadSingletonTranslator( TranslationLoader&& loader, QTranslator*& translator_p )
|
|
{
|
|
QTranslator* translator = new QTranslator();
|
|
loader.tryLoad( translator );
|
|
|
|
if ( translator_p )
|
|
{
|
|
QCoreApplication::removeTranslator( translator_p );
|
|
delete translator_p;
|
|
}
|
|
|
|
QCoreApplication::installTranslator( translator );
|
|
translator_p = translator;
|
|
}
|
|
|
|
namespace CalamaresUtils
|
|
{
|
|
static QTranslator* s_brandingTranslator = nullptr;
|
|
static QTranslator* s_translator = nullptr;
|
|
static QTranslator* s_tztranslator = nullptr;
|
|
static QString s_translatorLocaleName;
|
|
|
|
void
|
|
installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* )
|
|
{
|
|
loadSingletonTranslator( BrandingLoader( locale, brandingTranslationsPrefix ), s_brandingTranslator );
|
|
loadSingletonTranslator( TZLoader( locale ), s_tztranslator );
|
|
|
|
CalamaresLoader l( locale ); // because we want the extracted localeName
|
|
loadSingletonTranslator( std::move( l ), s_translator );
|
|
s_translatorLocaleName = l.m_localeName;
|
|
}
|
|
|
|
|
|
QString
|
|
translatorLocaleName()
|
|
{
|
|
return s_translatorLocaleName;
|
|
}
|
|
|
|
Retranslator*
|
|
Retranslator::retranslatorFor( QObject* parent )
|
|
{
|
|
Retranslator* r = nullptr;
|
|
for ( QObject* child : parent->children() )
|
|
{
|
|
r = qobject_cast< Retranslator* >( child );
|
|
if ( r )
|
|
{
|
|
return r;
|
|
}
|
|
}
|
|
|
|
return new Retranslator( parent );
|
|
}
|
|
|
|
void
|
|
Retranslator::attachRetranslator( QObject* parent, std::function< void( void ) > retranslateFunc )
|
|
{
|
|
retranslatorFor( parent )->m_retranslateFuncList.append( retranslateFunc );
|
|
retranslateFunc();
|
|
}
|
|
|
|
|
|
Retranslator::Retranslator( QObject* parent )
|
|
: QObject( parent )
|
|
{
|
|
parent->installEventFilter( this );
|
|
}
|
|
|
|
|
|
bool
|
|
Retranslator::eventFilter( QObject* obj, QEvent* e )
|
|
{
|
|
if ( obj == parent() )
|
|
{
|
|
if ( e->type() == QEvent::LanguageChange )
|
|
{
|
|
foreach ( std::function< void() > func, m_retranslateFuncList )
|
|
{
|
|
func();
|
|
}
|
|
emit languageChange();
|
|
}
|
|
}
|
|
// pass the event on to the base
|
|
return QObject::eventFilter( obj, e );
|
|
}
|
|
|
|
void
|
|
setAllowLocalTranslation( bool allow )
|
|
{
|
|
s_allowLocalTranslations = allow;
|
|
}
|
|
|
|
|
|
} // namespace CalamaresUtils
|