Show an error message when switching to a language that isn't installed

Also, ensure that the language names are not translated in the menus
and messages, since they are already translated in the code.

Fixes https://gitlab.com/kicad/code/kicad/issues/5324
This commit is contained in:
Ian McInerney 2020-09-01 23:41:06 +01:00
parent 84fb024b9d
commit 8bdf25d3e2
6 changed files with 131 additions and 39 deletions

View File

@ -36,6 +36,7 @@
#include <settings/app_settings.h> #include <settings/app_settings.h>
#include <settings/common_settings.h> #include <settings/common_settings.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <pgm_base.h>
#include <project/project_local_settings.h> #include <project/project_local_settings.h>
#include <tool/action_manager.h> #include <tool/action_manager.h>
#include <tool/action_menu.h> #include <tool/action_menu.h>
@ -343,9 +344,6 @@ void EDA_BASE_FRAME::HandleUpdateUIEvent( wxUpdateUIEvent& aEvent, EDA_BASE_FRAM
} }
// Contained inside pgm_base.cpp
extern LANGUAGE_DESCR LanguagesList[];
void EDA_BASE_FRAME::setupUIConditions() void EDA_BASE_FRAME::setupUIConditions()
{ {
// Setup the conditions to check a language menu item // Setup the conditions to check a language menu item

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2014-2017 KiCad Developers, see CHANGELOG.TXT for contributors. * Copyright (C) 2014-2020 KiCad Developers, see CHANGELOG.TXT for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -32,6 +32,7 @@
#include <config.h> #include <config.h>
#include <id.h> #include <id.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <logging.h>
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
#include <wx/debug.h> #include <wx/debug.h>
@ -439,8 +440,39 @@ void KIWAY::ExpressMail( FRAME_T aDestination, MAIL_T aCommand, std::string& aPa
void KIWAY::SetLanguage( int aLanguage ) void KIWAY::SetLanguage( int aLanguage )
{ {
wxString errMsg;
bool ret = false;
{
// Only allow the traces to be logged by wx. We use our own system to log when the
// OS doesn't support the language, so we want to hide the wx error.
WX_LOG_TRACE_ONLY logtraceOnly;
Pgm().SetLanguageIdentifier( aLanguage ); Pgm().SetLanguageIdentifier( aLanguage );
Pgm().SetLanguage(); ret = Pgm().SetLanguage( errMsg );
}
if( !ret )
{
wxString lang;
for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
{
if( aLanguage == LanguagesList[ii].m_KI_Lang_Identifier )
{
if( LanguagesList[ii].m_DoNotTranslate )
lang = LanguagesList[ii].m_Lang_Label;
else
lang = wxGetTranslation( LanguagesList[ii].m_Lang_Label );
break;
}
}
DisplayErrorMessage( nullptr,
wxString::Format( _( "Unable to switch language to %s" ), lang ),
errMsg );
return;
}
#if 1 #if 1
// This is a risky hack that goes away if we allow the language to be // This is a risky hack that goes away if we allow the language to be

View File

@ -36,9 +36,7 @@
#include <tool/action_menu.h> #include <tool/action_menu.h>
#include <tool/conditional_menu.h> #include <tool/conditional_menu.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <pgm_base.h>
// Contained inside pgm_base.cpp
extern LANGUAGE_DESCR LanguagesList[];
/** /**
* Function AddMenuLanguageList * Function AddMenuLanguageList

View File

@ -72,23 +72,23 @@ LANGUAGE_DESCR LanguagesList[] =
{ {
{ wxLANGUAGE_DEFAULT, ID_LANGUAGE_DEFAULT, _( "Default" ), false }, { wxLANGUAGE_DEFAULT, ID_LANGUAGE_DEFAULT, _( "Default" ), false },
{ wxLANGUAGE_ENGLISH, ID_LANGUAGE_ENGLISH, wxT( "English" ), true }, { wxLANGUAGE_ENGLISH, ID_LANGUAGE_ENGLISH, wxT( "English" ), true },
{ wxLANGUAGE_FRENCH, ID_LANGUAGE_FRENCH, wxT( "Français" ), false }, { wxLANGUAGE_FRENCH, ID_LANGUAGE_FRENCH, wxT( "Français" ), true },
{ wxLANGUAGE_SPANISH, ID_LANGUAGE_SPANISH, wxT( "Español" ), false }, { wxLANGUAGE_SPANISH, ID_LANGUAGE_SPANISH, wxT( "Español" ), true },
{ wxLANGUAGE_PORTUGUESE, ID_LANGUAGE_PORTUGUESE, wxT( "Português" ),false }, { wxLANGUAGE_PORTUGUESE, ID_LANGUAGE_PORTUGUESE, wxT( "Português" ),true },
{ wxLANGUAGE_ITALIAN, ID_LANGUAGE_ITALIAN, wxT( "Italiano" ), false }, { wxLANGUAGE_ITALIAN, ID_LANGUAGE_ITALIAN, wxT( "Italiano" ), true },
{ wxLANGUAGE_GERMAN, ID_LANGUAGE_GERMAN, wxT( "Deutsch" ), false }, { wxLANGUAGE_GERMAN, ID_LANGUAGE_GERMAN, wxT( "Deutsch" ), true },
{ wxLANGUAGE_GREEK, ID_LANGUAGE_GREEK, wxT( "Ελληνικά" ), false }, { wxLANGUAGE_GREEK, ID_LANGUAGE_GREEK, wxT( "Ελληνικά" ), true },
{ wxLANGUAGE_HUNGARIAN, ID_LANGUAGE_HUNGARIAN, wxT( "Magyar" ), false }, { wxLANGUAGE_HUNGARIAN, ID_LANGUAGE_HUNGARIAN, wxT( "Magyar" ), true },
{ wxLANGUAGE_POLISH, ID_LANGUAGE_POLISH, wxT( "Polski" ), false }, { wxLANGUAGE_POLISH, ID_LANGUAGE_POLISH, wxT( "Polski" ), true },
{ wxLANGUAGE_CZECH, ID_LANGUAGE_CZECH, wxT( "Čeština" ), false }, { wxLANGUAGE_CZECH, ID_LANGUAGE_CZECH, wxT( "Čeština" ), true },
{ wxLANGUAGE_RUSSIAN, ID_LANGUAGE_RUSSIAN, wxT( "Русский" ), false }, { wxLANGUAGE_RUSSIAN, ID_LANGUAGE_RUSSIAN, wxT( "Русский" ), true },
{ wxLANGUAGE_CHINESE_SIMPLIFIED, ID_LANGUAGE_CHINESE_SIMPLIFIED, { wxLANGUAGE_CHINESE_SIMPLIFIED, ID_LANGUAGE_CHINESE_SIMPLIFIED,
wxT( "简体中文" ), false }, wxT( "简体中文" ), true },
{ wxLANGUAGE_CHINESE_TRADITIONAL, ID_LANGUAGE_CHINESE_TRADITIONAL, { wxLANGUAGE_CHINESE_TRADITIONAL, ID_LANGUAGE_CHINESE_TRADITIONAL,
wxT( "繁體中文" ), false }, wxT( "繁體中文" ), false },
{ wxLANGUAGE_CATALAN, ID_LANGUAGE_CATALAN, wxT( "Català" ), false }, { wxLANGUAGE_CATALAN, ID_LANGUAGE_CATALAN, wxT( "Català" ), true },
{ wxLANGUAGE_JAPANESE, ID_LANGUAGE_JAPANESE, wxT( "日本語" ), false }, { wxLANGUAGE_JAPANESE, ID_LANGUAGE_JAPANESE, wxT( "日本語" ), true },
{ wxLANGUAGE_LITHUANIAN, ID_LANGUAGE_LITHUANIAN, wxT( "Lietuvių" ), false }, { wxLANGUAGE_LITHUANIAN, ID_LANGUAGE_LITHUANIAN, wxT( "Lietuvių" ), true },
{ 0, 0, "", false } // Sentinel { 0, 0, "", false } // Sentinel
}; };
#undef _ #undef _
@ -434,7 +434,8 @@ bool PGM_BASE::InitPgm()
// Init user language *before* calling loadCommonSettings, because // Init user language *before* calling loadCommonSettings, because
// env vars could be incorrectly initialized on Linux // env vars could be incorrectly initialized on Linux
// (if the value contains some non ASCII7 chars, the env var is not initialized) // (if the value contains some non ASCII7 chars, the env var is not initialized)
SetLanguage( true ); wxString tmp;
SetLanguage( tmp, true );
loadCommonSettings(); loadCommonSettings();
@ -559,10 +560,8 @@ COMMON_SETTINGS* PGM_BASE::GetCommonSettings() const
} }
bool PGM_BASE::SetLanguage( bool first_time ) bool PGM_BASE::SetLanguage( wxString& aErrMsg, bool first_time )
{ {
bool retv = true;
if( first_time ) if( first_time )
{ {
setLanguageId( wxLANGUAGE_DEFAULT ); setLanguageId( wxLANGUAGE_DEFAULT );
@ -596,7 +595,9 @@ bool PGM_BASE::SetLanguage( bool first_time )
m_locale = new wxLocale; m_locale = new wxLocale;
m_locale->Init(); m_locale->Init();
retv = false;
aErrMsg = _( "This language is not supported by the operating system." );
return false;
} }
else if( !first_time ) else if( !first_time )
{ {
@ -636,18 +637,32 @@ bool PGM_BASE::SetLanguage( bool first_time )
double result; double result;
msg.ToDouble( &result ); msg.ToDouble( &result );
if( result != dtst )
// string to double encode/decode does not work! Bug detected: // string to double encode/decode does not work! Bug detected:
// Disable floating point localization: // Disable floating point localization:
if( result != dtst )
setlocale( LC_NUMERIC, "C" ); setlocale( LC_NUMERIC, "C" );
// Try adding the dictionary if it is not currently loaded
if( !m_locale->IsLoaded( dictionaryName ) ) if( !m_locale->IsLoaded( dictionaryName ) )
m_locale->AddCatalog( dictionaryName ); m_locale->AddCatalog( dictionaryName );
if( !retv ) // Verify the dictionary was loaded properly
return retv; if( !m_locale->IsLoaded( dictionaryName ) )
{
wxLogTrace( traceLocale, "Unable to load dictionary %s.mo in %s",
GetChars( dictionaryName ), GetChars( m_locale->GetName() ) );
return m_locale->IsOk(); setLanguageId( wxLANGUAGE_DEFAULT );
delete m_locale;
m_locale = new wxLocale;
m_locale->Init();
aErrMsg = _( "The KiCad language file for this language is not installed." );
return false;
}
return true;
} }

45
include/logging.h Normal file
View File

@ -0,0 +1,45 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 Ian McInerney <ian.s.mcinerney at ieee dot org>
* Copyright (C) 2020 KiCad Developers, see AUTHORS.TXT for contributors.
*
* This program 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 2
* of the License, or (at your option) any later version.
*
* This program 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 this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wx/log.h>
/**
* A logger class that filters out all log messages that are not generated by wxLogTrace
* and ignores them, while passing the trace messages onwards.
*/
class WX_LOG_TRACE_ONLY : public wxLogInterposerTemp
{
public:
WX_LOG_TRACE_ONLY() : wxLogInterposerTemp()
{
}
protected:
void DoLogRecord( wxLogLevel aLevel, const wxString& aMsg, const wxLogRecordInfo& aInfo ) override
{
// Only forward the message if it is a trace message
if( aLevel == wxLOG_Trace )
wxLogInterposerTemp::DoLogRecord( aLevel, aMsg, aInfo );
}
};

View File

@ -52,7 +52,7 @@ class SETTINGS_MANAGER;
* The locale translation is automatic. * The locale translation is automatic.
* The selection of languages is mainly for maintainer's convenience * The selection of languages is mainly for maintainer's convenience
* To add a support to a new translation: * To add a support to a new translation:
* add a new item to s_Languages[]. * add a new item to LanguagesList[].
*/ */
struct LANGUAGE_DESCR struct LANGUAGE_DESCR
{ {
@ -69,6 +69,10 @@ struct LANGUAGE_DESCR
bool m_DoNotTranslate; bool m_DoNotTranslate;
}; };
/**
* An array containing all the languages that KiCad supports.
*/
extern LANGUAGE_DESCR LanguagesList[];
// inter program module calling // inter program module calling
#define VTBL_ENTRY virtual #define VTBL_ENTRY virtual
@ -224,16 +228,16 @@ public:
VTBL_ENTRY void ForceSystemPdfBrowser( bool aFlg ) { m_use_system_pdf_browser = aFlg; } VTBL_ENTRY void ForceSystemPdfBrowser( bool aFlg ) { m_use_system_pdf_browser = aFlg; }
/** /**
* Function SetLanguage
* sets the dictionary file name for internationalization. * sets the dictionary file name for internationalization.
* <p> * <p>
* The files are in kicad/internat/xx or kicad/internat/xx_XX and are named kicad.mo * The files are in kicad/internat/xx or kicad/internat/xx_XX and are named kicad.mo
* </p> * </p>
* @param first_time must be set to true the first time this funct is * @param aErrMsg is the string to return the error message it
* @param first_time must be set to true the first time this function is
* called, false otherwise * called, false otherwise
* @return true if the language can be set (i.e. if the locale is available) * @return false if there was an error setting the language
*/ */
VTBL_ENTRY bool SetLanguage( bool first_time = false ); VTBL_ENTRY bool SetLanguage( wxString& aErrMsg, bool first_time = false );
/** /**
* Function SetLanguageIdentifier * Function SetLanguageIdentifier