1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-12 00:54:20 +02:00

Merge pull request #208 from lliehu/i18n-fixes

Internationalization fixes to automatic playlist UI
This commit is contained in:
Uwe L. Korn
2014-04-16 00:36:01 +02:00
4 changed files with 56 additions and 38 deletions

View File

@@ -164,12 +164,12 @@ Tomahawk::EchonestControl::updateWidgets()
QComboBox* match = new QComboBox(); QComboBox* match = new QComboBox();
QLineEdit* input = new QLineEdit(); QLineEdit* input = new QLineEdit();
match->addItem( "Similar To", Echonest::DynamicPlaylist::ArtistRadioType ); match->addItem( tr( "Similar To" ), Echonest::DynamicPlaylist::ArtistRadioType );
match->addItem( "Limit To", Echonest::DynamicPlaylist::ArtistType ); match->addItem( tr( "Limit To" ), Echonest::DynamicPlaylist::ArtistType );
m_matchString = match->currentText(); m_matchString = match->currentText();
m_matchData = match->itemData( match->currentIndex() ).toString(); m_matchData = match->itemData( match->currentIndex() ).toString();
input->setPlaceholderText( "Artist name" ); input->setPlaceholderText( tr( "Artist name" ) );
input->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed ); input->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed );
input->setCompleter( new QCompleter( QStringList(), input ) ); input->setCompleter( new QCompleter( QStringList(), input ) );
input->completer()->setCaseSensitivity( Qt::CaseInsensitive ); input->completer()->setCaseSensitivity( Qt::CaseInsensitive );
@@ -245,7 +245,7 @@ Tomahawk::EchonestControl::updateWidgets()
QLabel* match = new QLabel( tr( "similar to" ) ); QLabel* match = new QLabel( tr( "similar to" ) );
QLineEdit* input = new QLineEdit(); QLineEdit* input = new QLineEdit();
input->setPlaceholderText( "Enter any combination of song name and artist here..." ); input->setPlaceholderText( tr( "Enter any combination of song name and artist here..." ) );
m_matchString = QString(); m_matchString = QString();
m_matchData = QString::number( (int)Echonest::DynamicPlaylist::SongRadioType ); m_matchData = QString::number( (int)Echonest::DynamicPlaylist::SongRadioType );
@@ -361,14 +361,14 @@ Tomahawk::EchonestControl::updateWidgets()
{ {
m_currentType = Echonest::DynamicPlaylist::ArtistMinLatitude; m_currentType = Echonest::DynamicPlaylist::ArtistMinLatitude;
QString deg = QString( QChar( 0x00B0 ) ); QString deg = QString( QChar( 0x00B0 ) );
setupMinMaxWidgets( Echonest::DynamicPlaylist::ArtistMinLatitude, Echonest::DynamicPlaylist::ArtistMaxLatitude, QString( "-180%1" ).arg( deg ), QString( "180%1" ).arg( deg ), 180 ); setupMinMaxWidgets( Echonest::DynamicPlaylist::ArtistMinLatitude, Echonest::DynamicPlaylist::ArtistMaxLatitude, QString( tr( "-180%1" ) ).arg( deg ), QString( tr( "180%1" ) ).arg( deg ), 180 );
qobject_cast< LabeledSlider* >( m_input.data() )->slider()->setMinimum( -180 ); qobject_cast< LabeledSlider* >( m_input.data() )->slider()->setMinimum( -180 );
} }
else if( selectedType() == "Longitude" ) else if( selectedType() == "Longitude" )
{ {
m_currentType = Echonest::DynamicPlaylist::ArtistMinLongitude; m_currentType = Echonest::DynamicPlaylist::ArtistMinLongitude;
QString deg = QString( QChar( 0x00B0 ) ); QString deg = QString( QChar( 0x00B0 ) );
setupMinMaxWidgets( Echonest::DynamicPlaylist::ArtistMinLongitude, Echonest::DynamicPlaylist::ArtistMaxLongitude, QString( "-180%1" ).arg( deg ), QString( "180%1" ).arg( deg ), 180 ); setupMinMaxWidgets( Echonest::DynamicPlaylist::ArtistMinLongitude, Echonest::DynamicPlaylist::ArtistMaxLongitude, QString( tr( "-180%1" ) ).arg( deg ), QString( tr( "180%1" ) ).arg( deg ), 180 );
qobject_cast< LabeledSlider* >( m_input.data() )->slider()->setMinimum( -180 ); qobject_cast< LabeledSlider* >( m_input.data() )->slider()->setMinimum( -180 );
} }
else if( selectedType() == "Mode" ) else if( selectedType() == "Mode" )
@@ -494,11 +494,11 @@ Tomahawk::EchonestControl::updateWidgets()
match->addItem( tr( "is not" ), 0 ); match->addItem( tr( "is not" ), 0 );
QComboBox* combo = new QComboBox(); QComboBox* combo = new QComboBox();
combo->addItem( tr( "Studio" ), "studio" ); combo->addItem( tr( "Studio", "Song type: The song was recorded in a studio." ), "studio" );
combo->addItem( tr( "Live" ), "live" ); combo->addItem( tr( "Live", "Song type: The song was a life performance." ), "live" );
combo->addItem( tr( "Acoustic" ), "acoustic" ); combo->addItem( tr( "Acoustic", "Song type" ), "acoustic" );
combo->addItem( tr( "Electric" ), "electric" ); combo->addItem( tr( "Electric", "Song type" ), "electric" );
combo->addItem( tr( "Christmas" ), "christmas" ); combo->addItem( tr( "Christmas", "Song type: A christmas song" ), "christmas" );
connect( match, SIGNAL( activated( int ) ), this, SLOT( updateData() ) ); connect( match, SIGNAL( activated( int ) ), this, SLOT( updateData() ) );
connect( match, SIGNAL( activated( int ) ), this, SLOT( editingFinished() ) ); connect( match, SIGNAL( activated( int ) ), this, SLOT( editingFinished() ) );
@@ -525,8 +525,8 @@ void
Tomahawk::EchonestControl::setupMinMaxWidgets( Echonest::DynamicPlaylist::PlaylistParam min, Echonest::DynamicPlaylist::PlaylistParam max, const QString& leftL, const QString& rightL, int maxRange ) Tomahawk::EchonestControl::setupMinMaxWidgets( Echonest::DynamicPlaylist::PlaylistParam min, Echonest::DynamicPlaylist::PlaylistParam max, const QString& leftL, const QString& rightL, int maxRange )
{ {
QComboBox* match = new QComboBox; QComboBox* match = new QComboBox;
match->addItem( "At Least", min ); match->addItem( tr( "At Least" ), min );
match->addItem( "At Most", max ); match->addItem( tr( "At Most" ), max );
LabeledSlider* input = new LabeledSlider( leftL, rightL ); LabeledSlider* input = new LabeledSlider( leftL, rightL );
input->slider()->setRange( 0, maxRange ); input->slider()->setRange( 0, maxRange );

View File

@@ -71,9 +71,19 @@ EchonestFactory::createControl( const QString& controlType )
QStringList QStringList
EchonestFactory::typeSelectors() const EchonestFactory::typeSelectors() const
{ {
QStringList types = QStringList() << "Artist" << "Artist Description" << "User Radio" << "Song" << "Genre" << "Mood" << "Style" << "Adventurousness" << "Variety" << "Tempo" << "Duration" << "Loudness" // Using QT_TRANSLATE_NOOP here because this function should return the untranslated types
<< "Danceability" << "Energy" << "Artist Familiarity" << "Artist Hotttnesss" << "Song Hotttnesss" QStringList types = QStringList() << QT_TRANSLATE_NOOP( "Type selector", "Artist" ) << QT_TRANSLATE_NOOP( "Type selector", "Artist Description" )
<< "Longitude" << "Latitude" << "Mode" << "Key" << "Sorting" << "Song Type"; << QT_TRANSLATE_NOOP( "Type selector", "User Radio" ) << QT_TRANSLATE_NOOP( "Type selector", "Song" )
<< QT_TRANSLATE_NOOP( "Type selector", "Genre" ) << QT_TRANSLATE_NOOP( "Type selector", "Mood" )
<< QT_TRANSLATE_NOOP( "Type selector", "Style" ) << QT_TRANSLATE_NOOP( "Type selector", "Adventurousness" )
<< QT_TRANSLATE_NOOP( "Type selector", "Variety" ) << QT_TRANSLATE_NOOP( "Type selector", "Tempo" )
<< QT_TRANSLATE_NOOP( "Type selector", "Duration" ) << QT_TRANSLATE_NOOP( "Type selector", "Loudness" )
<< QT_TRANSLATE_NOOP( "Type selector", "Danceability" ) << QT_TRANSLATE_NOOP( "Type selector", "Energy" )
<< QT_TRANSLATE_NOOP( "Type selector", "Artist Familiarity" ) << QT_TRANSLATE_NOOP( "Type selector", "Artist Hotttnesss" )
<< QT_TRANSLATE_NOOP( "Type selector", "Song Hotttnesss" ) << QT_TRANSLATE_NOOP( "Type selector", "Longitude" )
<< QT_TRANSLATE_NOOP( "Type selector", "Latitude" ) << QT_TRANSLATE_NOOP( "Type selector", "Mode" )
<< QT_TRANSLATE_NOOP( "Type selector", "Key" ) << QT_TRANSLATE_NOOP( "Type selector", "Sorting" )
<< QT_TRANSLATE_NOOP( "Type selector", "Song Type" );
return types; return types;
} }
@@ -530,7 +540,7 @@ EchonestGenerator::sentenceSummary()
* and all Artist types must be the same. The filters aren't checked at the moment until Generate / Play is pressed. Consider doing a check on hide as well. * and all Artist types must be the same. The filters aren't checked at the moment until Generate / Play is pressed. Consider doing a check on hide as well.
*/ */
QList< dyncontrol_ptr > allcontrols = m_controls; QList< dyncontrol_ptr > allcontrols = m_controls;
QString sentence = "Songs "; QString sentence = QObject::tr( "Songs ", "Beginning of a sentence summary" );
/// 1. Collect all required filters /// 1. Collect all required filters
/// 2. Get the sorted by filter if it exists. /// 2. Get the sorted by filter if it exists.
@@ -559,7 +569,7 @@ EchonestGenerator::sentenceSummary()
/// If there are no artists and no filters, show some help text /// If there are no artists and no filters, show some help text
if( required.isEmpty() && allcontrols.isEmpty() ) if( required.isEmpty() && allcontrols.isEmpty() )
sentence = "No configured filters!"; sentence = QObject::tr( "No configured filters!" );
/// Do the assembling. Start with the artists if there are any, then do all the rest. /// Do the assembling. Start with the artists if there are any, then do all the rest.
for( int i = 0; i < required.size(); i++ ) { for( int i = 0; i < required.size(); i++ ) {
@@ -573,24 +583,24 @@ EchonestGenerator::sentenceSummary()
if( i == 0 ) { // if it's the first.. special casez if( i == 0 ) { // if it's the first.. special casez
center = summary.remove( "~" ); center = summary.remove( "~" );
if( required.size() == 2 ) // special case for 2, no comma. ( X and Y ) if( required.size() == 2 ) // special case for 2, no comma. ( X and Y )
suffix = " and "; suffix = QObject::tr( " and ", "Inserted between items in a list of two" );
else if( required.size() > 2 ) // in a list with more after else if( required.size() > 2 ) // in a list with more after
suffix = ", "; suffix = QObject::tr( ", ", "Inserted between items in a list" );
else if( allcontrols.isEmpty() && sorting.isNull() ) // the last one, and no more controls, so put a period else if( allcontrols.isEmpty() && sorting.isNull() ) // the last one, and no more controls, so put a period
suffix = "."; suffix = QObject::tr( ".", "Inserted when ending a sentence summary" );
else else
suffix = " "; suffix = " "; // shouldn't happen, but don't fail. it doesn't make sense to have this translatable
} else { } else {
center = summary.mid( summary.indexOf( "~" ) + 1 ); center = summary.mid( summary.indexOf( "~" ) + 1 );
if( i == required.size() - 1 ) { // if there are more, add an " and " if( i == required.size() - 1 ) { // if there are more, add an " and "
if( !( allcontrols.isEmpty() && sorting.isNull() ) ) if( !( allcontrols.isEmpty() && sorting.isNull() ) )
suffix = ", "; suffix = QObject::tr( ", ", "Inserted between items in a list" );
else else
suffix = "."; suffix = QObject::tr( ".", "Inserted when ending a sentence summary" );
} else if ( i < required.size() - 2 ) // An item in the list that is before the second to last one, don't use ", and", we only want that for the last item } else if ( i < required.size() - 2 ) // An item in the list that is before the second to last one, don't use ", and", we only want that for the last item
suffix += ", "; suffix += QObject::tr( ", ", "Inserted between items in a list" );
else else
suffix += ", and "; suffix += QObject::tr( ", and ", "Inserted between the last two items in a list of more than two" );
} }
sentence += center + suffix; sentence += center + suffix;
} }
@@ -601,15 +611,15 @@ EchonestGenerator::sentenceSummary()
QString prefix, suffix; QString prefix, suffix;
if( last ) { // only if there is not just 1 if( last ) { // only if there is not just 1
if( !( required.isEmpty() && allcontrols.size() == 1 ) ) if( !( required.isEmpty() && allcontrols.size() == 1 ) )
prefix = "and "; prefix = QObject::tr( "and ", "Inserted before the last item in a list" );
suffix = "."; suffix = QObject::tr( ".", "Inserted when ending a sentence summary" );
} else } else
suffix = ", "; suffix = QObject::tr( ", ", "Inserted between items in a list" );
sentence += prefix + allcontrols.value( i ).dynamicCast< EchonestControl >()->summary() + suffix; sentence += prefix + allcontrols.value( i ).dynamicCast< EchonestControl >()->summary() + suffix;
} }
if( !sorting.isNull() ) { if( !sorting.isNull() ) {
sentence += "and " + sorting.dynamicCast< EchonestControl >()->summary() + "."; sentence += QObject::tr( "and ", "Inserted before the sorting summary in a sentence summary" ) + sorting.dynamicCast< EchonestControl >()->summary() + QObject::tr( ".","Inserted when ending a sentence summary" );
} }
return sentence; return sentence;

View File

@@ -29,6 +29,7 @@
#include <QPaintEvent> #include <QPaintEvent>
#include <QPainter> #include <QPainter>
#include <QStackedLayout> #include <QStackedLayout>
#include <QApplication>
using namespace Tomahawk; using namespace Tomahawk;
@@ -57,17 +58,23 @@ DynamicControlWrapper::DynamicControlWrapper( const Tomahawk::dyncontrol_ptr& co
m_plusL->addWidget( m_minusButton ); m_plusL->addWidget( m_minusButton );
m_plusL->addWidget( createDummy( m_minusButton, m_parent ) ); // :-( m_plusL->addWidget( createDummy( m_minusButton, m_parent ) ); // :-(
connect( m_typeSelector, SIGNAL( activated( QString) ), SLOT( typeSelectorChanged( QString ) ) ); connect( m_typeSelector, SIGNAL( activated( int ) ), SLOT( typeSelectorChanged( int ) ) );
connect( m_control.data(), SIGNAL( changed() ), this, SIGNAL( changed() ) ); connect( m_control.data(), SIGNAL( changed() ), this, SIGNAL( changed() ) );
m_layout.data()->addWidget( m_typeSelector, row, 0, Qt::AlignLeft ); m_layout.data()->addWidget( m_typeSelector, row, 0, Qt::AlignLeft );
if( !control.isNull() ) { if( !control.isNull() ) {
foreach( const QString& type, control->typeSelectors() ) foreach( const QString& type, control->typeSelectors() )
m_typeSelector->addItem( type ); m_typeSelector->addItem( qApp->translate( "Type selector", type.toUtf8() ), type );
} }
typeSelectorChanged( m_control.isNull() ? "" : m_control->selectedType(), true );
int typeIndex = 0;
if ( !m_control.isNull() ) {
typeIndex = m_typeSelector->findData( m_control->selectedType() );
if (typeIndex == -1) typeIndex = 0;
}
typeSelectorChanged( typeIndex, true );
m_layout.data()->addLayout( m_plusL, m_row, 3, Qt::AlignCenter ); m_layout.data()->addLayout( m_plusL, m_row, 3, Qt::AlignCenter );
m_plusL->setCurrentIndex( 0 ); m_plusL->setCurrentIndex( 0 );
@@ -141,19 +148,20 @@ DynamicControlWrapper::createDummy( QWidget* fromW, QWidget* parent )
void void
DynamicControlWrapper::typeSelectorChanged( const QString& type, bool firstLoad ) DynamicControlWrapper::typeSelectorChanged( int typeIndex, bool firstLoad )
{ {
Q_ASSERT( !m_layout.isNull() ); Q_ASSERT( !m_layout.isNull() );
m_layout.data()->removeWidget( m_matchSelector.data() ); m_layout.data()->removeWidget( m_matchSelector.data() );
m_layout.data()->removeWidget( m_entryWidget.data() ); m_layout.data()->removeWidget( m_entryWidget.data() );
// Get the untranslated type name
QString type = m_typeSelector->itemData(typeIndex).toString();
if( m_control->selectedType() != type && !firstLoad ) if( m_control->selectedType() != type && !firstLoad )
m_control->setSelectedType( type ); m_control->setSelectedType( type );
int idx = m_typeSelector->findText( type ); m_typeSelector->setCurrentIndex( typeIndex );
if( idx > -1 )
m_typeSelector->setCurrentIndex( idx );
if( m_control->matchSelector() ) { if( m_control->matchSelector() ) {

View File

@@ -61,7 +61,7 @@ signals:
void changed(); void changed();
private slots: private slots:
void typeSelectorChanged( const QString& selectedType, bool firstLoad = false ); void typeSelectorChanged( int selectedTypeIndex, bool firstLoad = false );
private: private:
QWidget* m_parent; QWidget* m_parent;